Python Tutorial: How to script in the BGE

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:

image

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, but in a way that sound like your mom is asking you to do some chore Y or Z. 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 currently running controller.
# The BGE executes each controller one after the other, but boy it's fast.
controller = bge.logic.getCurrentController()

# Controller "objects" (in Python) have a property named ".owner" that
# refers to the object owning the currently running 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.

Maybe a lot to read, but at least they explain a bunch of things, you don’t have to rush…
https://www.techbeamers.com/python-tutorial-step-by-step/

And I mean, maybe Google explains better than me:
https://developers.google.com/edu/python/set-up

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

Important!

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:

  • Windows:

    In Blender, click on Window > Toggle Console.

  • Linux/Mac:

    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 :slight_smile:

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 bge.logic module:
https://docs.blender.org/api/2.79/bge.logic.html

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.

Example:

I want to know how to move a cube

Ok, so we go on the documentation main page:
https://docs.blender.org/api/2.79/#game-engine-modules

Hmm, no idea in which module to look, so just use the search: "bge move"
https://docs.blender.org/api/2.79/search.html?q=bge+move

We can see a bunch of links, but if you look closely, there’s something interesting:

So, then let’s go check it out:
https://docs.blender.org/api/2.79/bge.types.KX_GameObject.html?highlight=bge%20move#bge.types.KX_GameObject.applyMovement

And now you can just read what are the parameters, what is the return value (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 .blend file.

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 .py to 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 :stuck_out_tongue:

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”:

image

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 script_folder.script_1.controller_function.

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 scripts/controllers.py:

# 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:

image

Note: I don’t know why the textbox is so small, but I wrote: scripts.controllers.rotate

What now?

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
  • Put print('apwoidoasiwjdosjfe') at strategic points in your code to see what goes wrong and what goes right (it happens).
  • Despair.

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 :anger:

Programming is mostly a game of patience and perseverance.

Good luck!

14 Likes

NOOB reaction inbound WHAHA, it just prints that text :frowning:

Jokes aside, damn good guide/start/explanation/wall of text :smiley: .

1 Like

Ahah, thanks :smiley:

Was a bit afraid once done that it was all for nothing…

But we’ll see, maybe someone will find it useful.

1 Like

Thank you for tutorial!

1 Like

great answer. Should be the start of a wiki ? You can also add a note of something Veeeery usefull in a python code :

print(' do you see this in the terminal ??') :eyes:

edit : oops didn’t saw this

1 Like

Thanks for the effort!

This is a good starting point for beginners, for sure. Two suggestions for improvement:

  • A hint about the actual used Python (System vs. Blenders) on different OS would be helpful.
  • You could add a section “How to import new modules” via pip, this would fit in here very well, I think.
1 Like

Hey, thanks for the feedback!

I think both of these are rather advanced concepts, while I was more targeting newcomers-ish.


But just so that I can double check with you what I know so far on both subjects you mentioned:

This depends on the build you install on your machine IIUC: On Windows it will use a bundled Python always. On Linux it will often use the system Python when installed through some system package, while if you download a build distributed with a bundled Python then it will use that.

One example is my case: I am running Ubuntu 16.04 and my system Python should be 3.5, although UPBGE ships with 3.6, so the build I downloaded was bundling this version. But when I install Blender through apt install blender, then this install will use my system Python, because this is the way the package is made.

It can be confusing…


Again, to do it right it requires some advanced concepts in my opinion.

Easy way

Find the Python executable used by your Blender install, and run

<blender-python> -m pip install <package>

Issue: This will install everything directly in your Blender installation (or system!), but if you are like me and you are working on multiple projects, maybe each will require a different set of packages to be installed, leading to conflicts. This method will work until at some point your Blender Python installation will become too polluted by random packages installed left and right in the long run.

Proper way

To avoid the issue mentioned right above, the use of Python Virtualenvs is strongly recommended.

But a problem with this method is that neither Blender nor the BGE are designed to run using one…

So, few things to do:

# set cwd to your project
cd "/your/blender/project"

# install `virtualenv` globally (do once) to create venvs
<system-python> -m pip install virtualenv

# install a utility package globally (do once) I made to make Blender/BGE use a virtualenv
<system-python> -m pip install pypath-setup

# create a virtualenv for your project using Blender's Python
# (or System's Python, depends on which your Blender uses)
<system-python> -m virtualenv -p "/path/to/blender/python/exe" <venv-name>

# start Blender and have it use the virtualenv
pypath-setup --venv <path-to-your-venv> <blender-or-player> <file>.blend

Most of this setup are “do onces”, like installing virtualenv and pypath-setup, but then for each project you need to create a virtualenv, and then you need to start Blender inside it.

Not really beginner-friendly.


Did I miss something?

+sources for pypath-setup in case you wonder what it does:
https://github.com/marechal-p/pypath-setup/blob/master/pypath_setup/__init__.py

Awesome! :slight_smile:
That is actually content which should have been in the official documentation.

1 Like

Which official documentation?

Also, what I described is only my way of doing things with virtual environments. Really would like more feedback, as it might not be as easy as it should. Maybe an addon could be made to automate this?

I mean the official documentation in the 2.79 manual on blender.org

There is so much good content in this forum, but unfortunately hidden in this flat structure without subtopics. Just imagine what would have happened if all the good stuff has not ended up hidden here been exposed directly on blenders main website…

With my 2.79b version of blender, I get

"Import Error : No module named ‘bge’

What is the last version of Blender that supports the GE ?

2.79b still has the BGE embedded.

How did you run your script?

  1. In a text window enter :

import bge

Then either
a) “hover mouse in text window” , press alt-p

or

b) Press the run script button.

  • Make sure the render is set to Blender Game
  • Hover the mouse on 3D View and press P
  • Or press Start Game Engine on the Game menu
  • Or press Start on the Render tab

the run script button is for bpy scripts that does something in the 3dview, like moving an object with bpy, or to test addons. It’s not to run bge scripts.

To run a script, select an object add:
always-> python(select your script)

Now hover over 3dview and press P to start the engine and the script will be executed.

I’m not evven sure why we need to explain this, it’s already explained in the OP.

Ok, thanks, the script is working when I actually run the game engine :slight_smile:

Well it’s been “awhile” since I last used the game engine.

I thought that I (“remembered”) an “Alt-p” would run “game engine” code, regardless if the game engine was running.

But maybe not :slight_smile:

Thank you for this tutorial i am just getting started at coding and this is really helpful resource explained really well. thanks again :slight_smile: