Python/Script delay

I have been trying to figure out how to delay .addObject. When a key stroke executes an animation I am trying to instantiate hitboxes from a separate layer. The issue is I want the hitbox to popup X tics after the key press depending on which animation is done. So if the animation is 30 frames, I only want the hitbox to be active from frame 12 to frame 18 of the 30 frame animation for example. Deactivating the hitbox on frame 18 is simple but delaying its activation is proving difficult with scripting. I tried a few scripts i found while searching but have yet to find something that works.
Thanks everyone.

On the animation actuator, one of the settings on it lets you pick a property to update with the current animation frame.

Then, hook up a property sensor that activates when the property is over frame 12 and hook it up to your addObject actuator.

1 Like

Thank you for the reply. I have found ways to do it with logic bricks, but i was looking for a way to do it with scripting. Particular some code i could add to my existing player control script. But even a separate script i could put on the empty that the object gets added to would be fine. Thanks again.

In that case, you’ll probably want to make yourself a scheduler. Keep a variable that represents the current frame number and increment it every frame. Then, keep a list of events to happen and action them on the matching frames.

You can even store functions in the list, so your scheduler could call the function you supply it.

e.g. your event list might look like this:
[[65, myFunc, (“first argument”, myObjReference)],
[76, myOtherFunct, ()]]

armature[‘frame’] = armature.getActionFrame(0) in this function “armature” its variable and number zero action layer layer need select equivalent layer play action, frame its property, and if you need get frames or individual frame number or numbers range you get armature[‘frame’] property and use in script

Thank you. I am a bit new to python and scripting in general. Here is a simple code I made that does the basic concept of what I need done except for the delay part.

import bge

scene = bge.logic.getCurrentScene()
ob= bge.logic.getCurrentController().owner
emp = scene.objects[“Empty”]

key = bge.logic.keyboard.events

W = key[bge.events.WKEY]

if W:
ob1 = scene.addObject(“Sphere”, ob, 50)
emp = scene.addObject(“Cylinder”, emp, 75)

I was just testing adding objects from another layer to both the main object and to an empty parented to the main object. The number 50 tells how long the added objects will live which is great. I was just looking to put something like this

if W:
delay 10 frames with fancy code stuff:
ob1 = scene.addObject(“Sphere”, ob, 50)

or even some way to add the delay as a number to the add.Object like this

if W:
ob1 = scene.addObject(“Sphere”, ob, 10 frames delay, 50 frames delete)

I know thats not how the scripts work and thats not the right syntax or whatever but thats how I see what I need in my head if that makes any sense.

Thanks again everyone.

Edit: Didn’t realize posting would get rid of the indentations but you get the point.

If I needed to solve that problem then I’d probably just spawn an empty which waits for 10 frames, then spawns the second object and kills itself. Or, if I didn’t need to spawn more than one thing at a time, I’d use a timer property and property sensors.

If you really want to do this with Python, then you’re looking at some kind of solution that involves tracking frame counts. Or, like Villi89 said, keep checking the animation frame until it reaches the desired level and then spawn your object.


def test(cont):
    
    own = cont.owner
    
    start_frame = 12
    end_frame = 18
    
    
    armature = own.scene.objects('armature_name')
    action_layer = 0
    animation_frame = armature.getActionFrame(action_layer)
    
    if animation_frame == start_frame:
        
        if not 'added' in own:
            added_obj = own.scene.addObject('obj_to_add', 'spawn_location', 'duration')
            own['added'] = added_obj
            
    elif animation_frame > end_frame: 
                   
        if own['added']:  
            own['added'].endObject()
            del own['added'] 
            

The spawn an empty that spawns the hitbox concept is something I didn’t think about. I tried the concept quickly but didn’t get it to work. Any idea what a script like that would look like? Thank you.

Thanks I will give that a try

import bge
from bge import logic
scene = bge.logic.getCurrentScene()

own = cont.owner
arm = scene.objects[‘Armature’]

arm[‘frames’] = arm.getActionFrame(0) # get play action frame layer number zero
arm.playAction(“Somebody_Actions”, 0, 100, blendin=5, layer=0)

if arm[‘frames’] in range(0, 10):
x1 = scene.addObject(“Cube”, own, 0)
elif arm[‘frames’] in range(11, 30):
x2 = scene.addObject(“Sphere”, own, 100)
elif arm[‘frames’]>=30:
bge.logic.endGame()
Just get action frame in you armature and use in script getting frames data numbers for add objects, play new animation, delete objects or translate message in objects or scenes. Use logic constructions if - elif - else for variations logic and you see this is simply and very good for you projects - Good luck for you

Ahhh yes if you need checking numbers range use " if x in range(0,10) " or anymore numbers or low numbers, and standart equal, not equal, more or low range, just remember equals numbers checking not everyone work good if engine framerate stand in 50 or 60 frame per second or more - maybe mades situation how script not see number and jumping to next number and ignoring need number, i recommend use checking “x in range(0, 100)” or “x>=100” or " x<=100 ". I hope you create all scripts right

That won’t work
it wil basically add the cube like 12 times

1 Like

yes off course, you right because range numbers add objects or run somebody 10 once until the received frames go beyond this range, so you need to specify a more precise value of something like x in range(9,10) and force the counter to be updated when the condition x in range is true

Just an update. I probably should have mentioned I was working in BGE 2.79. So anybody interested, these solutions may work in UPBGE, but I haven’t found anything that works in Blender BGE 2.79. There is also the possibility that some of these things may work but I do not have the knowledge to implement them. So if anyone comes looking with a similar problem, some of this information may be relavant. If I find a solution that works for me I will share it. Thank you everyone.

All suggestions suggested here works in 2.79 or upbge

Why doesn’t it work, well probably due to you arent parenting the spawned object to the armature, so the spawned object stays at the location you have spawned it.

def test(cont):
    
    own = cont.owner
    
    start_frame = 12
    end_frame = 18
    
    
    armature = own.scene.objects('armature_name')
    action_layer = 0
    animation_frame = armature.getActionFrame(action_layer)
    
    if animation_frame == start_frame:
        
        if not 'added' in own:
            added_obj = own.scene.addObject('obj_to_add', 'spawn_location', 'duration')
            added_object.setParent(armature)
            own['added'] = added_obj
            
    elif animation_frame > end_frame: 
                   
        if 'added' in own and own['added']:  
            own['added'].removeParent()
            own['added'].endObject()
            del own['added']