Search Unity

Go back and forth between Animator Idle and Timeline animation

Discussion in 'Timeline' started by BroncoBilli, Mar 21, 2020.

  1. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    I have this avatar in my scene. Most of the time, he's being animated by his Animator, and the Animator is looping an "Idle" animation...

    Once in a while, I want to smoothly have the avatar do a sequence of things, which I'd like to set up and edit on a Timeline! Maybe wave at the user, whistle a tune, do some stretches, use a signal on a signal track to activate some other things in the scene, THEN when the timeline is over, I want to ease back into the Idle animation.

    Naively, I thought the way to do this was for the Animator to have two states: An "IdleWhileNotBeingTimelined" and "BeingAnimatedByTimeline", and to provide a bool variable, "IsBeingTimelined" that when set, transitions from Idle to BeingAnimatedByTimeline, and the reverse transition is performed when the bool IsBeingTimelined is false. Idle also has a transition to itself, so when it gets to the end, it keeps idling. The timelines can only be activated by script, because I have to set the bool variable BEFORE starting the timeline (which stinks).

    This whole stupid approach WORKS, but it doesn't smoothly transition from the animation that was at the end of the timeline back to the idle animation. Which is a pretty good indication I don't know what I'm doing.

    Give the constraints of what I need to do, can anybody suggest a better way? It's essential the Timeline be used, however, it's going to be set up and edited by non-coders who actually don't know anything about Unity, they're just animating the Avatar to look good. I need a way to go from whatever is at the end of a played timeline back to an idle animation, smoothly. When it's not being animated by a timeline, it needs an idle loop where it plays an idle animation, or perhaps loops through several very long and random idle animations.

    What's unclear is how the Timeline, when using an animation track type, is using the Animator! I get it that the animation track needs to know what avatar to apply the animation to, but is there any state or variable or switch that gets set in the Animator when a Timeline starts applying its animation to the avatar? How can I tell, in the Animator's graph builder, when a Timeline is - what - additively adding? - an animation on top of what's currently going on!? Is this a feature request, a bug, or is there a way to do this?
     
    RodrigoSeVeN likes this.
  2. gekidoslayer

    gekidoslayer

    Unity Technologies

    Joined:
    Sep 27, 2016
    Posts:
    134
    If you have an animation track bound to the character in timeline, it will automatically override whatever the animator is doing - you could use a Signal to notify your character script that a timeline is active potentially.

    To blend from whatever the animator is doing to the timeline, you can use the 'blend in' time on the animation clips on timeline (or blend out)...this way it will blend from the looping idle to whatever the timeline does and back.
     
    yasirkula likes this.
  3. KognitoAK

    KognitoAK

    Joined:
    Mar 5, 2020
    Posts:
    3
    One approach is to return to the "idle" pose at the end of every timeline. During runtime only, increase the duration of your timeline by a small amount and insert clips that line up with the upcoming idle state.

    If you want to transition directly to / from a large number of idle states, it may require data structures populated before runtime. But there is another way; you can (upon the end of your idle phase) have the AnimatorController play a state that transitions quickly to a "universal" idle pose, ending with an AnimationEvent that kicks off your timeline cutscene.

    This is theory, I have faced similar but not identical challenges.

    I think many animation challenges stem from AnimationPlayableOutput. When multiple AnimationPlayableOutput point to the same animator (i.e. from an AnimatorController and a Timeline), there's limited communication between parts, and balancing or blending them requires offbeat solutions.
     
  4. alti

    alti

    Joined:
    Jan 8, 2014
    Posts:
    94
    When you select the clip in your animation track in timeline, the inspector will show a "ease out" duration.
    Input like 0.3 (s = seconds) and it will blend from the clip you are using in timeline, and seamlessly into you regular controller. You can do the same thing with the ease in value.

    However, on the topic of a better way, I would just make a new script and reference the animator. You can use those terrible animation lines in the animator and utilize bool parameters to get the animator to transition between clips where you can control the transition times, or you can just code it and use GetComponent<Animator>().CrossFadeInFixedTime("animName", transitionTime); where "anim name" is the animation name you want to transition to, and transitionTime is a float you set to a small value like 0.2f.

    IE:

    Code (CSharp):
    1. private float idleThreshold;
    2.     public float transitionTime;
    3.     Animator anim;
    4.  
    5.     void Update(){
    6.         idleThreshold -= Time.deltaTime;
    7.         if(idleThreshold < 0){
    8.             int randomAction = Random.Range(0, 3); //3 would be the number of options you made.
    9.             // anim.SetBool("idleAction_" + randomAction, true);
    10.             anim.CrossFadeInFixedTime("Animname_" + randomAction, transitionTime);
    11.             idleThreshold = 10f;
    12.         }
    13.     }
    this will play a clip randomly every 10 seconds, providing you name your alternative animations "idle_0" "idle_1" etc. Be sure not to run this script while your character's attacking or doing anything other than idling. You will know what suits your project best; there are plenty of ways to perform this check.

    For instance:

    string theState;
    if(theState == "idling") //execute the example code