['Help Please']: rewriting BGE Python into c#

Hello! I have built a prototype game in Blender Game Engine using Python to make the modules. I am interested in learning how to take python things I normally do and turn them into c# for Unity.

First question: I have these modules in my game:

-battle_functions.py
-battle_script_.py

-hud_script_.py
-hud_module.py

-player_movement.py
-fighter_class.py
-module for each monster.py

-world_functions.py
-world_script.py
-camera_functions.py

Is it safe to say that each of these modules will directly translate into a c# script? Because of Monobehaviour Update(), I think I can consolidate, for example, hud_script_ into hud_module.


I am going to give you an example function from my BGE turn based RPG game’s battle_functions.py module
Please rewrite this, or explain how to rewrite in c#. I think it would help me start to understand where to begin in rewriting the code.

#this is not within a python class, it is just a function in a module

def get_target_obj(target):

    target_obj = [ob for ob in logic.getSceneList()[0].objects if 'battleID' in ob and ob['battleID'] == target]   

    if check_confused(get_actor_obj()) == True: 

        new_target = random.choice(get_battler())
        return new_target
    else:
        return target_obj[0]

If anyone has any resources for Python —> C#, please share them!

use code tags:

This is especially important with python, since python is whitespace sensitive…

Tagged

I don’t think you’re likely to find anyone with the time to rewrite entire functions for you. Do you already know C#? If not, then start with that. There are many good C# tutorials on the net.

def get_target_obj(target):
    target_obj = [ob for ob in logic.getSceneList()[0].objects if 'battleID' in ob and ob['battleID'] == target]

    if check_confused(get_actor_obj()) == True:
        new_target = random.choice(get_battler())
        return new_target
    else:
        return target_obj[0]

As for converting this to C#…

well, first off you need to contend with the fact that the API is different now. You’re in Unity, so there are different classes and methods that do things. There also might not be classes or methods that do a thing that can be done in Blender.

Furthermore, I don’t know the types of any of the code there, or where some of those functions are… so I don’t know what they’d be if I converted it.

Like what is this line doing?

target_obj = [ob for ob in logic.getSceneList()[0].objects if 'battleID' in ob and ob['battleID'] == target]

What is ‘logic’?
What is getSceneList()?
what is the significance of ‘battleID’?
what does ob[‘battleID’] return, and how does it correlate to ‘target’?

In the rest of the code there’s more we know nothing about…

What is ‘check_confused’?
What is ‘get_actor_obj’?
What is ‘get_battler’?

Without that information, the most I could do is say:

//I have no idea what type 'target' is, nor what type type the object returned is
public TargetType GetTargetObj(TargetType target)
{
    var target_objs = *whatever your code was supposed to do*; //I assume this results in some array

    //presuming these 2 functions get defined somewhere
    if(check_confused(get_actor_obj()))
    {
        var battlers = get_battler(); //assuming this returns an array of battlers, and that the method is defined
        return battlers[Random.Range(0, battlers.Length - 1)];
    }
    else
    {
        return target_objs[0];
    }
}

But I mean honestly… that just is syntactically changing your existing code.

This is hardly going to be much help to you unless you learn C#.

Well, that shows what I know! :slight_smile:

Yeah, converting what is convertible of that code is like 5 seconds work (I spent more time typing the text of my response).

But it’s still useless… none of the methods that are called are defined in the Unity API.

Like ‘get_actor’… I’m assuming this is a accessor (property) of the ‘actor’ that the class is attached to… sort of like the gameObject property of a component. But I don’t know… it’s not defined… I’ve never used the blender API.

Blender Game Engine and Unity are not compatible - you can’t just translate the script from python to C# and go. You’ll need to transform everything that has to do with the engine as well.

@lordofduct
This syntax, tho:

target_obj = [ob for ob in logic.getSceneList()[0].objects if 'battleID' in ob and ob['battleID'] == target]

From the little python I remember, that’s a filter. So the C# equivalent would be, approximately, through Linq

