Python Tutorial: How to script in the BGE
(Not-so-)quick introduction to Python scripting on the BGE.
There are quite some things to go through, my bad… But it is not that hard, be brave!
Logic Brick: Python Controller
A Python controller is basically a logic brick that you can program using Python scripts.
If you look at how a controller usually behaves, they do pretty simple things:
- AND Controller: When all connected sensors are positive, activate all connected actuators.
- OR Controller: When one of the connected sensors is positive, activate all connected actuators.
- NAND Controller: When no connected sensor is positive, activate all connected actuators.
- XOR Controller: When only one of the connected sensors is positive, activate all … etc.
These are all basic logic gates, but what if you want more control?
Test if a sensor is positive, and actually check some values from it?
That’s when you use a Python controller:
Important: You need at least one sensor connected to the controller in order to trigger it!
It can be anything, but the trigger comes from a sensor…
Now to write a script you just open Blender’s text editor, and you can start writing your first script.
So, little bit of disclaimer: When people see programs they usually go “that’s so hacker, it is too complex”.
But fear not: Programs are meant to be written using English words, a bit like a recipe! It is a simple list of instructions to get from a state A to a state B.
import bge # the module to interact with the Blender Game Engine # When this script gets executed by a controller (when it will be its turn) # the following variable will point to the current running controller. # The BGE executes each controller one after the other, but boy is it fast. controller = bge.logic.getCurrentController() # Controller "objects" (in Python) have a property named ".owner" that # refers to the object owning the currently running controller. # This is because this script can be shared by different Python controllers # attached to other objects. Since we will run multiple times in a different context, # this line allows us to figure out what object is currently running the controller! owner = controller.owner # In this example, let's do something silly, and move the cube up owner.worldPosition.z += 0.1 # Let's make it turn too owner.applyRotation([0, 0, 0.1]) # [x, y, z]
Lot of comments in this code, but if you read the code word by word, usually it is pretty easy to understand what is going to happen once the Python controller will execute it!
I don’t know Python to begin with…
Ah, maybe worth trying to play with Python on the side, at least to cover the basics.
edit: Looking back at the link I posted I think there are better resources out there, it’s just a bit difficult to find the “right” one. But I managed to find the following which essentially looks amazing to me (make sure to go through the different chapters!)
I’ll leave the other ones up, but I’d recommend the one above
Maybe a lot to read, but at least they explain a bunch of things, you don’t have to rush…
And I mean, maybe Google explains better than me:
Just pick your poison. Take your time to read, really.
If you go through with it, you’ll be ready to try your new spells on the BGE!
How to see what failed
When you will write your scripts, most of the time you will make a typo, or call the wrong method, or do something silly that I cannot describe yet, so it is important that you know where to look for errors:
In Blender, click on Window > Toggle Console.
Open Blender from a terminal.
In both case you will have some kind of terminal/console where the errors will be displayed.
What you are looking for are messages like:
Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined
The error message is very important, in this case it tells me:
NameError: name 'a' is not defined
So this is helping me because I thought I had defined some
a variable, turns out I didn’t…
The stuff above the message is a stack trace, it mostly tells you from where the error comes from:
Traceback (most recent call last): File "<stdin>", line 1, in <module>
In this case I was running Python as a standalone program in my terminal, so it says that the file is
"<stdin>", that just means that it comes from me typing junk in the console. When running BGE scripts it will tell you which file of yours caused the exception, and what line to look at.
In the beginning you might have a lot of
SyntaxError, for these the stack is your enemy: It will say there is an error on some X line, but in reality the error comes from earlier in the code, where you forgot a parenthesis or something.
Don’t focus day and night on the displayed line, maybe it comes from elsewhere
Where to find each function and variable for Python in the BGE?
In the above example, I used a bunch of words and you might wonder how in hell are you supposed to know exactly what to write.
Fairly enough, there’s a good documentation that basically just list such functions and variables and everything for BGE scripts: https://docs.blender.org/api/2.79/#game-engine-modules
But if you don’t really know where to start, it is a bit much to ask you to read.
But oh well, you can start by reading the introduction for the
They kind of explain a lot what you are supposed to do with it.
The process of reading such a documentation is simply to sit down and browse links that have names that sound like the thing you are looking for.
I want to know how to move a cube
Ok, so we go on the documentation main page:
Hmm, no idea in which module to look, so just use the search:
We can see a bunch of links, but if you look closely, there’s something interesting:
So, then let’s go check it out:
And now you can just read what the parameters are, what the return value is (if any), etc…
You can do more searches if some things are not clear, like how do we pass a vector? In this case I will help you a bit: it comes from the module
mathutils which holds all mathematical objects used by the BGE in Python.
But there’s a trick as most functions in the BGE that expect a vector as parameter can also take a list of 3 elements, like:
i_am_a_list = [0, 1, 2] object.applyMovement(i_am_a_list)
From there it’s primarily trial and error, just try things and keep searching the docs!
Using Python modules from your disk
Ok, one important part of scripting on the BGE, is to keep your code organized, somehow…
The Blender Text Editor is fine to learn and tinker, but you will certainly prefer using a better editor, like I don’t know, Notepad++, Atom, VS Code, or whatever it is you like writing Python with!
But in order to use such editors that aren’t part of Blender, the Python scripts need to be files on your disk, that means somewhere near your
Usually, to be able to import scripts inside Blender, your files must be located next to your file:
- game_folder/ - game.blend - script_1.py - script_2.py - ...
Important: The files must end with
.pyto be considered scripts/modules!
This way, you can import your scripts as modules doing:
import script_1 a = script_1.some_function(b, c, d, ...)
You can also place your scripts in a folder:
- game_folder/ - game.blend - script_folder/ - script_1.py - script_2.py - ...
Then, you must access your scripts as:
from script_folder import script_1 script_1.something(...)
Once you start doing that, life becomes better, because the Blender Text Editor simply sucks
Calling module functions directly from a Python Controller
The next step in Python scripting on the BGE is to define your custom controller logic not as a full script, but as a function from a module.
When you use Python Controller, they expect a file from the Text Editors, but once you start making modules you don’t want to store things inside Blender, as everything is already outside, on your disk.
Fortunately, the BGE allows you to point to a function inside one of your module, you just need to change the Python Controller mode from “Script” to “Module”:
Once that is done, the text box will not show you available scripts to use, because in Python there is no real way of knowing what module or what function is meant to be used in the BGE.
So you will have to write the import line yourself!
It works just like we saw modules working a bit above this section: Scripts/modules must be next to your blend, and the path is something like
You must refer to a function inside the module now, because functions are executable bits of code, and that’s what the BGE is now looking for.
Ok, as an example, imagine a controller function
rotate inside the file
# I just write this comment to help you: # File is: "scripts/controllers.py" def rotate(controller): ''' This is just a function comment in Python (docstring) Here, when the BGE will call the function, the Python Controller will pass itself as the first argument, no need for `bge.logic.getCurrentController()`! ''' owner = controller.owner owner.applyRotation([0, 0, 0.1])
And now, we just write the Python import string inside the Python Controller:
Note: I don’t know why the textbox is so small, but I wrote:
Well, welcome in the world of “how am I supposed to program this MMORPG?”.
You are ready to do like all programmers do:
- Read documentation, in search of functions that do something that can help you do the bigger thing.
- Write algorithms that are slow and trying to find what makes it slow
print('apwoidoasiwjdosjfe')at strategic points in your code to see what goes wrong and what goes right (it happens).
Just know that thanks to the BGE running Python, you can do a LOT of things. In my case I was able to begin making an online game!
Is it easy though? No. Well, you have to know a big bunch of different things about Python, processes, network, etc… But I didn’t learn everything in one day, I learned writing a lot of stupid scripts, reading a lot of documentation, and spending a lot of time just despairing in front of my code that wasn’t working, just to see a stupid typo in some variable name
Programming is mostly a game of patience and perseverance.