A simple question: is it possible to see in what order scripts execute? I know about the priority flag and that you should avoid dependencies, but I sometimes find it a bit of a grey area. Example:
I have an object that creates a bge.logic.globalDict entry, and a text object uses this to display the text in the dict. Now, to begin with I would get key errors (as the text object runs its script before the generating object). I created a third object that has the priority flag set, establish the dict and it works fine (no key errors).
The crazy Voodoo part is this: if I duplicate the first object that generates the dict, delete the original (so the copy is the last object created in the scene) the system works fine without the third object at all. No explanation, just Voodoo magic.
It would be lovely if we could shuffle the Python scripts so we could set what executes in what order. Is it possible? Or does it make for sloppy scripting?
I don’t think you can set individual priorities, but it’s easy to avoid the situation you’re talking about.
Say your globaDict entry is called [“text_info”]. You want to load the text info before trying to display it.
You need an extra line of code in your text object:
if "text_info" in bge.logic.globalDict:
own['Text'] = bge.logic.globalDict["text_info"]
Now you can let the code run anytime.
You can also add an [‘initializations’] dictionary to globalDict (a dictionary can contain other dictionaries) so:
if "navigation_ini" in bge.logic.globalDict["initializations"]:
do_some_navigation()
###
if "inventory_ini" in bge.logic.globalDict["initializations"]:
open_inventory()
###
if "enemy_ini" in bge.logic.globalDict["initializations"]:
spawn_enemy(location,number,gold)
That way you can make sure you’re not trying to run a script before it’s dependencies have initialized. Of course you should avoid dependencies but there will be some no matter what you do, you just have to make sure you handle them correctly.
I tried it but got some very strange results. First an extra window popped up, full of stuff I’ve been working on this afternoon, but unconnected with the current blend.
I assume it’s some kind of stuff from an image/render buffer or something. The window is just called “Blender”.
It’s not part of any currently open Blend, I was working on it a few hours ago.
Simple answer: write the behavior in a way that it does not rely on the execution of other code -> no need to know the order.
Ask yourself: Why do I get key errors? Answer - “as the text object runs its script before the generating object”
Unfortunately this is not the truth. The text object relies on an input that is not present.
Ask yourself: Why does the text object relies on this object? Why it can’t deal with the situation this object is not present? Obviously this is a common situation.
possible solution: if the configuration is not present, use a default value:
Ah, the demo itself doesn’t include the example functions -> They’re just generic print statements at the moment.
The principle is this;
A controller set to module mode can be executed using the lookup trick with a module name like so “priority.queue(“printer2”, 1)”, which will queue a function called “printer2” to be executed at the end of the frame. This is technically incorrect because it is running the next frame (after the render update of the current frame), but it’s just a POC after all.
You’d define a function called “printer2” in the same module, and it would need to accept the argument “cont”. The second argument is the evaluation priority-> lower numbers are visited first.
When I talk about initialization I mean some scripts have a set up phase that they need to run through before being ready. For example if you have procedurally generated terrain you need to get and store navigation data after adding the terrain objects to the scene.
I usually use states to control this:
State1: generate terrain.
state2: get navigation data and render minimap.
state3: add player and enemies.
state4: run game.
each script ends with a command to change to the next state. You can get other objects in the scene or other scenes and change them from an inactive state (no logic bricks in that state) to an active one. I usually do that at the end of initialization.
This is a very complex processing. Similar to loading a save point from file, it deserves a complete frame for processing (as it effects the visible objects too). The simplest solution is to start with a blocked camera and remove the block (black plane) within the first frame. This way the “vision” and the “normal” processing starts with frame 2.
Indeed this requires that the “components” do not rely on each other in frame 0 (here we are back to avoid dependency).
Yes, during the first three states everything in the scene is essentially on pause, because it is set to a state with no logic bricks. Then before switching to state 4 I go through all the objects and switch their state to 1 (the active state).
Sometimes I leave them in an inactive state until they are a certain distance from the player. This can save on processing time while the inactive agents are too far away to have any impact on the player’s game. Other times I have an empty set as a spawn point, which can spawn an agent when the player comes close enough.
I also often use this method for setting up UI elements, so that I can add boxes or options dynamically and lay them out with mathematical precision.
In any case I don’t switch things over to an active state until all the initialization is done. Therefore there can be no break in dependence. As such it’s not really necessary for me to have a method in the globalDict, but there are times when it can be useful.
Using ob.get() is always a good idea by the way, Monster is 100% right there.