Search Unity

Need to set bindings at runtime

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

  1. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    I have a PlayableDirector which has an animation track on it (track 0), and I need to set its binding at runtime for the Animator to animate to. When the program starts, the binding is null. In script, I need to set it.

    I'm trying to fool around with getting the Playable Director's PlayableAsset and looking at its enum 'outputs', but that isn't working...
     
    KeigoTakamura likes this.
  2. gekidoslayer

    gekidoslayer

    Unity Technologies

    Joined:
    Sep 27, 2016
    Posts:
    134
    Use the SetGenericBinding method on your playable director for this:

    https://docs.unity3d.com/ScriptReference/Playables.PlayableDirector.SetGenericBinding.html

    You need to get a handle to the track that you are binding.

    You can call GetOutputTracks() on the timeline asset and iterate through them to find the one you're looking for:
    https://docs.unity3d.com/Packages/com.unity.timeline@1.2/api/UnityEngine.Timeline.TimelineAsset.html

    Pseudo code something like so (where pd is your playable director and go is the gameobject you want to bind to)

    Code (CSharp):
    1.  
    2. var timelineAsset = pd.playableAsset as TimelineAsset;
    3.  
    4. var trackList = timelineAsset.GetOutputTracks();
    5.  
    6. foreach( var track in trackList)
    7. {
    8.    // check to see if this is the one you are looking for (by name, index etc)
    9.  
    10.  
    11.    if (thisistheTrack)
    12.     {
    13.         // bind the track to our new actor instance
    14.         pd.SetGenericBinding(track, go);
    15.     }
    16.  
    17. }
     
    Foge and luvjungle like this.
  3. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    Yup. that worked. I think I uncovered a bug? I have an avatar, with an Animator on it, and the animator is looping an Idle animation as long as it's not being played by a Timeline. When I play a timeline, I set a flag in the Animator to shift the animator to a "non animating" state. After the timeline finishes, I set the flag back to false, and the Animator shifts back to playing the Idle animation. The weird thing is that when the Animator goes BACK to playing the Idle animation, the avatar jumps in position from Z Pos = 0, to Z Pos = 7.56! The specific offset doesn't matter.... Anyhow, I looked at the Animator, and I unchecked "Apply Root Motion" and the problem fixed itself. The timeline animation and the animator animation (they're different), both of them are "idle" animations, and don't appreciably move the avatar in the Z position. The fact it jumps to Z Pos = 7.56 makes me think I uncovered some weird goofy bug?
     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    The animator continues to play while the timeline runs, it's just that timeline is evaluated last. Would that explain the jump? Could the animator have been in a state that moved it?
     
  5. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    On another thread, a unity person told me the Timeline "overrides" whatever the Animator is doing. That would make a little more sense than "in addition to", from a complexity standpoint, but "in addition to" also makes sense. It's too bad, from the Animator standpoint, that it can't DETECT whether or not a Timeline is "overdriving" (is that a good word?) it. I would love to be able to switch on a state in the Animator, depending on if it's being Timeline-d or not.

    Anyhow, I digress...

    No, the two animations are both "idles". They do NOT move the object around in XZ space, much. In fact, even if we took the XZ delta from the start of either of the two animations (the one on the animator, or the one on the timeline), at no point is the delta XZ on the animation even close to 7 in magnitude, compared to the beginning of the clip. I can see there being some kind of issue if the Timeline idle animation was half-way through it's loop and then for whatever random reason the Animator loop took back over, that there would be an XZ offset issue, but I'm talking a delta of 7+ pops up, and there's no way the animations jump or move the model over 7 meters.

    I'm pretty sure it's a bug. A weird one.
    Are you in Bellevue, SeanT? I work at Microsoft. It'd be easy for me to demonstrate, someday, if there wasn't this covid19 thing going on. :-( We're doing a lot of Unity stuff over here at Microsoft Research. I always have technical issues because we're "hitting it so hard". it's tough to get questions answered quickly...
     
  6. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Unfortunately I'm not in Bellevue. But feel free to post a small video if possible -

    'In addition to' is a better description, but when dealing with animation between the controller and the timeline it may appear to 'override' as the behaviour can change between Humanoid and Generic models, in particular with non-animated fields in one or the other.

    Admittedly, I'm a bit stumped by a jump of 7 as well, if they are both running idles. My guess was there is an accumulation of root motion happening somewhere. If you apply an ease out to the last clip on the track, and see if it blends out to 7, that might give a hint to the cause. Other than that, do you have multiple animation tracks on the same target? They will layer in playmode, but not in editor.
     
  7. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    While I have you on the hook... I'm having another issue w/ "rotation". The avatar in the scene has a normal forward vector. That is, if you move it "forward" according to its axis, in the Z direction, it's as if it was a normal human, walking forwards. That is, +Z is "face forward". Now, I want this avatar to face the camera, so I put a rotation of 180 into the Y rot... Next, I import an idle animation from Miximo... let's suppose I bake all the parameters into the animation upon import (shouldn't matter). Unity shows +Z on the animation as being "face forward". Super. Now, I put this animation into the animator and preview it. Looks fine, the character idles in place staring at the camera. Now instead, I put the animation onto a Timeline, take it out of the Animator, and preview it. Suddenly, the model is facing AWAY from the camera, doing it's idle thing! I'm pretty sure this is a bug. I described this on another thread, didn't hear back.

    I'm trying to make a video of the above issue with the jump. Will let you know when I've posted it to youtube.
     
  8. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    540
    I know this post is a few months, but I have a similar situation, I want to create a timeline for CS (currently only animations), but the player can pick different characters at runtime (but they are all humans and have the same animation), but since the player selects the character at runtime I can't reference it in the timeline, that's the recommend way to handle this?

    To create the timeline I just dragged one of the possible characters into the scene and added all movements etc and it works fine with this one character, but now im wondering how to change it at runtime.

    Should I use the generic binding method like mentioned above or am I missing something obvious?

    But let's assume that I should use the generic binding method like above, how do I actually add the check "check to see if this is the one you are looking for (by name, index etc)", because the timeline has multiple animations / animators, there are also animations for scene objects which shouldn't change, I would need to add some check like "does this animation track reference my dummy character animation) and only change these, but I didn't find a way to check the current animator reference of the track.
     
  9. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    540
    Nvm I realized that there is also a GetGenericBinding and not just set, so I foreach over all outputs, get the current binding and check if the current binding is my dummy game object and then update the binding with the current player character. Works fine so far, not sure if there is a better way to handle this.
     
  10. EricHFrazer

    EricHFrazer

    Joined:
    Jun 30, 2020
    Posts:
    20
    I'm BroncoBilli... I think the whole answer to this was to go into the animation track and make sure to set "apply scene offsets", NOT "apply track offsets". I think the animator's "apply root motion" was not the issue here. It's NOT obvious one needs to set that track flag.

    I have an automatic script now that sets these flags up upon any playable director running. it's the handiest script in the world for an avatar that has to be animated by 100 different timelines. It assigns the animation track to the avatar, the lip sync track to the avatar, the sound emitter, and a bunch of other stuff... Good times...
     
  11. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    540
    I think I just had a similar problem as you, Im using a parent game object (which has the animator) and the actual model as it's child, the child has a Y rotation of 180. Now I made a timeline animation which moves the parent object position and suddenly the child of this parent objects transform is changed to 0 in the timeline even when literally nothing should change the position of the child, because it's not referenced anywhere in the timeline, I checked multiple times to make sure that the animation clip only changes the position property of the parent and not the child. I will check tomorrow if your solution will also fix my problem, otherwise I have no idea why it happens to the child.

    But tbh timeline maybe overkill for my needs anyways, I just want to play some animation clips and wait until they are done before I show the next dialog line and I can do the same thing with an animator and the Play(statename) method anways, I wanted to play around with timeline a bit but it seems like it just makes it more complicated for my use case instead of easier.