Search Unity

How can I play an animation backwards?

Discussion in 'Timeline' started by mrpmorris, Oct 1, 2017.

  1. mrpmorris

    mrpmorris

    Joined:
    Dec 25, 2012
    Posts:
    47
    I've added an animation to my timeline, but the timescale on that animation won't let me specify a negative number. How can I play the animation in reverse? (Speed -1).
     
  2. thierry_unity

    thierry_unity

    Unity Technologies

    Joined:
    Jun 10, 2015
    Posts:
    183
    Hi,
    Unfortunately, right now there is no way to play an animation in reverse inside timeline. It's something that came up a couple of time but there is no easy way to do it. Only solution I can give you is to duplicate your clip and inside the animation window, using the box tool, you could reverse the 2nd clip.
     
    DenisK_WRG, KQQky and TheWarper like this.
  3. mrpmorris

    mrpmorris

    Joined:
    Dec 25, 2012
    Posts:
    47
    Ah damn, that's really disappointing!

    Thanks for your answer.
     
  4. vladk

    vladk

    Joined:
    Jul 10, 2008
    Posts:
    159
    could you please explain how to do it? What's a box tool?
     
  5. Sergey_Droba

    Sergey_Droba

    Joined:
    Nov 6, 2016
    Posts:
    29
  6. ferretnt

    ferretnt

    Joined:
    Apr 10, 2012
    Posts:
    314
    Timeline can't currently play animations backwards.

    To fix this, you can duplicate your animation in the project window, and then create a reversed copy in "Keys" view by dragging right to its end then scaling negatively, which works, but is a pain on large animations as the Animation UI becomes quite unresponsive.

    Or, you can clone your anim and run this script:

    https://answers.unity.com/questions/476819/reverse-animation-help.html

    Both confirmed working in 2017.4, but the script version is much less hassle.

    It would be nice to be able to create the reversed animation clip at runtime, but I believe that's not possible until 2018.2 (?)
     
    fbittner and TheWarper like this.
  7. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    59
    Is this now possible?
     
  8. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,161
  9. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    59
  10. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    59
    If it helps anyone else, I modified the script above to be inside the context menu when you right click on an animation clip. It also automatically creates the copy and adds "_Reversed" to the name so you don't have to copy it first. Not perfect, but it saves me some time.



    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.IO;
    4.  
    5. public static class ReverseAnimationContext
    6. {
    7.  
    8.     [MenuItem("Assets/Create Reversed Clip", false, 14)]
    9.     private static void ReverseClip()
    10.     {
    11.         string directoryPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(Selection.activeObject));
    12.         string fileName = Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject));
    13.         string fileExtension = Path.GetExtension(AssetDatabase.GetAssetPath(Selection.activeObject));
    14.         fileName = fileName.Split('.')[0];
    15.         string copiedFilePath = directoryPath + Path.DirectorySeparatorChar + fileName + "_Reversed" + fileExtension;
    16.         var clip = GetSelectedClip();
    17.  
    18.         AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(Selection.activeObject), copiedFilePath);
    19.  
    20.         clip  = (AnimationClip)AssetDatabase.LoadAssetAtPath(copiedFilePath, typeof(AnimationClip));
    21.  
    22.         if (clip == null)
    23.             return;
    24.         float clipLength = clip.length;
    25.         var curves = AnimationUtility.GetAllCurves(clip, true);
    26.         clip.ClearCurves();
    27.         foreach (AnimationClipCurveData curve in curves)
    28.         {
    29.             var keys = curve.curve.keys;
    30.             int keyCount = keys.Length;
    31.             var postWrapmode = curve.curve.postWrapMode;
    32.             curve.curve.postWrapMode = curve.curve.preWrapMode;
    33.             curve.curve.preWrapMode = postWrapmode;
    34.             for (int i = 0; i < keyCount; i++)
    35.             {
    36.                 Keyframe K = keys[i];
    37.                 K.time = clipLength - K.time;
    38.                 var tmp = -K.inTangent;
    39.                 K.inTangent = -K.outTangent;
    40.                 K.outTangent = tmp;
    41.                 keys[i] = K;
    42.             }
    43.             curve.curve.keys = keys;
    44.             clip.SetCurve(curve.path, curve.type, curve.propertyName, curve.curve);
    45.         }
    46.         var events = AnimationUtility.GetAnimationEvents(clip);
    47.         if (events.Length > 0)
    48.         {
    49.             for (int i = 0; i < events.Length; i++)
    50.             {
    51.                 events[i].time = clipLength - events[i].time;
    52.             }
    53.             AnimationUtility.SetAnimationEvents(clip, events);
    54.         }
    55.         Debug.Log("Animation reversed!");
    56.     }
    57.  
    58.     [MenuItem("Assets/Create Reversed Clip", true)]
    59.     static bool ReverseClipValidation()
    60.     {
    61.         return Selection.activeObject.GetType() == typeof(AnimationClip);
    62.     }
    63.  
    64.     public static AnimationClip GetSelectedClip()
    65.     {
    66.         var clips = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets);
    67.         if (clips.Length > 0)
    68.         {
    69.             return clips[0] as AnimationClip;
    70.         }
    71.         return null;
    72.     }
    73.  
    74. }
    75.  
     
  11. xhdfgT

    xhdfgT

    Joined:
    Feb 12, 2017
    Posts:
    1
    Your Script is Amazing, it is working fine, Thanks for sharing
     
    Straafe likes this.
  12. Elin42

    Elin42

    Joined:
    Oct 21, 2014
    Posts:
    21
    Such a useful function. This should be in unity by default, if there is no easy way to reverse a clip in Timeline.
     
    Straafe likes this.
  13. Mr_Jigs

    Mr_Jigs

    Joined:
    Apr 18, 2015
    Posts:
    60
    Straafe likes this.
  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    780
    @Straafe You could change the menu path to "CONTEXT/AnimationClip/Create Reversed Clip" to make it a context menu function on the AnimationClip asset instead. Give it a "MenuCommand command" parameter and use "command.context" to access the clip it's being called on instead of "Selection.activeObject". That way you could select multiple clips and run the function for all of them at once (and it isn't taking up space in the main Assets menu).
     
    fbittner and ferretnt like this.
  15. pinaeong

    pinaeong

    Joined:
    Dec 17, 2019
    Posts:
    1
    @Straafe You are so amazing!! Thank you so much. Can I post your code on my blog? Of course, I'll write where it came from and who wrote it. Thank you!
     
  16. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    59
  17. steveh2112

    steveh2112

    Joined:
    Aug 30, 2015
    Posts:
    218
    sorry but where exactly do i place this code? thanks
     
  18. dasparadoxon

    dasparadoxon

    Joined:
    Aug 16, 2014
    Posts:
    2
    Thank you @Straafe for this script !!!!

    (@steveh2112 : put it into an folder named Editor, also make sure that the file is named ReverseAnimationContext.cs )
     
  19. rudehouse

    rudehouse

    Joined:
    Feb 16, 2019
    Posts:
    1


    In this video the man change the speed to negative and the animation starts playing backwards
     
    timothywwcase likes this.
unityunity