Search Unity

Change AnimationTrack clip at runtime

Discussion in 'Timeline' started by daxiongmao, Aug 16, 2018.

  1. daxiongmao

    daxiongmao

    Joined:
    Feb 2, 2016
    Posts:
    271
    I was hoping that it might be possible to use Timeline and the AnimatorOverrideController together.
    Where the clip specified in the timeline would be replaced by the clip in the AnimatorOverrideController on the Animator.

    From what I searched it doesn't seem this is possible. As the timeline drives the clip properties directly.

    So my other thought was to try and do this on the timeline directly. Look at the existing clip name and replace it with the correct overridden one. The clips length etc would be same.

    After getting an AnimationTrack and its GetClips the animationClip is readonly.

    The use case is so I can switch characters and use the same timeline at runtime.
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    883
    If you have the timeline clip, you can change the animation clip at runtime using something like
    ((AnimationPlayableAsset) clip.asset).clip = overrideAnimationClip;

    Make sure the playable director isn't playing already, and you should probably change it back (even in Playmode the change will be permanent).

    i.e. .
    1. Stop the playable director
    2. Change the clip(s)
    3. Play the playable director (or call RebuildGraph)
    4. Change it back.

    At step 3 the timeline asset is 'compiled' into a playable graph. Once the graph is playing, the asset can be restored.

    Hope that helps.
     
  3. tbriley

    tbriley

    Joined:
    Sep 10, 2013
    Posts:
    110
    sorry for the necro-bump, but i'm trying to do i think the same thing and not yet at the stage of having the timeline clip...

    the problem i'm actually trying to solve is i need a boatload of tutorials but 90%+ of the content is identical. i thought this would be straightforward with timeline and a good excuse to really dig into the tool. i could just build the graph entirely dynamically but what i'd like to do is visually map out the sort of base "templates" and then override / swap some of the animations in some of the tracks. some sketch-code:

    Code (CSharp):
    1.  
    2. //data is a scriptable object that references the root / template asset as well as some animations and text to swap out
    3. playableDirector.playableAsset = data.Timeline;
    4.  
    5. var bindings = data.Timeline.outputs;
    6. foreach (var binding in bindings)
    7. {
    8.   if (binding.streamName == "TextSwitcherTrack")
    9.   {
    10.     playableDirector.SetGenericBinding(binding.sourceObject, tutorialDescription);
    11.     //here i'd like to swap out some of the text in the text switcher track clips
    12.   }
    13.   else if(binding.streamName == "TutorialTrack")
    14.   {
    15.     var animationTrack = binding as AnimationTrack;
    16.     //here i'd like to swap out some of the animations in the animation track clips
    17.   }
    18. }
    19. playableDirector.time = 0;
    20. playableDirector.Play();
    21.  
     
    Last edited: Feb 12, 2019
  4. tbriley

    tbriley

    Joined:
    Sep 10, 2013
    Posts:
    110
    neat, apparently this works:

    Code (CSharp):
    1.  
    2. //data is a scriptable object that references the root / template asset as well as some animations and text to swap out
    3. playableDirector.playableAsset = data.Timeline;
    4.  
    5. var bindings = data.Timeline.outputs;
    6. foreach (var binding in bindings)
    7. {
    8.   if (binding.streamName == "TextSwitcherTrack")
    9.   {
    10.     playableDirector.SetGenericBinding(binding.sourceObject, tutorialDescription);
    11.     var track = binding.sourceObject as TextSwitcherTrack;
    12.     var clips = track.GetClips();
    13.     for (var i = 0; i < data.TextOverrides.Count && i < clips.Count(); i++)
    14.     {
    15.       var clip = clips.ElementAt(i).asset as TextSwitcherClip;
    16.       clip.template.text = data.TextOverrides[i];
    17.     }
    18.   }
    19.   else if(binding.streamName == "TutorialTrack")
    20.   {
    21.     var track = binding.sourceObject as AnimationTrack;
    22.     var clips = track.GetClips();
    23.     for (var i = 0; i < data.AnimationOverrides.Count && i < clips.Count(); i++)
    24.     {
    25.       var clip = clips.ElementAt(i).asset as AnimationPlayableAsset;
    26.       clip.clip = data.AnimationOverrides[i];
    27.     }
    28.   }
    29. }
    30. playableDirector.time = 0;
    31. playableDirector.Play();
    32.  
     
  5. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    898
    Thanks for that example code that was very helpful.
    I want to dynamically change the cliptext in the update loop so I can update some ugui text.
    The clip.template.text field is being changed by my script. I can see the updated value in the inspector but only if i move the mouse. If I click on the gameobect in the hierarchy that has the playable director component attached at any point it updates the uGUI text object but not always with correct value.

    If I press play and touch nothing then the text is never updated in the UI

    Code (CSharp):
    1.  
    2.     // Update is called once per frame
    3.     void Update()
    4.     {
    5.         if (videoPlayer == null) return;
    6.         bar = (float) (videoPlayer.time / videoPlayer.length);
    7.         Debug.Log("Bar =" + bar);
    8.  
    9.         if (clip == null) return;
    10.         percent = ((int)(bar * 100));
    11.         if (percent > lastPercent )
    12.         {
    13.             sPercent = percent.ToString() + " %";
    14.             Debug.Log("Percent =" + sPercent);
    15.             clip.template.text = sPercent;
    16.             lastPercent = percent;
    17.         }
    18.         sb.size = bar;
    19.     }
    20.  
    I am guess this set text is only being called at the clip beginning? Is there a way to force a refresh on each text update.
     
    Last edited: Jun 30, 2019