Might seem obvious but I can’t figure it out. I have an Armature that plays an action when a key is pressed. I want another action to play when that action ends. How can I trigger an action to play when another action ends on the same Armature in Python. Thanks everyone.
if you need another action when the current action is completed or the frames of the current action have reproduced the animations you need, you can always switch to new ones - you need to get the armature frames and write conditions or logical bricks and compare the frame property -
arm[‘frame’] = arm.getActionFrame()
if arm[‘frame’] in range (50, 60):
arm.playAction(“New_Action”, 70, 100, blendin=5, layer =0)
I would advice getting the name of the currently playing action, than cross-check to see if the current frame has reached a stated frame value yet:
Imagine the demo has 2 animations, one called Anim_1, and another called Anim_2. When one action reaches it's stated end, Python will run the other action, and vice-versa in a infinite loop. (If so desired, you can tweak the code yourself)
import bge END_FRAME_1 = 30 END_FRAME_2 = 60 def main(self): # Anim_1 if self.owner.getActionName() == "Anim_1": if self.owner.getActionFrame() == 30: self.owner.playAction("Anim_2", 0, 60) # Anim_2 elif self.owner.getActionName() == "Anim_2": if self.owner.getActionFrame() == 60: self.owner.playAction("Anim_1", 0, 30)
Thanks for the answers so far. The script is like this. How could I make Animation4 play after Animation1 is completed?
from collections import OrderedDict
from mathutils import Vector
c = bge.logic.getCurrentController()
owner = c.owner
key = bge.logic.keyboard.events
ms = bge.logic.mouse.events
W = key[bge.events.WKEY]
LMB = ms[bge.events.LEFTMOUSE]
arm = owner.children.get(‘GameRig’)
frame = arm.getActionFrame()
action = arm.getActionName()
blendin = 2
arm.playAction(‘Animation1’, 1, 60, blendin = blendin, speed = 1.5)
blendin = 2
arm.playAction(‘Animation2’, 1, 60, blendin = blendin)
blendin = 2
arm.playAction(‘Animation3’, 1, 60, blendin = blendin, priority = 1)
Thanks for the help everyone.
you need get frames from animation number1 and get name animation1 and create a block of conditions that will check its completion
if arm.getActionName()==‘Animation1’ and arm[‘frames’] in range (59, 60):
arm.playAction(“Animation4”, 0, 60, blendin=5, layer=0)
I do not recommend setting specific numbers of animation frames and comparing them since these frames are skipped very often and it is better to compare the frame range since this always works. And remember one more thing - if you use animation layers, you need to specify the layer number at the end of the line in parentheses when receiving frames, otherwise it will be equal to 0 arm[‘frames’] = arm.getActionFrame(1) #1 for first layer frames if play more layers animation
Hey thanks. I know this is probably basic but I am a complete noob at scripting. I get the error
KeyError: ‘value = gameOb[key]: KX_GameObject, key “frames” does not exist’
you need create property - ‘frames’ for armature - for assign numbers in property
Ok. Thank you. I created a property called frames and if I put the property number in the range it skips the first animation and goes straight to the second. Any ideas?
You need setup range frame action - if you animation use 60 frame need stand range in 59-60, animation work to 59 and triggered new animation, if you select long range, trigger start not right. Remember - if all animations end need assign to frames property 0 because script save last play frame and this make errors
Thanks. Still not working for some reason. Not sure what I am missing. I tried a property on the armature and the controller each. I tried integer and float both set to 0. Animation is 60 frames, range is 59-60. I get the first animation but not the second. If I set the the property to 59 I get the second animation and not the first. Not sure what I am doing wrong. Thanks for the help.
I should probably also have mentioned I am using Blender 2.79 and not UPBGE if that makes a difference. Sorry for any confusion. Thanks
Guess I used up all my tech support lol. If I find a solution that works for me I will post up. Thanks to everyone who attempted to help.
You could play each animation on a different layer and use
isPlayingAction(layer) to check if the action is being played.
You would need a property that you toggle when Animation1 is played.
Animation1_Layer = 1 if W: blendin = 2 arm.playAction(‘Animation1’, 1, 60, layer = Animation1_Layer, blendin = blendin, speed = 1.5) arm['Animation1started'] = True elif arm['Animation1started'] and not arm.isPlayingAction(Animation1_Layer): # Animation1started is true but no Action is being played on the Animation1 layer means that the action ended arm['Animation1started'] = False # play animation 4