Code may not be 100% accurate, it is for example only
I’m tired from writing several external python scripts to make future projects easier, and in the process I learned some things.
- Blender shares data, a lot of data.
If you have ever tried to change the textures on objects that use the same material, or change vertex colors on two copies of the same object, you may have noticed that both objects have the same changes (even if you just did it for one). When using addObject, each object has separate object data, but share mesh and material data, this makes it easy to change the textures on a group of objects with the same material (like trees), but makes some tasks a bit more daunting. This allows blender to reduce overhead, which is good, but you should be careful of how you write your scripts.
- using the four lines, or any blender-specific modules, at the top of an external script is a bad idea.
(importing any modules at the top of external scripts is probably a bad idea, yet I do it all the time)
The four lines are as follows, and are usually the first four lines in any bge script.
import bge
logic = bge.logic
cont = logic.getCurrentController()
own = cont.owner
They import the bge and allow quick access to the logic sub-module, current controller the script is on, and the object the script is on. From this you have a large degree of access to manipulate the game engine.
Four whole lines, and some actions take as many or more lines to accomplish. So the idea to write external modules is a good one, but may take some planning.
Let’s look at an external module.
import bge
logic = bge.logic
cont = logic.getCurrentController()
own = cont.owner
def colorChange(color):
own.color = color
Not very impressive, but it will do, it is also wrong. If you put this in an external .py file, import it, and use the module (assuming you passed it a legitimate color); it will work. Then how is it wrong? I believed that the internal script would be evaluated (/run) for each object independently so that each object has different data pointers even if they are using the same script, or are copies of the same object. When you use an external script any lines not inside a function/module might be held as (scriptName.variablename), thus sharing data, and actions across objects. The colorChange module will work, but subsequent objects will have the same colors (either the first or the last object to use the script will set the color for everyone). I noticed this when I was asking for different sensors with objects using the same modules, the first object found it’s sensor, but not the other sensor.
Here is a little better script:
def colorChange(color):
import bge
logic = bge.logic
cont = logic.getCurrentController()
own = cont.owner
own.color = color
This will work, but is superfluous. It is better to just pass the color, and the owner like this:
def colorChange(own, color):
own.color = color
I don’t think that importing modules like “random” at the top of an external script would hurt anything, but it is better to import the modules you need in the modules/functions that are going to use them. Like this:
def colorChange(own):
import random
r = random.randrange(1,100)/100
g = random.randrange(1,100)/100
b = random.randrange(1,100)/100
own.color = (r,g,b,1.0)
tip : object color channels should be between 0.0 and 1.0, but can be any real number, this over saturates (or oversouls) the color channels, try it for some neat effects and colors beyond imagining.
- You can’t directly pass anything using the python module controller.
The python controller has an option to just use an external module, but it has to be in the format of (script.module), no parenthesis or braces, so let’s look at a good example script to use in the python module controller.
def colorChange():
import bge
logic = bge.logic
cont = logic.getCurrentController()
own = cont.owner
color = (own["red"], own["green"], own["blue"], 1.0)
own.color = color
As you can see, we are passing the colors via properties, but you can just randomly generate them, or use a list.
If this was in a file named color.py the text in the python module controller would be (color.colorChange).
As you noticed, the four lines are in the module/function and can be used on separate objects. You could probably knock the four lines to two if you just need the owner.
#Tip : the string property can hold more than just strings, I’ve placed lists, dictionaries, vertex arrays, and material textures into them from python. I’m not sure if you can just write a list into them, but if it doesn’t work there is always eval().
This is just a bit of what I have learned through trial and error, and I hope it helps someone avoid these mistakes and write code a bit more efficiently. Code re-writes and modifications are no fun.