Automatically reload external Python files

I need to move from using logic blocks to Python, but I’m not getting along with the internal text editor, and would like to use an external tool for editing the code. This makes for a horrible work flow since I have to manually reload my .py files every time I’ve made a change. Rapid iteration is essential if I’m ever going to get to grips with UPBGE programming - how can this be achieved?

AFAIK an external text is just refererenced… so you don’t have to reload… it’s just used…

That would be nice, but making a change in an external file and saving it does not update the value used by UPBGE - I have to go into the Blender text editor and reload the file for that to happen.

Check this manual sub-chapter. You have to use python controller-module and press the ‘D’
https://upbge.org/docs/latest/manual/manual/python/introduction.html#debug-your-game-while-it-runs

Yes indeed i just checked (dummy me should had this doen first)… but if called from another ?? Does blender relly don’t have a automatic change detection?? (too few scripting in blender; do programming elsewhere)

Ups ist just tell you it’s edited (the questionmark icon)…

Yeah, I’ve already read that - it’s a little different to what I’m after. Firstly, I am overriding the main game loop (the scene property “__main__” is set to my main.py file), so there is no Python module to load. Secondly, module debug reloads the file on every frame, which affects performance. I just want external assets to be checked for changes and reloaded if necessary when the game engine is started.

It does have that - a life preserver icon appears bottom left in the text editor when the file has been changed outside Blender, but you have to click it to decide what to do with the changes every time:

Screenshot_2022-05-31_17-29-43

If only there was an option to say “always do this without asking”…

Is an Always sensor with true-pulse enabled not sufficient enough?
If you’re not using it because you’d rather not use 1 frame for initializing in the same script as a infinite frame script, you can actually do both calculations in the same script.

import bge

def main(self):

  if self.sensors["Always"].status == 1:
    # Runs only 1 frame like with "tap" enabled and "true-pulse" disabled
  if self.sensors["Always"].status == 2:
    # Runs infinitely like with "true-pulse" enabled

Note: You do need true-pulse enabled for your sensor that is running the script.

I’m not using logic blocks because I’m not sure they’re a good fit for my use case, which is somewhat unusual: I have an existing Python program which controls a load of real world hardware including RGB LEDs, video playback on a screen, button inputs and relay outputs. It’s not super complex, but now I want this code (basically a state machine) to also control the state of a Blender animation, adding and animating objects in the 3D space based on real world inputs and in sync with all the other bits. For this reason I assumed the best route would be to take control over main.py and put my existing code in there. However, I am very new to UPBGE and it is quite likely that I’ve misunderstood something. Logic blocks feel too object specific (the object is the “owner”) for putting the overarching code into (since you cannot add logic blocks to the scene or the world, only to individual objects in the scene).

Edit: There is, for obvious reasons (I’m not making a game in the traditional sense), scant information to be found on the Internet on how to best achieve what I’m after. I am now almost a week into what I thought would be relatively simple project and my stress level is getting quite high - if anyone has any helpful pointers these would be very welcome.

As an alternative, is there a way to instantiate “blenderplayer” from Python, get it to load my scene and access the objects within the scene? I only really need to be able to show/hide objects, trigger “actions” on them (i.e. animations) and control the frame counters of those actions.

if there are folders or files in the directory of the blend, things can be imported simply.

say you have py file named “game.py” with a function def main():. you can use module mode to point right to the function, and whats cool is everything not in a function gets run only the first time the py file is loaded.

a python module block with “game.main” will run the main function. script mode shouldnt be used normally. if the “game.py” is in a folder called “PY”, just add another dot level “PY.game.main”

This sounds genuinely useful, but I have a few questions:

  1. Since modules have to be attached to an object, and that object cannot be the scene itself, how do I decide where “god level” code lives? There ought to be a natural place for the code that controls all the other code to go, but other than __main__ I don’t know where that might be.

  2. Will this deliver the reload-automatically-when-edited-externally functionality I was asking for, and if so, why? Using the debug “D” switch does not do this; it reloads the code on every frame, which is not desirable since it will reset any local variables.

Right, so the file gets evaluated at start, and any functions in it become callable. This is basically a Python import statement.

I have no idea what you mean, could you please elaborate? What is “script mode”?

script mode runs a text block like a function. bth im not sure exactly how it works, but its only good for little background things that are blend specific.

my “god” object is just an empty with a python module block. simple as that. you need to remember this isnt your typical game engine, its a logic loop tacked onto a 3d modeling program. things are not gonna be prim-and-proper, theres no real one way to do things. do what works for the need. like python, blender scenes can be freely manipulated (no read-only flags) during runtime, just know what your god object and be sure you dont mess with it.

1 Like

I found a (somewhat brutal) solution, by moving my code to a new file created outside UPBGE and replacing the contents of main.py with

import bge
import os

filename = os.path.join(os.path.dirname(bge.logic.expandPath("//")), "mypython.py")
exec(compile(open(filename).read(), filename, "exec"))

Restarting the game preview with Esc and “P” reloads the contents of mypython.py every time

1 Like

there is no real difference in performance when it comes to module and script mode.

In case anyone else is unsure of what exactly are the differences between script vs. module:

That is if you have small scripts, if over 1000 lines of code modules are better and faster, due to python is already a slow language.

differences are actually pretty simple:

Script:

  • python reads complete script(all lines of code) every time it get’s called
  • script is only usable on 1 object, every other object will overwrite the “properties/variables”

Module:

  • script/code get’s only read when the module/function is being called, on init it will only read the funtion names/lines " def abcdefg(cont): " and not the code that is within that function.
  • module mode can be used on infinite objects instead of only one.
  • modules/functions can be used multiple times in a “.py file” so less repeated code needed, simply call the function instead.

That’s the basics.

module mode is not faster than script mode, it is just a different way of writing code, the python interpreter and your CPU sets the speed.

BGE/UPBGE only support single core threading, so having a stronger CPU doesn’t mean your game runs faster necessarily. Although the animations in UPBGE 0.3+ I believe are multi-threaded, with the exception of nonexistent GPU skinning.

i where not talking about multi treading, but just the core clock speed, a CPU that runs a 5Ghz is still faster than one that runs 1Ghz.