Animation not playing when triggered the second time.

I had been reading many posts with similar problems and tried all suggested approaches for the last 2 days but still could not get my scenario to work. Therefore, I am posting my question with as much details as possible. The use case is shown in the attached file.

The ‘ball’ game object is inside the “BallContainer” parent object.

I have 3 animations: Idle, BallStraight and Shot1. Idle is the start position. When “Ball” button is clicked, I play the BallStraight Animation. The animation is simply a position transition. I just set the trigger for the animation to play.

anim.SetTrigger("BallStraight");

The animation does not work when “Apply Root Motion” in the Animator component is Checked. So I un-checked it. Then the animation works. The ball moves.

While the ball moves, button “Shot” is clicked. Then the ball should move to the right from its current position. To achieve this I used parent object position. (the script of code below is attached to the “Ball” object)

void Start ()

    {

        anim = GetComponent<Animator>();

        defaultBallPosition = transform.position;

        defaultParentPosition = transform.parent.position;

    }
public void AnimateBallMovement()

    {

        transform.parent.position = transform.position;

        transform.localPosition = Vector3.zero;


        anim.SetTrigger(“Shot1”);

    }

Now the ball moves right. When it reaches the boundary (which is a trigger collider), I have to move the ball back to “Idle” position. Since the “Idle” animation has no position coordinates defined, I have to set the position manually and change the animation state. Here I set it as follows.

public void ResetBallPosition()

    {

        transform.parent.position = defaultParentPosition;

        transform.localPosition = Vector3.zero;

        anim.SetTrigger("Idle");

    }

The ball moves back to its original position. All works as expected to this point. Now when I click the “Ball” Button again, it does not play the “BallStraight” animation. Everything freezes. When I check the Animator window, I see the state has moved to “BallStraight” but frozen there. However, I never saw the ball move at all. It only plays once. I just want the state to reset, and continue playing the steps. What am I doing wrong? Is the animation somehow changing into “applyRootMotion=true” implicitly? Because that is the same behavior I see when I check the “Apply Root Motion” check box in Animator component in the start.

I’m guessing it has something to do with the trigger not being consumed - however I’m not a programmer so - I’m just guessing.
Hope this points you to a solution.

I think it would be much more simple if you just moved the ball in code rather depend on animation root motion. For instance:

  • if (anim.GetCurrentAnimatorStateInfo(0).IsName(“BallStraight”))
  • {
  • parent.transform.translate(Vector3.forward * Time.deltatime());
  • }

alternatively you could set root motion to HandleInScript, or whatever that option is where you read the root motion manually and apply it yourself with OnAnimatorMove() and animator.deltaPosition. Either of these options is giving you good feedback so you can solve your problems quicker whatever they may be.

Thanks for the reply @CaseyLee .

Problem with moving the ball manually is that, in the final product the ball will not move in a straight line. It has to move like a real ball does (bumping and stuff). This is just a test scenario. And i will have to make a lot of movements like that for all directions. I thought this would be a very difficult task to do manually. That’s why i decided to utilize the existing animation mechanism.

However i would like to try your second option out. Can you give me some more details on what to do? Or point me to link where i can get more details?

If were talking about complex movements, like ones handled by unity physics for instance - then ill first suggest a third option where-in the animations are decided after considering the objects velocity (instead of the velocity changing per animation). One example of this would be storing the object’s current velocity and exposing it to the animations per animation parameters (one for each axis), and updating the parameters each frame. the animations could be in a blend tree playing either roll left/right/idle animations depending on X axis velocity, and up/down/idle depending on Y velocity.

as for you question concerning “OnAnimatorMove”: you need to change the animation root motion to “Handle in script”, then, any script that is on the same object as the animator (or an object that is a child of the animator’s) will get the OnAnimatorMove() callback each time the animator updates.

Using this callback, if you print the values for anim.deltaPostion and anim.deltaRotation you will be looking at the root motion stored in the current animatin being played. this is the root animation that you would be seeing if root motion was enabled. For starters you can use this simply as a way to debug your animations, checking the root motion is there, and the clip is configured properly in its import settings. if you are getting zero values, you need to check clip settings.

sooo… instead of having unity “animate” the root motion you can “animate” it yourself by applying deltaPosition to your objects position, and same for rotation if need be. Using this gives you many options in the long run, for instance you may want to get that deltaPosition and subtract a friction value from it if your doing the physics yourself, here is a simple example:

OnAnimatorMove()
{
timeInState = some time in state variable, or time playing the animation
float frictionX = -.1f * timeInState;
float frictionY = -.2f * timeInState;

var velocity = new Vector3 (anim.deltaPosition.x + frictionX, anim.deltaPosition.y + frictionY, 0f ); // 2D game for now -.-

if(Mathf.sign(velocity) == Mathf.sign(anim.deltaPosition)
transform.position += velocity;

}

CODE NO CHECKED!* sudo code!

1 Like

When you say exposing the parameters to the animation, does that mean we can use the dynamically passed in parameters in the animation and make it work according those values? Never came across anything like that. I thought they are just triggers. Could that only be done from code? Or is there a way to make use of parameter values in the Animation window in Unity?

Thats the main purpose for Unity’s blend trees: Unity - Manual: Blend Trees

and for changing parameter values, I believe it must be from a script.