1
$\begingroup$

In my game i need a way to delay a script for x amount of seconds. Generally I would use the following...

import time
time.sleep(x)

but when I use this Blender decides to crash. Is there any other delays I can use that will not crash Blender or is there something wrong with the way I am using sleep?

$\endgroup$
5
$\begingroup$

Blender doesn't crash and you don't use it wrong. Because the BGE has only one thread you stop it for x seconds. So never use time.sleep(x) in BGE. What you can do instead is using a delay sensor, timer property or a variable that increments every frame. Here's an example for the last option that's probably the easiest one to do (taken from this thread from Blenderartists):

obj = cont.owner

if not 'init' in obj:
    obj['init'] = 1
    obj['timer'] = 0.0

obj['timer'] += 1.0 / logic.getLogicTicRate()

if obj['timer'] > 10: # 10 seconds
    #Do something

It basically just creates a property in your object and increases it every time the script is executed. If your script is executed every logic tick the property will count in seconds.

But you need to keep in mind that since you don't stop your script as it is but it starts over from the start every time it's called, all your variables defined like var = None will be gone (or have a new value). Meaning that if you have any variables you still need after delaying the script you'll have to store it either in your object (obj['var'] = None) or in the globalDict (bge.logic.globalDict['var'] = None).

The way you want it is that the script gets activated by a sensor and waits for a rotation to finish to apply a movement. What you can do is executing the script over and over again until then time is up and the executing the remaining part. And that's quite simple. Just add a property to your object (for example a property called execute). I guess the boolean type would fit the best for that so we'll use that one. Then add a property sensor, select your property, use the value True and activate True Level Triggering. Now the script gets executed when either the collision sensor or the property sensor or both are true. Now the property execute still needs to be controlled from the script. Therefore the lines obj['execute'] = True and obj['execute'] = True are needed. And the property obj['timer'] needs a reset after it's over 10 (in the example script) as well. obj['timer'] = 0.0 does the trick. And don't forget to import the logic module. Otherwise it's undefined and you'll get errors.

That's the full script:

from bge import logic
    obj = cont.owner

    if not 'init' in obj:
        obj['init'] = 1
        obj['timer'] = 0.0

    obj['timer'] += 1.0 / logic.getLogicTicRate()
    obj['execute'] = True # due to this the property sensor gets activated every logic tick and the script gets executed every logic tick.

    if obj['timer'] > 10: # 10 seconds
        obj['execute'] = False # now it doesn't get executed every logic tick
        obj['timer'] = 0.0 # reset the timer so that it can be used again
        #Do something

And here's the described logic brick setup: logic brick setup

$\endgroup$
  • $\begingroup$ but i can only have the script run once. so i can't have the property increase every time the script is run. the effect i am trying to create here is a car ramming a alien and when the car hits the alien hits the car it triggers a collision sensor and activates this code. the reason i want a delay is because when the collision sensor is activated the code applys a rotation. after the rotation i want it to delay and then after x seconds applysMovement. sorry $\endgroup$ – gamer103 Aug 29 '16 at 21:27
  • $\begingroup$ There's no way of doing that without executing the script over and over again. You can't delay a script itself, only it's execution. The only way to delay the script and go on executing it would be time.sleep(x), but as I wrote it stops the whole game. It's like telling the game that it doesn't have to do anything for x seconds. And because it doesn't have to do anything it doesn't even draw a frame. But the way you want it is still possible with the way I suggested. I'll update my answer soon. $\endgroup$ – palkonimo Aug 30 '16 at 16:53
  • $\begingroup$ Whenever I run the code it gives me this: NameError: name ‘logic’ is not defined: The line it is referring to is 23 on which I have the following line of code: obj['timer'] += 1.0 / logic.getLogicTicRate() is there something I have to import to get logic or something? $\endgroup$ – gamer103 Sep 1 '16 at 22:00
  • $\begingroup$ logic is the bge logic module, so you need to import it first. Use from bge import logic. You can of course just import the bge module (import bge) and put bge in front of every logic in the script too. Whatever you like more $\endgroup$ – palkonimo Sep 2 '16 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.