Search Unity

Strange Timeline bug with custom track

Discussion in 'Timeline' started by Squeazer, Jun 13, 2021.

  1. Squeazer

    Squeazer

    Joined:
    Aug 4, 2015
    Posts:
    14
    Hey, I've encountered a strange bug with timeline, and I'm mostly sure it's not something I'm doing. I managed to boil down an example to this:

    I have a custom track, that extends TrackAsset and ILayerable:
    Code (CSharp):
    1. [Serializable]
    2. [TrackClipType(typeof(AnimationPlayableAsset), false)]
    3. [TrackBindingType(typeof(Animator))]
    4. public class CustomAnimationTrack : TrackAsset, ILayerable {
    5.  
    6.     public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) {
    7.         return AnimationMixerPlayable.Create(graph, inputCount);
    8.     }
    9.  
    10.     public Playable CreateLayerMixer(PlayableGraph graph, GameObject go, int inputCount) {
    11.         AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(graph, "LayerMixerOutput123", null);
    12.         return Playable.Null;
    13.     }
    14.  
    15. }
    The track just creates an AnimationMixerPlayable for the TrackMixer, and returns Playable.Null for the LayerMixer, but it also creates an instance of AnimationPlayableOutput there. This example does nothing with it but in my "actual" track I do use it.

    So this particular track doesn't do anything exciting (I removed all the irrelevant code), except for one thing. If I have two tracks, each with one clip (or more), the ControlTrack that comes after them will not work. So for example, in this setup:
    Screenshot 2021-06-13 at 22.32.49.png

    The ControlTrack will not work. The clip that is on it is driving a GameObject in the scene with an ITimeControl script on it, that logs all the methods. I get no log in the console. I also don't see anything weird in the playable graph. If I remove one of the custom tracks (or all the clips on one), the ControlTrack starts working normally. Other types of track (e.g. ActivationTrack) work as expected.

    This is happening on Unity 2020.3.11f1. I attached an example project showing the issue.

    Does anyone have an idea what's going on?
     

    Attached Files:

    Last edited: Jun 14, 2021
  2. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    I have attached to this post a working version of your CustomAnimationTrack file.

    You're not supposed to create other outputs in
    CreateTrackMixer
    or
     CreateLayerMixer
    . This is what
     TrackAsset.outputs
    is for.

    Timeline has some strong expectations about the structure of the PlayableGraph. Each track must match an output, and output types should match Playable types.

    I'm not sure what exactly was not working correctly with your setup, but the attached script creates a graph structure that Timeline recognizes.

    If you want to debug your graph, I would suggest that you install the Playable Graph Visualizer like this:

    upload_2021-6-14_10-50-23.png
    upload_2021-6-14_10-51-1.png

    This is what the graph should look like in the PlayableGraph Visualizer (under Window/Analysis/PlayableGraph Visualizer):
    upload_2021-6-14_10-53-48.png

    And this is what yours looked like before my changes:
    upload_2021-6-14_10-55-17.png

    Note the disconnected Animation Outputs.

    If you cannot get your use case to work using
    outputs
    , then you can post a more complete example here, but if you diverge too much from the expected structure, we might not be able to help you.
     

    Attached Files:

  3. Squeazer

    Squeazer

    Joined:
    Aug 4, 2015
    Posts:
    14
    Hey @DavidGeoffroy, thanks for the feedback, I didn't know about "outputs". Doing it that way fixed the issue, thanks! Just for reference, this is my actual track:
    Code (CSharp):
    1. [Serializable]
    2. [TrackClipType(typeof(AnimationPlayableAsset), false)]
    3. [TrackBindingType(typeof(Animator))]
    4. public class AdditiveAnimationTrack : TrackAsset, ILayerable {
    5.  
    6.     public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) {
    7.         return AnimationMixerPlayable.Create(graph, inputCount);
    8.     }
    9.  
    10.     public Playable CreateLayerMixer(PlayableGraph graph, GameObject go, int inputCount) {
    11.         // This mixes the the first layer ("base" track) with all the other layers as additive
    12.         AnimationLayerMixerPlayable layerMixer = AnimationLayerMixerPlayable.Create(graph, inputCount);
    13.         layerMixer.SetLayerAdditive(0, false);
    14.         layerMixer.SetInputWeight(0, 1f);
    15.         for (uint i = 1; i < inputCount; i++) {
    16.             layerMixer.SetLayerAdditive(i, true);
    17.             layerMixer.SetInputWeight((int) i, 1f);
    18.         }
    19.  
    20.         // Create an output to the Animator
    21.         PlayableDirector director = go.GetComponent<PlayableDirector>();
    22.         Animator controller = director.GetGenericBinding(this) as Animator;
    23.         AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(graph, "LayerMixer", controller);
    24.         playableOutput.SetSourcePlayable(layerMixer);
    25.  
    26.         return layerMixer;
    27.     }
    28.  
    29. }
    It's basically an "animation" track with support for additive animations. If I remove the "Create an output to the Animator" section and add an override for outputs, it works and the issue is gone:
    Code (CSharp):
    1. [Serializable]
    2. [TrackClipType(typeof(AnimationPlayableAsset), false)]
    3. [TrackBindingType(typeof(Animator))]
    4. public class AdditiveAnimationTrack : TrackAsset, ILayerable {
    5.  
    6.     public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) {
    7.         return AnimationMixerPlayable.Create(graph, inputCount);
    8.     }
    9.  
    10.     public Playable CreateLayerMixer(PlayableGraph graph, GameObject go, int inputCount) {
    11.         // This mixes the the first layer ("base" track) with all the other layers
    12.         AnimationLayerMixerPlayable layerMixer = AnimationLayerMixerPlayable.Create(graph, inputCount);
    13.         layerMixer.SetLayerAdditive(0, false);
    14.         layerMixer.SetInputWeight(0, 1f);
    15.         for (uint i = 1; i < inputCount; i++) {
    16.             layerMixer.SetLayerAdditive(i, true);
    17.             layerMixer.SetInputWeight((int) i, 1f);
    18.         }
    19.  
    20.         return layerMixer;
    21.     }
    22.  
    23.     public override IEnumerable<PlayableBinding> outputs {
    24.         get {
    25.             yield return AnimationPlayableBinding.Create(name, this);
    26.         }
    27.     }
    28.  
    29. }
    However, the graph looks the same in both cases, which is still weird.
     
  4. DavidGeoffroy

    DavidGeoffroy

    Unity Technologies

    Joined:
    Sep 9, 2014
    Posts:
    542
    If you have the PlayableGraph Visualizer installed, can you post side by side screenshots of the graphs?
     
  5. Squeazer

    Squeazer

    Joined:
    Aug 4, 2015
    Posts:
    14
    Hey David, I was a bit wrong here, the graphs in the two examples do look different:

    Using "outputs":
    graph_outputs_fix.png

    Creating output in CreateLayerMixer:
    graph_nofix1.png

    But the strange part is, if I move the Control Track one space up, so it's between the two animation tracks, it starts working again, but the only thing that changes in the graph is the order:
    graph_nofix2_working.png

    That part still confuses me. Why would just changing the ordering of the track "fix" the issue?