Search Unity

playing animation backwards

Discussion in 'Scripting' started by cboe, Nov 18, 2008.

  1. cboe

    cboe

    Joined:
    Nov 18, 2008
    Posts:
    15
    hi folks

    im stuck now for 3 hours with a really simple issue: i want to play an animation backwards. in the script reference i found that i just need to set the speed to -1. so i did this:

    Code (csharp):
    1.  
    2. hand.animation["bridge"].speed = -1;
    3. hand.animation.Play("bridge");
    4.  
    it does nothing, what am i doing wrong?

    ps: is there a way to start an animation at a different time in the timeline (ie at the 5. frame)?
     
  2. rightpurdy

    rightpurdy

    Joined:
    Oct 31, 2007
    Posts:
    39
    I don't see any offending code in your example other than your declaring the hand object before the animation component, you could try adding the animation component to the hand object, making sure you define the animation string name, and then just call animation["bridge"].speed in the code for the object, here is the snippet I use and it works for me:
    Code (csharp):
    1.  
    2. if(Input.GetKeyDown("w") || Input.GetKeyDown("up")) { animation["walk"].speed = 1.0; animation["run"].speed = 1.0; }
    3. if(Input.GetKeyDown("s") || Input.GetKeyDown("down")) { animation["walk"].speed = -1.0; animation["run"].speed = -1.0; }
    4.  
    You could run some tests to make sure your playing an animation and it is the "bridge" animation:
    Code (csharp):
    1.  
    2. if(animation.IsPlaying("bridge")) { print("bridge animation is running"); }
    3.  
    Also for the starting the animation at a different timeline, someone can correct me, but I believe you wold use:
    Code (csharp):
    1.  animation.Blend("animation",target distance(i.e. 5.0=50% of animation),fadelength(i.e. speed of the aniamtion to blend in));
    Hopefully that may help out some.
     
  3. Sanity11

    Sanity11

    Joined:
    Nov 25, 2007
    Posts:
    96
    Hmm, I am wondering how to get this to work:

    Code (csharp):
    1.  
    2. function Update() {
    3.     print("Triggerstay= " + triggerStay);
    4.     if(triggerStay) {
    5.         if (Input.GetButtonDown ("Fire1")  !isOpen) {
    6.             print("Open door");
    7.             deurObject.animation["Open"].speed = 1.0;
    8.             deurObject.animation.Play("Open");
    9.             isOpen = true;
    10.         } else if (Input.GetButtonDown ("Fire1")  isOpen) {
    11.             print("Close door");
    12.             deurObject.animation["Open"].speed = -1.0;
    13.             deurObject.animation.Play("Open");
    14.             isOpen = false;
    15.         }
    16.     }
    17. }
    18.  
    This code uses the "Open" animation to open and close a door. When it's playing forward it animates just fine. But when going backward it closes at once. It looks like the animation simply resets or something. What am I doing wrong?
     
  4. cboe

    cboe

    Joined:
    Nov 18, 2008
    Posts:
    15
    Sanity11, it's the same problem that I've got. ill try it with rightpurdys method, hopefully that works, thanks!
     
  5. cboe

    cboe

    Joined:
    Nov 18, 2008
    Posts:
    15
    ok ive put the script directly in the object that has the animation now (had it linked to an empty game object before) and i tried to make some adjustments, but it doesnt change anything. when i print the animation speed, it says -1, but it doesnt play it, instead it immediately switches to the start position of the animation.

    any1 else who had problems with playing animations backwards?

    thx in advance

    ps: it works when i set another positive speed, like 2
     
  6. careyagimon

    careyagimon

    Joined:
    Dec 20, 2007
    Posts:
    209
    I think you need to set when the animation is playing from first. Playing it backwards from 0.0 doesn't do anything. You need to play it backwards from the end of the animation.


    Code (csharp):
    1.  
    2. hand.animation["bridge"].speed = -1;
    3. hand.animation["bridge"].time = hand.animation["bridge"].length;
    4. hand.animation.Play("bridge");
    5.  
    Even better is if you can set the wrap mode to ClampForever. Play the animation once at speed 1 and then set the speed to -1 to reverse back to the starting state.
     
  7. cboe

    cboe

    Joined:
    Nov 18, 2008
    Posts:
    15
    that's it, thx a lot
     
  8. chishti

    chishti

    Joined:
    May 21, 2009
    Posts:
    188
    thanks careyagimon I had the same problem as cboe. and now it works.

    thanks again
     
  9. pjl110

    pjl110

    Joined:
    Mar 27, 2010
    Posts:
    20
    you are right!thank you!
    careyagimon正解!
     
  10. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    Thanks a lot, works perfectly!
     
  11. xCyborg

    xCyborg

    Joined:
    Oct 4, 2010
    Posts:
    633
    Finally, thank you, setting time to length is something that would ages to think about, here is what I got to:
    Code (csharp):
    1.     public void AttackAnimation(bool on){
    2.         if(on){
    3.             //print ("Attack On");
    4.             animation["Attack"].wrapMode=WrapMode.ClampForever;
    5.             animation["Attack"].speed = 10;
    6.             animation["Attack"].time = 0;
    7.             animation.CrossFade("Attack");
    8.         }else{
    9.             //print ("Attack off");
    10.             animation["Attack"].wrapMode=WrapMode.Once;        
    11.             animation["Attack"].speed = -10;
    12.             animation["Attack"].time = animation["Attack"].length;
    13.             animation.CrossFade("Attack");
    14.         }      
    15.     }
    16.     public void DefendAnimation(bool on){
    17.         if(on){
    18.             //print ("Defense On");
    19.             animation["Defend"].wrapMode=WrapMode.ClampForever;
    20.             animation["Defend"].speed = 10;
    21.             animation["Defend"].time = 0;
    22.             animation.CrossFade("Defend");
    23.         }else{
    24.             //print ("Defense off");
    25.             animation["Defend"].wrapMode=WrapMode.Once;        
    26.             animation["Defend"].speed = -10;
    27.             animation["Defend"].time = animation["Defend"].length;
    28.             animation.CrossFade("Defend");
    29.         }      
    30.     }
    31.  
    The speed variable is apparently absolute value and not relative, I guess it's a new change along with Mechanim, so I measured it first using Log and then hardcoded like this because using multiplier like: animation[clip].speed*=-1; resulted in oldTime>newTine error or some like that, an alternative could be using absolute math function but for me hardcoding is fine.
    One last inportant step is the wrapMode, it's imperative that the positive animation has a ClampForever mode while the negative one has a Once mode, otherwise it wouldn't make sense and the animation would be jittery.
    And last this code is not perfect for long animation because time on a ClampForever animation is not limited to length but infinite which makes impossible to make a smooth animation even with conditional time setting.
    I hope Unity Team could implement native Reverse Play cuz I thought it was there until I needed it and as far as I know, there is no 3rd party solution as well.
     
  12. Andy-Sun

    Andy-Sun

    Joined:
    Jul 30, 2013
    Posts:
    1
    @careyagimon , Perfectly work! Thanks a lot !
     
  13. hal69

    hal69

    Joined:
    Jul 17, 2013
    Posts:
    1
    I've got the same problem, and found part of the answer here, thank you!
    A "play once" animation timer is reset to zero once played. So, try to play it reversed has no effect.
    You just have to set the timer correctly before playing your animation, this little code works in everycase (forward or backward):

    if (reversed)
    {
    animation[animation_name].normalizedTime = 1f;
    animation[animation_name].speed = -1f;
    }
    else
    {
    animation[animation_name].normalizedTime = 0f;
    animation[animation_name].speed = 1f;
    }
    That was the best solution for me, hope it will help
     
  14. Anton1274

    Anton1274

    Joined:
    Dec 7, 2013
    Posts:
    10
    Try this for me worked fine:-
    if(!animation.IsPlaying("walk")) animation["walk"].time = animation["walk"].length;
    animation["walk"].speed=-1.0;
    animation.CrossFade("walk");
    Reversing an animation without put the begin at the end make no sense.
    So if your animation is not playing (before it starts) set the time of the animation to it's end.
    then set the speed to a negative number and play it....
    It works very fine for me.
     
  15. cyenketswamy

    cyenketswamy

    Joined:
    Jul 24, 2015
    Posts:
    41
    For those using Unity 5 the following also works.

    Animator animator;

    animator = GetComponent<Animator>();

    animator.speed =-1;

    If you have a sliding door blender model with one animation saying opening a door the above can be used to simulate a closing door animation.
     
  16. brazierli

    brazierli

    Joined:
    Mar 26, 2016
    Posts:
    1
    why not something like this.
    Code (CSharp):
    1.  
    2.     public string runing;  
    3.     bool run;
    4.     Animator anim;
    5.  
    6. void Start(){
    7.         anim = GetComponent<Animator>();
    8.         anim.animation[runing].speed = -1;
    9.     }
    10.  
    11.  
    12.     void Update () {
    13.  
    14.         //input
    15.         if(run){
    16.             //if done run
    17.             if(anim.animation[runing].time == 0){
    18.  
    19.                 anim.animation[runing].speed *= -1;
    20.  
    21.                 anim.animation[runing].time =  Mathf.Clamp(anim.animation[runing].length * -anim.animation[runing].speed,0,anim.animation[runing].length);
    22.  
    23.                 anim.animation.Play(runing);
    24.  
    25.                 run = false;
    26.             }
    27.         }
    28.     }
    29.  
    its toggleable so it reverses itself each time it is activated.
     
    Last edited: Mar 26, 2016
  17. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Unity UI is sort of doing animation forward and backward with Button's. I mean you can apply the same thing to doors, pressureplates and others. You have 2 animations, where both have only 1 keyframe at 0:00. The transition between them is the animation, like ButtonUp -> ButtonDown, and ButtonDown -> ButtonUp. For this we don't need to negate speed.
     
  18. rahulpatil6220375

    rahulpatil6220375

    Joined:
    Dec 10, 2018
    Posts:
    19
    animation only run one time