Search Unity

Modify Animation Track offsets during runtime

Discussion in 'Timeline' started by WayneC, Jul 27, 2017.

  1. WayneC

    WayneC

    Joined:
    Jan 15, 2016
    Posts:
    13
    Currently I'm able to align root motion between clips by apply 'match offsets to previous clip' to each clip, but if I play the whole track again, the start position is reset.
    I want the track start from the position where last track ends. I tried to implement a playable which modify animation track offsets after the track ends, but unfortunately I can't find a way to get the animation track reference.
    Is there any way to align root motion between each track play? Thanks.
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Hi,

    Timeline doesn't have a way to do this out of the box, although it is an option we have recently been discussing. One way to do this is using the track offsets on the animation track. Here's an example monobehaviour you could try that automatically sets the track offsets to make the timeline play relative to the current positions of the animated objects.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Timeline;
    6. using UnityEngine.Playables;
    7.  
    8. [RequireComponent(typeof(PlayableDirector))]
    9. public class PlayTimelineRelative : MonoBehaviour
    10. {
    11.     private PlayableDirector director;
    12.  
    13.     void Awake()
    14.     {
    15.         director = GetComponent<PlayableDirector>();
    16.     }
    17.  
    18.     void OnEnable()
    19.     {
    20.         // if the director is playing, timeline changes won't have an effect
    21.         director.Stop();
    22.  
    23.         var timelineAsset = director.playableAsset as TimelineAsset;
    24.         if (timelineAsset == null)
    25.             return;
    26.  
    27.         foreach (var track in timelineAsset.GetOutputTracks())
    28.         {
    29.             var animTrack = track as AnimationTrack;
    30.             // could check for a specifically named track here as well...
    31.             if (animTrack == null)
    32.                 continue;
    33.  
    34.             var binding = director.GetGenericBinding(animTrack);
    35.             if (binding == null)
    36.                 continue;
    37.  
    38.             // the binding can be an animator or game object with an animator
    39.             var animator = binding as Animator;
    40.             var gameObject = binding as GameObject;
    41.             if (animator == null && gameObject != null)
    42.                 animator = gameObject.GetComponent<Animator>();
    43.  
    44.             if (animator == null)
    45.                 continue;
    46.  
    47.             // turn on the track offsets, and apply the current position
    48.             animTrack.applyOffsets = true;
    49.             animTrack.position = animator.transform.position;
    50.             animTrack.rotation = animator.transform.rotation;
    51.         }
    52.  
    53.         // start the director. This will build the graph with embedded offsets
    54.         director.Play();
    55.     }
    56.  
    57.     public void OnDisable()
    58.     {
    59.         if (director == null)
    60.             return;
    61.  
    62.         // turn off the offsets so the editor resets to 0,0,0
    63.         var timelineAsset = director.playableAsset as TimelineAsset;
    64.         if (timelineAsset == null)
    65.             return;
    66.  
    67.         foreach (var track in timelineAsset.GetOutputTracks())
    68.         {
    69.             var animTrack = track as AnimationTrack;
    70.             if (animTrack == null)
    71.                 continue;
    72.  
    73.             animTrack.applyOffsets = false;
    74.         }
    75.  
    76.     }
    77.  
    78. }
    79.  
     
    vonSchlank, Razmot and thierry_unity like this.
  3. WayneC

    WayneC

    Joined:
    Jan 15, 2016
    Posts:
    13
    Thank you for your reply! I test the code just now and it just works as expected!

    And if the binding object is not under the scene root, use 'localPosition' and 'localRotation' instead of 'position' and 'rotation'

     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Yes, right. You can also just move the parent instead of using the script since Timeline only animates the local position.
     
  5. AnthonyReddan

    AnthonyReddan

    Joined:
    Feb 27, 2018
    Posts:
    39
    Hi there,

    I'm attempting to do this currently with
    trackOffset
    since
    applyOffsets
    has been deprecated. It doesn't seem to change anything at runtime. Do I need to force rebuild the graph or something? The director is stopped beforehand and played afterwards as in the sample code above. If I inspect the track in the editor while playing, the value seems set appropriately - it just doesn't actually apply the offset (it works in edit mode if I manually modify the offset on the AnimationTrack).
     
    henry23333 and vonSchlank like this.
  6. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    513
    Also does it work with several Playable directors wanting different relative offset yet playing the same Timeline asset at a single time ?