How to stop animated character returning to starting position after animation is complete

Hi,

I’m animating an intro to a level where my Player starts off standing on a box and then jumps off and begins a running stance. I will CrossFade a running animation and a translation forwards to move him and begin the game.

Now, to ensure that the animations are not looping, they are all set to WrapMode.Once and the loop is activated using a key press.

The problem I’m having is that while I can successfully CrossFade the animation from Standing on the box → Jumping off of box onto ground and beginning to run, the Player always seems to return to his starting position on the box after this. The running animation that follows this then takes place at this starting position, and if I also translate him forward, it will occur at that elevated height.

I’m wondering how to get around this, do I have to reset his position or something similar?

Thanks

//–
Continuing from comments below;

    void Start () 
        {  
            // PLAYER
            PlayerObj.animation[Player_start_idle.name].wrapMode = WrapMode.Once;
            PlayerObj.animation[Player_start_escape.name].wrapMode = WrapMode.Once; // Tried; ClampForever, Clamp
            PlayerObj.animation[Player_run.name].wrapMode = WrapMode.Loop;
            
            // Also tried adding the run animation into a higher layer
            //PlayerObj.animation[Player_run.name].layer = 2;
        }
    
       void update()
       {
           StartCoroutine(PlayEscapeAnimations());
       }

  IEnumerator PlayEscapeAnimations()
      {
          PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f);

          yield return new WaitForSeconds(Escape_lights_delay);

          if (PlayerObj.animation.IsPlaying(Player_start_escape.name))
          //PlayerObj.animation.CrossFade(Player_run.name, 0.2f);
          {
              // Let this animation finish
          }
          else
          {
              PlayerObj.animation.Play(Player_run.name);
          }
      }

In my eyes, this could be because of 1 of these 2 things:

  • You don’t apply gravity to your object, or you don’t translate it’s y position. So your character will not fall down but stays at the height it starts at.

  • Your animation might be wrong. Did you change the character’s position animation wise? Like, when he jumps, the character’s y position changes in the animation itself? Because you need to change the y position of the character gameObject, not the animation. In the animation itself, your character’s position should remain more or less the same.

Explanation: the character model has a prefab, which turns into a gameObject when you place it in your game. This gameObject has a certain position in the world. An animation is played, relatively to this point as it is a child/component of this gameObject. When you reposition the character inside the jump animation it will look like it moves but the parent gameObject doesn’t change position, only the mesh itself. When you then return to the running animation, which probably has no position offset, it will play this animation relatively to the position of the gameObject again, which didn’t move. Resulting in your character swapping back to it’s starting position. At least, that’s what seems to happen.

I hope this answer doesn’t confuse you too much, if it does I’m sorry but I don’t think I can explain it any better.

Hope it helps :wink:

You want to use WrapMode.ClampForever to stop it from automatically resetting to the starting frame.

I adjusted your script so it doesn’t always trigger the escape animation in the coroutine. I’m not sure about what the “Escape_lights_delay” is supposed to do but I assume it’s some sort of delay you apply after the escape animation?

What did I change? I put the escape animation in the Start function as I understand it needs to play immediately? Now the coroutine is still called every frame but doesn’t start an animation by default. It just checks if the escape animation is playing and if not, start the run animation after the “Escape_lights_delay”. Is this kinda what you’re looking for?

void Start () 
        {  
            // PLAYER
            PlayerObj.animation[Player_start_idle.name].wrapMode = WrapMode.Once;
            PlayerObj.animation[Player_start_escape.name].wrapMode = WrapMode.Once; // Tried; ClampForever, Clamp
            PlayerObj.animation[Player_run.name].wrapMode = WrapMode.Loop;

            //start the escape animation at the beginning
            PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f);
 
        }

       void update()
       {
           StartCoroutine(PlayEscapeAnimations());
       }

  IEnumerator PlayEscapeAnimations()
      {
          //PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f);   -> deleted because otherwise, this animation will always be playing

          if (PlayerObj.animation.IsPlaying(Player_start_escape.name))
          {
              // Let this animation finish
          }
          else
          {
              yield return new WaitForSeconds(Escape_lights_delay);
              PlayerObj.animation.Play(Player_run.name);
          }
      }