Game Development Community

LightRecoil - setActionthread vs. playthread

by Martin Banks · in Torque 3D Professional · 09/09/2009 (3:09 pm) · 14 replies

I have created a character and a weapon. I have set up the weapon states so that there is a ready and fire. The fire state defines lightrecoil, and the character has a corresponding light_recoil animation. I copied this relationship setup from the full example supplied with beta5. However, unlike the example project characters (boombot etc.) when my character fires, the item anim plays as expected, but the character's light_recoil gets to the end and then is stuck on its final frame.

I can then walk around, and instead of returning to my character's idle animation, it poses right back to the final frame of the weapon fire animation.

I've read that if a nonlooping animation is played using playthread(), then it will stick to the final frame until stopThread() is called on that animation slot. However, I'm not sure if that is the method behind playing the light_recoil animation. Would this behavior also occur using setActionThread()?

What am I missing here?

Thanks in advance.

#1
09/14/2009 (5:21 pm)
I am noticing in Player::pickActionAnimation() that when this sticking or freezing occurs, the velocity (vel) sticks at 0,0,0. So, this prevents the 'run' action from being set.

Anyone else getting this issue?
#2
09/14/2009 (6:03 pm)
How do you use setActionThread() ?
I believe you are using it with wait/hold flag.
#3
09/14/2009 (6:08 pm)
@Picasso

I simply call it in script with the name of the animation sequence and no other parameters.

setActionThread("animName");

Unless it defaults to wait/hold, then I can't see how that is being set.
#5
09/15/2009 (11:40 am)
@WCIT
My root animation works. The light_recoil is not looping, and is not exported as a blend. It simply sticks to the last frame, and prevents the 'run' animation from playing every. So the sequence is as follows:

idle, run, idle, Lrecoil, idle, try to run and now its sticks.

At this point I then noticed the velocity was stalled at zeroes, as noted above in Player::pickActionAnimation().

#6
09/15/2009 (1:36 pm)
OK,try this one:

player.cpp

after the console method setactionthread(),add a new one:
ConsoleMethod( Player, setActionThread2, bool, 3, 8, "action,forward,hold,wait,fsp,forceSet)")
{   //parameters : action,forward,hold,wait,fsp,forceSet
    object->setActionThread(dAtoi(argv[2]),dAtob(argv[3]),dAtob(argv[4]),dAtob(argv[5]),dAtob(argv[6]),dAtob(argv[7]));
	return true;
}

in player.h correct setactionthread to be in public,so we now have an access to it :
virtual void setActionThread(U32 action,bool forward,bool hold = false,bool wait = false,bool fsp = false, bool forceSet = false);

replace with this one:
public:
   virtual void setActionThread(U32 action,bool forward,bool hold = false,bool wait = false,bool fsp = false, bool forceSet = false);
   protected:

And do not forget to add setMaskBits(ActionMask) in the real setactionthread();

Test your animation with setActionThread2() method.
Now you have an access to all flags.

Actually animation problems are very hard to be solved from torquescript,because of the little functionality.
I believe you should move to c++ to trace out what exactly happens.
#7
09/15/2009 (3:05 pm)
thanks, picasso I'm definitely gonna try this.

I am actually in the engine code tracking this down, the reference above to discovering the zero velocity (which I think is a lead to the problem here) that happens while the character is moving forward/back/side was discovered in player.cpp

Player::pickActionAnimation() sets the index into the action sequence list, then calls Player::setActionThread().
#8
09/15/2009 (3:16 pm)
pickActionAnimation() sets the sequences in relation to player's velocity.But not all of them.
Only those with the colinear vector directions - run,back and side.
If eventually there is no velocity,root is set.
The rest is handled in various ways - setSequence(),then transitioning to another sequence and so....
Look for more information ActionAnimationList at the beginning of the file.

If you want to see there is no problem with the velocity,you can call setActionThread() with forceset+wait directly in c++.

Your problem appear to be setting the action thread all the time,setting it twice,holding it or high sequence priority.
#9
09/15/2009 (4:27 pm)
Ok, so I renamed my light_recoil sequence to "squeeze" and then called setActionThread() in script Player::onTrigger for trigger0 and now everything appears to be working with no unexpected blending or sticking.
#10
09/15/2009 (4:37 pm)
Right now i take a look at the code and see there is an additional thread (mRecoilThread) for the recoil animation.
You don't need even to use setActionThread(),just rename your file to "light_recoil", "medium_recoil" or "heavy_recoil" and advanceTime() will advance your animation.

setActionThread() is intended to be used for an ActionAnimation thread,not mRecoilThread.
This mRecoilThread seems as a thread that controls a specific part of the player.So it depends how you provide it.
If you export "light_recoil" like a normal animation,it will advance over the whole player (like the ActionAnimation.thread).
So you have two threads working on the player,that's why it is messed up.
#11
09/15/2009 (4:50 pm)
I think this could help:
http://www.garagegames.com/community/forums/viewthread/76357
Actually, I would call it a "bug" (same as in TGEA171 in mentioned thread).
#12
09/15/2009 (4:58 pm)
@Picasso - I had the sequence named to light_recoil initially and it was not playing consistently, and it was giving me the sticking/unexpected blendfreeze problems. The rest of the history happens at the beginning of the thread.

I think there is something going on with the way the hinted/default actions are initiated that was causing the problem. Seems that maybe the recoil thread is sticking and holding.
#13
09/15/2009 (5:45 pm)
@Fydoor I looked at the problems you describe in that post for recoil. http://www.garagegames.com/community/forums/viewthread/76357

If I understand correctly, then you ran across these problems as a result of having several recoil animations defined, which I notice were defined as sequences in your TSShapeConstructor(myCharShape).

In my example I only had one recoil (light_recoil), but it was originally a collada import so my sequences were added in the myChar.cs file myCharShape::onLoad via addsequence().
#14
09/16/2009 (2:33 pm)
Martin,
you get unexpected behaviour of the body because you did export your recoil animation as a full body animation.
This animation should control a specific part of the body.

When you call setactionthread(),you change the sequence control.
You move the control to the action animation thread and you can not play a second sequence while playing your recoil sequence.
And it is normal.

A thread can control a single sequence.
That's why there is a recoil thread - to play two sequences at the same time.
If your animation is not cyclic,it will hold the full body animation at end.It will overlap the animation bone control of the main action thread,because mRecoilThread is played after it (look at updateAnimation()) - this is exactly what you see.
If it is cyclic,it will run all the time.
You can not tell 2 sequences to control same bones on the player at the same time.
I believe now you understand the problem.

You can workaround this by:
- removing all keyframes for the rest body animation
- use fullbody animation (as now),but separate the sequences in different priorities.