Change AnimationTrack clip at runtime

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.

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.

1 Like

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:

//data is a scriptable object that references the root / template asset as well as some animations and text to swap out
playableDirector.playableAsset = data.Timeline;

var bindings = data.Timeline.outputs;
foreach (var binding in bindings)
{
  if (binding.streamName == "TextSwitcherTrack")
  {
    playableDirector.SetGenericBinding(binding.sourceObject, tutorialDescription);
    //here i'd like to swap out some of the text in the text switcher track clips
  }
  else if(binding.streamName == "TutorialTrack")
  {
    var animationTrack = binding as AnimationTrack;
    //here i'd like to swap out some of the animations in the animation track clips
  }
}
playableDirector.time = 0;
playableDirector.Play();

neat, apparently this works:

//data is a scriptable object that references the root / template asset as well as some animations and text to swap out
playableDirector.playableAsset = data.Timeline;

var bindings = data.Timeline.outputs;
foreach (var binding in bindings)
{
  if (binding.streamName == "TextSwitcherTrack")
  {
    playableDirector.SetGenericBinding(binding.sourceObject, tutorialDescription);
    var track = binding.sourceObject as TextSwitcherTrack;
    var clips = track.GetClips();
    for (var i = 0; i < data.TextOverrides.Count && i < clips.Count(); i++)
    {
      var clip = clips.ElementAt(i).asset as TextSwitcherClip;
      clip.template.text = data.TextOverrides[i];
    }
  }
  else if(binding.streamName == "TutorialTrack")
  {
    var track = binding.sourceObject as AnimationTrack;
    var clips = track.GetClips();
    for (var i = 0; i < data.AnimationOverrides.Count && i < clips.Count(); i++)
    {
      var clip = clips.ElementAt(i).asset as AnimationPlayableAsset;
      clip.clip = data.AnimationOverrides[i];
    }
  }
}
playableDirector.time = 0;
playableDirector.Play();

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

    // Update is called once per frame
    void Update()
    {
        if (videoPlayer == null) return;
        bar = (float) (videoPlayer.time / videoPlayer.length);
        Debug.Log("Bar =" + bar);

        if (clip == null) return;
        percent = ((int)(bar * 100));
        if (percent > lastPercent )
        {
            sPercent = percent.ToString() + " %";
            Debug.Log("Percent =" + sPercent);
            clip.template.text = sPercent;
            lastPercent = percent;
        }
        sb.size = bar;
    }

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.