I have finally taken the plunge and started to learn about actions and the action logic brick within Blender, but I have come across an odd problem.
I have a simple setup. A cube has an action (a basic up/ down movement) and I want to adjust the speed of the animation using a property. It seems simple enough, but unmodified the cube will stop its animation until the property stops changing.
With some research, I came across two forum posts that talk about using setActionFrame() but when I try this the animation goes from being smooth to very jerky.
What am I doing wrong? I’ve attached a blend that has the setup I am experimenting with. Just press space to increase the property that should speed up the action. I’ve commented out where I think setActionFrame() should go.
As a workaround, I can control the animation speed a little by changing the always sensors pulse rate, but I would really love to know how to do this properly.
Can anyone help?
ActionProblem.blend (444 KB)
First at all, you dont need Action brik at all, if you use playAction().
So, rid Action brik away
and next lines froms script.
Set ipoFlags to zero (I don’t know how these work,But another numbers dont work)
Now You can drive your animations without logic briks.
Avoid restarting if speed changed:
It need some logic in the script, I have no time to example, but
idea is simple:
Get current frame to memory when you change speed with (getActionFrame(layer))
and set back after new Action started with (setActionFrame(frame, layer)
Thanks for the pointers- I have got rid of the logic brick and its all in Python now.
However I could not get getActionFrame and setActionFrame to do what I wanted. I’m missing a very small piece somewhere…the nearest I have so far is this attachment: it has some strange issues but its the closest I have yet. I think there is a reason I have avoided trying to learn animation and actions- they are a right pain!
I inserted one extra line and things seem to be better:
own = cont.owner
sce = bge.logic.getCurrentScene()
obList = sce.objects
name = "CubeAction"
start = 1.0
end = 6.0
layer = 0
priority = 1
blendin = 0.0
mode = bge.logic.KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = own["SpeedUp"]
own.playAction(name, start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
frame = own.getActionFrame(0)
if frame > 5:
speed = own["SpeedUp"]
own.setActionFrame(frame,0) < -----NEW LINE
if speed > 2.5:
own["SpeedUp"] = 2.5
Is this how it is supposed to be?
ActionProblem2.blend (439 KB)
you can just have the action in property mode, and adjust the property with logic and/or python this is nice because you can use the property for sequencing
like if property =7 apply force or add object etc.
here’s a short example on how to do.
ActionProblem3.blend (460 KB)
You should only play the action again when the action is finished. Also, you should set Animation Frame Rate to the Logic Tic Rate (in this case 60). Doing so enables you to preview actions correctly in the viewport. The example shows how I would do it.
Edit: don’t activate Sun Shadows because it will mess with any action in Blender 2.72b (it’s a bug)
Piston_action.blend (86.3 KB)
Is the speed supposed to change while the animation is playing? Or stays the speed constant during the play, but you play with each time with different speed?
Is the speed supposed to change while the animation is playing?
This in a way, Monster.
What I am aiming for is this set-up:
Property that increases as a button is held, and decreases when button is let go. The property has set limits.
This property is used in the speed argument in playAction.
The longer the button is held, the faster the animation. If the button is let go, the animation slows.
In game, this will be a piston for an engine. As the player accelerates, the piston animation gets faster and when the player lets go of the acceleration key it slows.
A blend is attached now, sorry for the delay.
check this out
press W to speed up animation:D
Reciprical.blend (412 KB)
As this means you change the speed while playing, I think the ActionActuator in property mode is a good way to deal with this requirement.
You will get full control what frame is played. You can even play reverse.
Here is an example with speed change by factor ( one percent )
The logic to perform the animation is this (state 1):
The logic to change speed is in state 2.
Btw. The speed is in animation frames per frame ( 1= 60 frames/sec)
Animation_with_variable_speed.blend (92.8 KB)
This is all gold, guys! Thanks for all your help and taking time to make examples. From taking apart everything here I have made this which seems to work reliably- my programming skills are not as good as yours Raco so I simplified it as much as I could.
I am quite fond of logic examples too and thanks for those .Blends BluePrintRandom and Monster.
To control use the up and down cursors. There are no lower limits (so values below 0 mess things up) but it works a treat. In essence the action animates one loop and then will use the speed value (so no restarts/ stuttering mid animation). The only niggle is that the line
end = 6.0
if own.getActionFrame() >= 5:
cannot be cleaner with
end = 6.0
if own.getActionFrame() == end:
as I can never get the frame to finish on 6.0 exactly- but it works and thats the main thing!
Edit: here is a cleaner version:
Piston.blend (445 KB)Piston_Clean.blend (444 KB)