var target_obj = from ob in logic.getSceneList() where ob.Contains("battleID" && ob["battleID"] == target select ob;

So yeah.

oh the syntax of it I get (I do write python for my day job)… it’s just that the majority of the things they were doing in it were undocumented specific to their needs that converting it was pointless… it would have been even more gibberish than the rest of the code I wrote. So I just omitted it.

First, thanks for the reply.
I feel like I might be asking more than is appropriate, so yeah no offense taken if it’s just not possible. I’ll just have to start from the ground up
@Baste thank you for the reply as well

It’s funny because I had a whole post explaining all of that and I was like 'nah I’ll just post the function as it is without any explanation and deleted it.

logic is the class from which all other classes are derived (like Unity’s Monobehavior I gather)

getSceneList() collects all of the scenes within the game project. In blender you use one scene overlayed on another to make the HUD, so getSceneList()[0] would be where the 3D transforms, characters, etc are stored while getSceneList()[1] would be the HUD where cursors, menu objects, etc are stored.

I think transforms are 3D objects, empties, etc in Unity so that’s how I’ll be using the term in the following:

‘battleID’ is a string variable that is given to each transform that takes a turn in battle
ob[‘battleID’] returns the string of the battleID. the [‘’] in python show that it is a dictionary key. properties are stored in a dictionary within the game object and called game properties when the user wants them to be easily accesible from an editor like window in the BGE

so if ob[‘battleID’] == target is just saying, the argument target is equal to the variable battleID’s string

As for the functions,
because there is no module_name as the first element in the sequence,( e.g. “check_confused()” a single element sequence), it means that they are functions defined in the same module as the function that is calling them.

Here are some straight forward questions


By curiosity is,starting with a python script with a bunch of functions inside, if I have a c# script with ‘the same’ bunch of functions inside, does each of those functions need its own class?
**If I reference some function within the c# script in another function in that same script, what would that look like?

I have attempted this approach for a start. But I could not found the python nor C# in the language lists.

So question,

what are you asking?

Are you asking for how to write C#?

Or are you asking how you’d implement this design in Unity?

Because both are completely different questions.

ahh… haha

I think your example code that you posted before is basically what I wanted to see.

So I got another question!

In my BGE game, there is a script that basically is the Awake() in Monobehavior. It runs before all else and runs just once. In this script I create BGE logic’s equivalent of variables (dictionary keys) that I want to mutate and reference throughout game play.

For example a list (which can contain any type, combination of objects)

gd[‘player_1_inputs’] = [ ]

This list stores player input.

If I wanted to do something similar in c#, would this work?

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


namespace Awake
{
    public class _Awake : MonoBehaviour
    {
        void Awake(){
            var current_camPosition = new Vector3 (0, 0, 0);
            var original_camPosition = new Vector3(0, 0, 0,);

            int gold = 0;
            string current_level;
            var last_worldPosition = new Vector3(0, 0, 0);

            float a0001_fatigue = 0;
            float a0002_fatigue = 0;
            float a0003_fatigue = 0;
            float a0004_fatigue = 0;

            string previous_field_element;
            string current_field_element;
            string creature_group;

            List<List<string>> action_queue = new List<List<string>>();
            List<List<string>> unsorted_initiatives = new List<List<string>>();
            List<List<string>> sorted_initiatives = new List<List<string>>();

            string current_day;
            List<List<string>> week_days = new List<List<string>>();
            week_days.Add(new List<string> { "Fireday", "Waterday","Earthday","Airday" });

            List<List<string>> global_inputs = new List<List<string>>();

            List<List<string>> a0001_inputs = new List<List<string>>();
            List<List<string>> a0002_inputs = new List<List<string>>();
            List<List<string>> a0003_inputs = new List<List<string>>();
            List<List<string>> a0004_inputs = new List<List<string>>();

            bool a0001_complete;
            bool a0002_complete;
            bool a0003_complete;
            bool a0004_complete;



       

    }
}

No, that wouldn’t work the way you want it to because you’ve just created a bunch of local variables. At the end of the method, they go poof.

You probably want to declare those as fields instead (after “public class… {” but before the first method).

Thanks @JoeStrout ! That is exactly what I wanted. Of course, what you said is closer to what I have in my python module in the first place and I just misinterpreted it. :slight_smile:

New question:

The way I am using variables is by making a ton of public ones on the main camera, and then referencing them using this:

GameObject MainCam = GameObject.Find ("MainCam");
_Awake awake = MainCam.GetComponent<_Awake>();

Which I learned from here:

When I put the above code outside of a function, it becomes un-highlighted which I assume implies that it is no longer in a valid place.

However, I really don’t want to keep writing that over and over again. Is there a way to write the above code just once somewhere in each script I need it in?

Also, glad to say that this translation is going much more smoothly than anticipated :smile:


Second Question:

With BGE Python, because variable names are dictionary keys which are strings, I can make a loop like this:

for( i in range(1,5))
    {
        current_fatigue = float(gd['a000'+str(i)+'_fatigue_counter']); //a000(1-5)_fatigue_counter is a string of the variable name of a float in this context
        new_fatigue = current_fatigue + .2;
        gd['a000'+str(i)+'_fatigue_counter'] = str(new_fatigue);
    }

Which is looping through float variables and setting their values by way of the string of their name. How can I do something like this in c#?

(I guess writing variable+=2, however many times in this case would technically be about as long, but still)

Just figured I’d throw a random translation up for those interested to see how it looks. Haven’t tested any of them yet, I’m going to do it all at once instead of piece-meal, so we’ll see how it continues:

        public void after_random_encounter_defeat()
        {
            GameObject MainCam = GameObject.Find ("MainCam");
            _Awake awake = MainCam.GetComponent<_Awake>();

            //logic.sendMessage('reset_battle_hud','','','CameraHUD');
            remove_undefeated_enemies();
            GameObject battle_level = GameObject.Find (awake.current_battle_level);
            GameObject.Destroy (battle_level);
            awake.current_level = awake.last_inn;
            GameObject inn = GameObject.Instantiate (Resources.Load (awake.current_level));
            GameObject current_char = GameObject.Find (awake.current_char);
            current_char.transform.position = inn.transform.position + new Vector3 (0, 0, 4);
            unfaint_members ();


        }

def after_random_encounter_defeat()
{

    logic.sendMessage('reset_battle_hud','','','CameraHUD');
    remove_undefeated_enemies();
    logic.getSceneList()[0].objects[gd['currentlevel']+'_battle'].endObject();
    gd['currentlevel'] = gd['last_inn'];
    logic.getSceneList()[0].addObject(gd['currentlevel'],'AssetsLevelSpawn',0);
    logic.getSceneList()[0].objects[gd['current_char']].worldPosition = logic.getSceneList()[0].objects[gd['last_inn']].worldPosition + Vector([10,4,4]);
    unfaint_members();
}