I have seen a similar thread posted somewhere before but for some reason i cant find it. Heres my situation:
I have an enemy. Here are the things he does:
My question is…should I make 3 different python controllers for each individual script? Or should I “mash” the 3 scripts together and have the new script run on just one python controller? Which way is more optimized?
ok. That leads me to another related question. Is there a specific reason for putting my method definitions and IF statements into a main()? I say this because right now as I have it, I just have my statements and methods “out in the open” that arent enclosed in a main function and it works fine. What are the benifits of enclosing my script in a main()? Is a reason for doing so because it prevents all of my peripheral scripts from running all the time, which saves computational power?
from bge import render, logic
from mathutils import Vector # for easy editing of Vectors
distance = 1.5 # the distance of the ray
object = cont.owner
# Create the lists
objectProps = object.getPropertyNames()
polyIndex = 
#polyRayCastId =  | I didn't actually use this list
# initiate x to 0
x = 0
# Check the objects properties
for prop in objectProps:
# Look for Properties that have "FaceProperty" in them
if "FaceProperty" in prop:
# increment x
x = x + 1
# Look for Properties that have "FaceIndex" in them
if 'FaceIndex' in prop:
# if "polyData" is present in the object then this wont run
if not 'polyData' in object:
mesh = object.meshes
CalcMeshData(mesh) # I just moved these calculations to a function so it was easier to read the code
transform = object.worldTransform
polyData = object['polyData']
hostID = object['hostID']
# this loops through the indexes we collected earlier
for item in polyValues:
# Check to see if the property needs to send data
if object[polyProperties[item]] != "Empty" and object[polyProperties[item]] != None:
# loops through the mesh data
for data in polyData:
id = int(data[-2:])
if 'FaceIndex' in data:
String = str(data)
String2 = int(String.split("_"))
#if the current FaceIndex is equal to the mesh Id then it casts a ray
if object[polyIndex[item]] == id:
start = Vector(transform * data)
end = Vector(transform * (data + data))
render.drawLine(start, end, [255, 0, 0])
hitOb, _, _, hitPoly = object.rayCast(end, start, 0, '', 0, 0, 1)
# if the ray hits another object,
# it gets the face id and gives it the data
hitMat = hitPoly.material_name
if 'Sensor_' in hitMat:
hitID = int(hitMat.split("_"))
hitOb['hostID'] = hitID
if hitID < 10:
hitOb["FaceProperty_0%s" % (hitID)] = object[polyProperties[item]]
hitOb["FaceProperty_%s" % (hitID)] = object[polyProperties[item]]
object[polyProperties[item]] = "Empty"
object['hostID'] = 0
object.state = 1
# I just made this a function so I could read the code better
polyData = 
# loops through all the polygons in the mesh
for polyId in range(mesh.numPolygons):
poly = mesh.getPolygon(polyId)
polyMat = poly.material_name
# is the polygons material name cantains "Sensor_"
if 'Sensor_' in polyMat:
matID = poly.material_id
numVerts = poly.getNumVertex()
coords = Vector((0, 0, 0))
normalList = 
totalNormal = Vector([0,0,0])
# Loops through all the vertices in the polygon
for vertIndex in range(numVerts):
vert = mesh.getVertex(matID, vertIndex)
coords += vert.XYZ
# adds all the vertex normals together
for n in normalList:
totalNormal += n
# averages out the normal and applies the distance
polyNormal = (totalNormal / len(normalList)) * distance
# averages out the position
polyPos = coords / numVerts
# adds the data to the list
polyData.append([polyMat, polyPos, polyNormal])
# assigns the list to a property on the object
logic.getCurrentController().owner['polyData'] = polyData
I prefer to have one module running on an object. The advantage is that you have less logic bricks which makes the logic more portable. If you wanted to make a different mesh have the same behavior as your current object, you just add 1 Always sensor and 1 Python controller and you are done. If you have them separate then you have to duplicate the logic bricks in the new object.
ok well i combined all of my modules together into a main(). However, my framerate seems to have droped since the change…is executing one long python script the reason why my game is now running slower?
I’m no real programmer so I’m not quite there yet to tell you what the best approach should be. I’ll give my impression though. Hope someone will correct me if I’m wrong. I think the way to organize things depends on weighing functionalities. By spreading the code over multiple scripts you get more transparency and enables you to recycle, which I found to be useful, especially when dealing with a lot of data. For example, by importing modules from a script with general functions I don’t have to have the same code multiple times. Also with libraries I found it useful to have them separately. In that case I don’t mind if it’s costing a little bit in performance (which I doubt will be much).
But for the rest you want the code to be as efficient as possible. And I think it’s more efficient to have just one script for one type of game object if you need access to all modules from a main function. But also avoid running a script more than necessary, because most of the time processing through Python will be more expensive than processing through logic bricks. For example, better to check a property with a Property Sensor to activate a script instead of checking a Property by running a script all the time. And better switch to other states when scripts have had their purpose. For example, when an enemy died and his body only serves as a decoration to the scene. So accessing all modules from a main function can be effective, but in some cases it’s better to access the modules of the same script through different controllers, making use of states.
“when an enemy died and his body only serves as a decoration to the scene”…lolol. But yea, I believe raco has point. But here is my latest situation:
I found out that the reason for my framerate drop was that I had a keyboard sensor with true pulse enabled which significantly lowered my framerate depending on how many of my enemies I spawned in the scene. I know this discussion has veered away from the name of this thread, but I have a new question. I believe Kastoria made a reference that certain sensors slow down your framerate more than others. Specificly, “mouse over”, “radar”, “near”, and “collision” sensors.
My question is is it good practice, in the situation of spawning multiple carbon copy enemies, to have as few of these sensors as possible running with so many instances of the enemy running at the same time? Especially when these sensors have true pulse enabled?
p.s. I will soon combine my now optimized scripts together into 1 working module and tell you guys if my problem has been resolved.
Yes, it is good practice to have as few sensors on your objects as you can. From a logic brick standpoint, it is easy to put a mouse-over sensor on every object that you want to detect a mouse hover on. However, lots of those sensors will take a lot of logic time so you are better off using a single, mouse-over-any sensor and having all the objects check that one. I’m not sure if it is possible to do that trick with just logic bricks.
Sometimes you cannot avoid it. If you need to test if an enemy had a collision with something in the environment, then there is no way to get around having a collision sensor on each guy.
if you use script mode with one single block of text , you have to have one single controller that trigger the script:
you can have many sensor but only one controller python ,
using more controller and one single script is possible using statement of sensor as fake entry point but the script is read more times in the same frame and do a work useless in the best case
if you want use more controller and one big script you have to use modules
A) “main” is used as entry point when stating a pure Python application. As the BGE is no Python application there is no such entry point. You see it as you have to call main() from own code. In a real Python application you never do that.
B) “main” is a very generic name. It does not provide any information (except the information mentioned in A) which is irrelevant in the BGE). Imagine this as somebody is calling you “human”. This is right but not helpful. Better choose a name with a meaning: e.g. moveForward().
C) “main” needs to be called after defining this function. This forces the reader to scroll to the end of the code just to see how it begins. This is like reading a novel starting with the last page. So it is not really a good idea.
Script mode - choose a name of the file that describes what the complete code does
Module mode - choose a name of the file that categorizes the callable methods of the module - choose names of the function that describe what the functions do.
Back to the real question:
One big module or a few modules:
If the code belongs together it makes sense to place them into the same container (module/package)
If the code has no or weak relationship it makes sense to place them in separate containers.
As usually there is a large gray area in this topic. You need to decide by yourself.
You can use the internal state system.
Only sensors connected to active states are evaluated. (This means the other sensors are not evaluated and do not eat processing time)
This is a good way to deactivate heavy sensors.