I’m new to blender and bge, but am really liking it so far.
For the moment I’m trying to create a 3rd person camera and understand bge better in the process.
So here is my script that executes without problems, but the behavior is off:
import bge
distance = 4
controller = None
owner = None
scene = None
mouse = None
ACTIVE = bge.logic.KX_INPUT_ACTIVE
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
def init():
global controller
global owner
global scene
global mouse
controller = bge.logic.getCurrentController()
owner = controller.owner
#setting initial distance
owner.position.z = distance
#getting scene
scene = bge.logic.getCurrentScene()
scene.active_camera = owner
#getting mouse
mouse = bge.logic.mouse
def main():
print(distance)
#handeling zooming
zoom()
#api says that the local value is set
owner.position.z = distance
def zoom():
global distance
if(mouse.events[bge.events.WHEELUPMOUSE]==ACTIVE):
distance -= 1
#print(distance)
if(mouse.events[bge.events.WHEELDOWNMOUSE]==ACTIVE):
distance += 1
#print(distance)
init()
main()
So what I realized with this is that the entire script is executed if I connect it to an “Always” sensor.
Now I know this seems obvious, however my thinking was because of the tutorials and scripts that I have seen that only the main() function is executed. This might assumption could also have stemmed from my brief time with Unity3d.
Regardless, I consider getting the owner, controller, mouse etc every time kind of a waste even if the engine might handle it well enough. It just logically does not rub me the right way.
So my question is how can I have something like a init function that is executed only once on game start-up and/or game object creation.
I would also really appreciate it if the answer was script based. I find logic bricks really neat, but I find code easier to manage and understand.
Thanks for your time and I hope to be able to help others out as well once I start to get the hang of bge scripting.
edit: I am sorry to the moderator for posting this question twice, I did not properly read the redirection method where it is stated that every topic has to be approved and thought my post had not been submitted.
First of all, thank you for your quick reply.
I have tried it as described and it does work since now all that is outside a function only gets executed once, however the init function still gets called every frame.
So I removed all the init operations outside of a function and just call the main() from the module. This works and seems to avoid unnecessary variable assignments.
The cleaned up code now looks like this:
import bge
distance = 4
controller = None
owner = None
scene = None
mouse = None
ACTIVE = bge.logic.KX_INPUT_ACTIVE
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
controller = bge.logic.getCurrentController()
owner = controller.owner
#setting initial distance
owner.position.z = distance
#getting scene
scene = bge.logic.getCurrentScene()
scene.active_camera = owner
#getting mouse
mouse = bge.logic.mouse
print("Init finished")
def main():
#handeling zooming
zoom()
#api says that the local value is set
owner.position.z = distance
def zoom():
global distance
if(mouse.events[bge.events.WHEELUPMOUSE]==ACTIVE):
distance -= 1
if(mouse.events[bge.events.WHEELDOWNMOUSE]==ACTIVE):
distance += 1
So my final question on the subject is if this a good way to proceed?
First off welcome to the BGE. To start I don’t completely understand why you’ve written the lines ‘controller = none, owner = none’ etc. Maybe I’m misinterpreting what you’re trying to do but if you don’t want to give yourself a variable for controller or owner, you don’t have to write anything. The only reasons you see things like ‘controller = bge.logic.getCurrentController()’ written at the start of peoples scripts is purely personal choice. You don’t have to write anything at all, and do as you have done and define ‘controller’ later on in your script.
To do with your questions about execution. I understand what you mean about wanting to do everything from the script, but its not how the BGE works. You need a sensor to trigger your controller, since you have chosen your controller type to be a script obviously, then the script will be executed only when told to be by the sensor. An ‘always’ sensor is exactly that, it is always positive. However, your script will not be run on every frame because your controller will not be run again until a negative pulse is sent from the sensor, which won’t happen of course because the sensor is always positive. This means the script will be run on the very first logic tic of your game, then never again. If you want your script to be run on every frame, click the true pulse triggering (button that looks like ‘’’) on your always sensor. This means your controller, in this case your script, will be triggered to run by the sensor on every frame that the sensor is positive on, which will be for the entire game, again, because always sensors don’t go negative.
To do with your question about the main() function being the only one run. I could be wrong from here on because I’ve only just started digging into module mode myself, but from what I understand this isn’t the case. In a ‘Python’ controller you’ve got a drop-down menu with 2 options, script execution mode, and module execution mode. If you’ve selected script mode, your entire script will be run when triggered by the sensor. In module mode, you can run certain functions only. For instance, if you have a script called ‘myScript.py’ in the text editor, and you have 2 functions in the script, ‘main’ and ‘doStuff’. You can make the controller run only one of these two by naming it in the ‘module to be run’ field, e.g. ‘myScript.main’ or ‘myScript.doStuff’. So really a main function isn’t needed at all.