Search Unity

How to create a 0 length motion / empty animation clip

Discussion in 'Animation' started by RakNet, Nov 30, 2017.

  1. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    315
    I wanted to share my discovery on how to create an empty animation clip. This is useful in my case where I have a moddable game and I want to use a shared state machine where some states are optional. But I can see it used in other contexts. For example, it gives you a way to use AnimatorOverrideController to turn states on and off.

    If you were to go by Unity's own example:
    https://docs.unity3d.com/ScriptReference/AnimationClip.SetCurve.html

    You would expect this to work:
    AnimationClip clip = new AnimationClip();
    clip.name = clipName;
    anim.AddClip(clip, "test");

    It doesn't. Empty AnimationClips play for 1 second, they just play nothing and your animated object is frozen for that time. You can't change that 1 second from what I've tried.

    Here's a workaround:
    AnimationClip clip = new AnimationClip();
    clip.name = name;
    AnimationCurve curve = AnimationCurve.Linear(0.0F, 1.0F, .0001F, 1.0F); // Unity won't let me use 0 length, so use a very small length instead
    EditorCurveBinding binding = EditorCurveBinding.FloatCurve(string.Empty, typeof(UnityEngine.Animator), "ThisIsAnEmptyAnimationClip"); // Just dummy data
    AnimationUtility.SetEditorCurve(clip, binding, curve);
    AssetDatabase.CreateAsset(clip, "Assets/" + name + ".anim");
     
    madfish-od likes this.
  2. hk1ll3r

    hk1ll3r

    Joined:
    Sep 13, 2018
    Posts:
    88
    Awesome! Great job dude. Unity is like your typical random github project. Gotta poke around to get things working.
     
    Romaleks360 likes this.
  3. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Try using float.Epsilon as the length (the smallest possible value above 0). Not that it would make any practical difference.
     
  4. hk1ll3r

    hk1ll3r

    Joined:
    Sep 13, 2018
    Posts:
    88
    I ended up creating an animation in editor with no sprite and a super small length (by setting the frames per second to 1200). Instead of the sprite, I have the animation animate a dummy variable. Gets around having to setup the animation in code.
     
    madfish-od likes this.
  5. madfish-od

    madfish-od

    Joined:
    Nov 11, 2012
    Posts:
    2
    Thanx to @RakNet

    Example of editor script below

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class DummyClipCreate : Editor
    5. {
    6.     [MenuItem("Tools/Create Dummy Clip")]
    7.     static void CreateDummyClip()
    8.     {
    9.         var path = EditorUtility.SaveFilePanelInProject("Save Dummy Animation Clip", "Dummy", "anim", "");
    10.         AnimationClip clip = new AnimationClip();
    11.         clip.name = "Dummy";
    12.         AnimationCurve curve = AnimationCurve.Linear(0.0F, 1.0F, 0.017F, 1.0F);
    13.         EditorCurveBinding binding = EditorCurveBinding.FloatCurve(string.Empty, typeof(UnityEngine.Animator), "DummyAnimationClip");
    14.         AnimationUtility.SetEditorCurve(clip, binding, curve);
    15.         AssetDatabase.CreateAsset(clip, path);
    16.     }
    17. }
     
    Last edited: Aug 27, 2020
    Miraslavk likes this.
  6. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    542
    The code works to create a short, "empty" animation, but does not actually work for the use case the OP mentions.

    The goal was to use these "empty" animations as optional states for an AnimatorOverrideController, so you can drag in the empty animation and in same cases leave them empty in the specific AnimatorOverrideController to make them "optional".

    I wanted to achieve the same thing so I found this thread, but it does not work for me. In my "base" Animator I have 3 animation states. I call them DrinkStart with a transition to DrinkLoop with a transition to DrinkEnd.

    Some of my models don't have a specific start/end animation, so I created 3 "empty" animations with the code above and used them as placeholder. In the animal AnimatorOverrideController for the animals with all animation I drag all 3 animations and it works fine, but for the animals which only have the loop animation and no specfic start / end I only drag the loop animation in the AnimatorOverrideController and so the "empty" animation plays for the start / end states.

    But this "empty" animation in the DrinkStart state causes the animal to go into a weird (T-Pose?) position before the transition to the DrinkLoop state (which has a "real" animation).

    So am I doing something wrong here or did this thread never actually achieve the OPs goal? If so is there a new / better / different way to create real "optional" states in a base animator?

    My next idea would be to create an other base Animator for animels which don't have 3 different animations per "action" but then I would still have to duplicate the logic between 2 base Animators.
     
    Last edited: Sep 29, 2021
    ludidilu22 likes this.
  7. Realinspirer

    Realinspirer

    Joined:
    Aug 19, 2020
    Posts:
    7
    So, in case someone just wanna use the editor. You can just crank up the speed to 50 or something, and boom your (almost) 0 second transition is ready! Phew... that's a silly workaround, but it works!
    upload_2022-8-18_4-5-9.png
     

    Attached Files:

    phil_slf likes this.
  8. Romaleks360

    Romaleks360

    Joined:
    Sep 9, 2017
    Posts:
    72
    Works fine for me. Make sure that m_StopTime of your AnimationClip is not zero (you can see it in Debug inspector mode)

    You CAN create such a clip without code. You just have to set the m_StopTime of your clip to whatever your like, but greater than zero (epsilon gets rounded to zero). Something like 0.01 will do. But the clip also MUST contain at least some keys, or it will snap back to default duration. So this works as follows:
    - create a clip
    - add keys. Two options here: either put it in Animator and just add any property (like transform.position), or add a dummy empty curve from code like OP did.
    - change the duration. Again, two options: just move the last animation key to the smallest possible time (this will change the m_StopTime), or manually change the m_StopTime of your clip from debug inspector mode (in this case, the duration of the clip itself, i.e the position of the last key doesn't matter)

    That's it!
     
    Last edited: Oct 18, 2022
  9. phil_slf

    phil_slf

    Joined:
    Jun 28, 2013
    Posts:
    3
    This is the workaround I have been using for the exact same situation and still works fine in 2023.
     
  10. Realinspirer

    Realinspirer

    Joined:
    Aug 19, 2020
    Posts:
    7
    So, future me is here. That was actually a dumb workaround, still it, works... But apparently Unity has a 'default' clip length of 1 second for some reason. I don't know why/how they decided it to be 1 second, or it can be totally arbitrary.

    So, if you have only one keyframe in your animation, it will have a default length of 1 second, but what you gotta do is just copy the same keyframe from there to the immediate next keyframe, and you got yourself a proper 0 second- wait actually it's of 1/(sample-rate) seconds, but I do believe that's the way it goes. But tbh, 0 second clip? Doesn't make too much sense, though almost 0 second clip does make more sense.