Search Unity

Timeline - Available in Unity 2017.1

Discussion in 'Timeline' started by gekidoslayer, Feb 7, 2017.

  1. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    You cannot set a default duration for clips with custom PlayableAssets right now. We'll consider this feature for future releases.

    Here's how to use exposed references:
    Code (CSharp):
    1.  
    2. public class TestPlayableAsset : PlayableAsset
    3. {
    4.     [SerializeField] public ExposedReference<GameObject> reference;
    5.  
    6.     public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
    7.     {
    8.         GameObject aReference = reference.Resolve(graph.GetResolver());
    9.  
    10.         return Playable.Create(graph);
    11.     }
    12. }
    13.  
     
  2. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    You can use a Control Track to do this. In your timeline, add a Control Track, then a Control Playable Asset. In Source Game Object, drag the GameObject which contains the PlayableDirector you wish to control. This new timeline will drive the time of the PlayableDirector attached to it.
     
  3. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Yes, you can use the TrackBindingType attribute. See my answer here for more details: https://forum.unity3d.com/threads/custom-track-object-binding.463657/#post-3014371
     
  4. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Do you have a use case for this? I don't see why you would need an OnDestroy method.

    You can override the OnPlayableDestroy method in PlayableBehaviour. Maybe this is what you are looking for.
     
  5. dnoparker

    dnoparker

    Joined:
    Aug 28, 2013
    Posts:
    63
    Can you use the timeline to activate/run certain scripts?
     
  6. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    862
    Did anyone make a custom TrackAsset for the new VideoPlayer? It would make sense for UT to implement this natively, similar to AudioTrack.
     
  7. HugMat

    HugMat

    Joined:
    Mar 30, 2017
    Posts:
    16
    I'm working on CinemachineTracks via script. I've managed to add a new default clip to a CinemachineTrack (which is then a Cinemachine Shot), but I don't know how to add a virtualCamera to this shot. haven't found anything in the API...
    Is there a way to do so ?

    Thanks a lot
     
  8. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    862
    I have created a custom track for the new VideoPlayer. It works, but I doubt that this is how the API was intended to be used. For example; Is it really necessary to resolve the exposed reference to the VideoClip both in PlayableAsset.CreatePlayable and TrackAsset.CreatePlayable ?

    I find the Playable framework and it's integration into Timeline really difficult to grasp. More examples and perhaps a diagram would be very useful. If anyone can improve the script below, please post.

    ~ce

    TimelineVideoplayer.PNG


    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Playables;
    6. using UnityEngine.Timeline;
    7. using UnityEngine.Video;
    8.  
    9. [System.Serializable]
    10. public class VideoPlayable : PlayableAsset, ITimelineClipAsset
    11. {
    12.     public ExposedReference<VideoClip> clip;
    13.  
    14.     public ClipCaps clipCaps { get { return ClipCaps.None; } }
    15.  
    16.  
    17.     public override Playable CreatePlayable( PlayableGraph graph, GameObject owner )
    18.     {
    19.         ScriptPlayable<VideoPlayableBehaviour> playable = ScriptPlayable<VideoPlayableBehaviour>.Create( graph );
    20.  
    21.         // Assign VideoClip to VideoPlayableBehaviour.
    22.         VideoPlayableBehaviour behaviour = playable.GetBehaviour();
    23.         VideoClip videoClip = clip.Resolve( graph.GetResolver() );
    24.         behaviour.clip = videoClip;
    25.  
    26.         return playable;
    27.     }
    28. }
    29.  
    30.  
    31. [System.Serializable]
    32. public class VideoPlayableBehaviour : PlayableBehaviour
    33. {
    34.     public VideoPlayer player;
    35.     public VideoClip clip;
    36.  
    37.  
    38.     public override void OnBehaviourPlay( Playable playable, FrameData info )
    39.     {
    40.         if( !Application.isPlaying ) return;
    41.  
    42.         // Assign clip to player.
    43.         if( clip && player.clip != clip ) player.clip = clip;
    44.  
    45.         // Play to request the video to be loaded.
    46.         player.Play();
    47.  
    48.         // Pause if timeline is not playing.
    49.         bool isTimelinePlaying = playable.GetGraph().IsPlaying();
    50.         if( !isTimelinePlaying ) player.Pause();
    51.     }
    52.  
    53.  
    54.     public override void OnBehaviourPause( Playable playable, FrameData info )
    55.     {
    56.         if( !Application.isPlaying ) return;
    57.  
    58.         if( player ) player.Pause();
    59.     }
    60.  
    61.  
    62.     public override void PrepareFrame( Playable playable, FrameData info )
    63.     {
    64.         if( !Application.isPlaying ) return;
    65.        
    66.         // Play if timeline is playing and player is not playing
    67.         bool isTimelinePlaying = playable.GetGraph().IsPlaying();
    68.         float clipTime = (float) playable.GetTime();
    69.         if( isTimelinePlaying ){
    70.             if( !player.isPlaying ){
    71.                 player.time = clipTime;
    72.                 player.Play();
    73.             }
    74.         } else { // Scrub.
    75.             player.time = clipTime;
    76.         }
    77.  
    78.         // TODO check video player time against timeline clip time and sync if outside freewheel extents.
    79.     }
    80. }
    81.  
    82.  
    83. [System.Serializable]
    84. [TrackColor(0.8f, 0f, 0f)]
    85. [TrackClipType(typeof(VideoPlayable))]
    86. [TrackBindingType(typeof(VideoPlayer))]
    87. public class VideoTrack : TrackAsset
    88. {
    89.    
    90.     protected override Playable CreatePlayable( PlayableGraph graph, GameObject go, TimelineClip clip )
    91.     {
    92.         ScriptPlayable<VideoPlayableBehaviour> playable = ScriptPlayable<VideoPlayableBehaviour>.Create( graph );
    93.  
    94.         // Assign the VideoPlayer (that is binded the track) to VideoPlayableBehaviour.
    95.         PlayableDirector timeline = go.GetComponent<PlayableDirector>();
    96.         VideoPlayer player = timeline.GetGenericBinding( this ) as VideoPlayer;
    97.         VideoPlayableBehaviour behaviour = playable.GetBehaviour();
    98.         behaviour.player = player;
    99.  
    100.         // Assign VideoClip to VideoPlayableBehaviour.
    101.         VideoPlayable videoAsset = clip.asset as VideoPlayable;
    102.         VideoClip videoClip = videoAsset.clip.Resolve( graph.GetResolver() );
    103.         behaviour.clip = videoClip;
    104.  
    105.         return playable;
    106.     }
    107. }
    108.  
     
  9. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    I'm not sure I understand what the problem is... Is it that the drag n drop operation is not working? Or that the inspector doesn't show the right thing? I need more information in order to help you.
     
  10. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Do you have an example? I'm not sure why you need to remove a few frames on the clip.

    This is a good idea! We'll consider your idea when planning for new features.
     
  11. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Yes! You can write custom clips and tracks in Timeline, which will let you run your scripts. See the Timeline examples on this thread's first post to get started.
     
  12. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    One of my colleagues wrote a VideoScriptPlayable! Let me know if this works for you.
     

    Attached Files:

    cecarlsen likes this.
  13. bingob0y

    bingob0y

    Joined:
    Nov 19, 2016
    Posts:
    4
    Why can't record in Animation Track in play mode?I think the function is useful.
     
  14. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    56
    Hi there,

    Timeline looks great, but I'm struggling to figure out how to trigger a particle effect with it. Am I missing something obvious?

    EDIT - Found it. There's an example in the example project of creating your own script for triggering particles.
     
    Last edited: Jul 10, 2017
  15. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    You can also use a Control Track to use a particle system with Timeline.
     
  16. thierry_unity

    thierry_unity

    Joined:
    Jun 10, 2015
    Posts:
    187
    There is technical issues preventing us to do it right now. But we are looking into it.
     
  17. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    190
    i'm also having issues. i'm not on the latest Timeline/2017 beta version, so that may be the issue. it seems what i get in Preview mode and what i get when playing the scene back are different, which makes editing animations pretty frustrating. when i'm in Editor mode i can can set root offsets for the animated object, but when i play back the animation, the root positions basically revert back relative to whatever the original animation put them as. so if i edit say the characters Y height root position to make it lower in the preview mode, it will appear higher when playing the scene back, leaving the only option to adjust the root offset on the animation FBX import properties itself.

    i have tried to click the record button to record movement per the manual instructions, but no keyframes seem to be created. i suspect that keyframes may not be working as the interface allows going to individual frames or animation boundaries via keystroke, but not keyframes. also no curves appear that can be edited and there's no documentation for it. is it also possible that i have to convert the curve or keyframes to an animation before it appears in Scene playback?

    any answers appreciated! thanks!
     
  18. fnan

    fnan

    Joined:
    Jun 15, 2017
    Posts:
    1
    Hello,
    I am using Timeline, Unity 2017.1.0f2 - version, There is a problem I couldn't fix!!
    I recorded a custom Animation track for my character and applied Track Offsets on it. Everything works when I play the preview from the Timeline editor but I play the game,then it starts animating from (0,0,0). Also it adds the offset values and put the character on the desired position when exited play mode, but never on Game play mode. Can you help me ??
     
    Last edited: Jul 12, 2017
    metaphysician likes this.
  19. xarcius

    xarcius

    Joined:
    Dec 3, 2014
    Posts:
    8
    I recorded a video of a problem that occurs sometimes. Is it a bug? The animation I allocate to the Timeline of a Gameobject moves to coordinate (0,0,0). This happens when I select the mod Scene. Thanks for reply

     
  20. guoliulong

    guoliulong

    Joined:
    Aug 16, 2012
    Posts:
    14
    Hello,I read CinemachineMixer code,but i dont know where param playerData comes from? how you set the playerData






    public sealed class CinemachineMixer : PlayableBehaviour
    {
    // The brain that this track controls
    private CinemachineBrain mBrain;
    private int mBrainOverrideId = -1;

    public override void OnGraphStop(Playable playable)
    {
    if (mBrain != null)
    mBrain.ReleaseCameraOverride(mBrainOverrideId); // clean up
    mBrainOverrideId = -1;
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
    base.ProcessFrame(playable, info, playerData);

    // Get the brain that this track controls.
    // Older versions of timeline sent the gameObject by mistake.
    GameObject go = playerData as GameObject;
    if (go == null)
    mBrain = (CinemachineBrain)playerData;
    else
    mBrain = go.GetComponent<CinemachineBrain>();
    if (mBrain == null)
    return;
     
  21. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    playerData is your track's bound object:
     
  22. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    190
    If you watch my short tutorial here on youtube (and download my github actions for timeline and playmaker), you can control a whole host of things using playmaker (including triggering a timeline to play). These actions should have an official release in the playmaker ecosystem in the next week or so when I get a chance.

    Playmaker Actions: https://github.com/dumbgamedev/timeline-playmaker

     
    theANMATOR2b, zeb33, kustom and 2 others like this.
  23. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    190
    Being able to reverse the timeline via calling a method would be amazing. Even in pretty simple applications. Enter trigger, door starts to animate open. Exit trigger, timeline reverses and the door starts to close again. Enter again and it once again plays forwards. Currently I dont see a reasonable way to do this.
     
    theANMATOR2b and mfCleRIC like this.
  24. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    190
    When the timeline is paused, the enable track gameobjects become enabled (even if they were disabled before the timeline started). This seems like a bug. Basically if my cutscene is paused, then all the particle effects suddenly start playing.
     
  25. John3D

    John3D

    Joined:
    Mar 7, 2014
    Posts:
    441
    Awesome new feature! Thanks!
     
  26. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Currently, there is no method you can call to reverse a timeline. However, with a little bit of setup, it is possible to reverse a timeline. See this post for more information.
     
    tcmeric likes this.
  27. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Do you have the steps to reproduce your issue?
     
  28. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    190
    Thank you. I also posted an issue here, to which I got a nice reply. Basically I was looking for a way to reverse it via a mono script. I am writing action (c# snippets) for playmaker, to control timeline. However, actions need to be run from within playmaker. https://forum.unity3d.com/threads/r...ance-from-playable-director-component.484125/

    I am still looking to see if it is possible to get all of the instances of playables within a playableDirector component. I am somewhat of a beginner c# programmer, so I wasent able to see a way via the API documentation, and havent seen any examples yet. I dug through all the examples posted on this thread. (Which have been helpful in writing the other C# snippets/actions).

    Ideally, I would love to be able to mute tracks for example, in a running timeline, or add animations at X time, etc.
     
  29. AutoFire-II

    AutoFire-II

    Joined:
    Oct 30, 2015
    Posts:
    4
    First off, I love the Timeline system! Cinemachine doesn't quite fit into my current project, but it also looks great.

    Unfortunately the documentation isn't super clear on the code-side. I understand that, as a beta feature, the top priority should be getting Timeline working nicely, so no worries there.

    But I want to know: has anyone done any custom tracks with key frames? I currently have an enemy that fires bullets by enabling a child game object. I'm currently using an Activation Track to do this, but it doesn't make a lot of sense; I want to enable my game object for quick, one-frame-long pulses, rather than entire clips. For this, a way to just be able to pick a point in time to fire makes more sense. Key frames seem more fitting for my needs, so I'd like to be able to make a custom track for this. (Note: I've yet to look much at other's examples. I will do that soon, but I've been pretty busy with other things. I just want to know if it's possible in 2017.1.0f3)

    On that note, when working with really tiny clips, the interface becomes rather painful. The mouse always opts to resize the clip, as opposed to dragging it around. If I want to drag a small clip around, I need to grow the clip, move it, and then shrink it. Also, it does nothing to right-click on short clips; they have to be lengthened in order to right-click the center of the clip.

    I know that I could always fiddle with the inspector, but it's much more convenient to manipulate the clip from the Timeline view.
     
  30. xDavidLeon

    xDavidLeon

    Joined:
    Jun 9, 2014
    Posts:
    123
    Adding a Cinemachine Collider to a Cinemachine Free Look gives me a NullReferenceException.

    Looks like in UpdateRigCache(), m_Rigs content becomes pointers to null for some reason. It was previously populated properly.
     

    Attached Files:

    Last edited: Jul 31, 2017
  31. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    Hi,
    I intend to write a playable for my custom voice over format, which holds audio and text for all languages.
    The problem is: One line of audio might have different lengths in different languages.

    Take this timeline from witcher3 for example:

    english:

    french:

    time offset comparison of these two:


    So my question is:
    1: Can I somehow create a custom VoiceOver clip, which reveals its real length at runtime?
    2: And can I somehow tell the following clips to offset relative to the end of the VoiceOver clips?
     
    Last edited: Aug 1, 2017
    AA-Matt likes this.
  32. xDavidLeon

    xDavidLeon

    Joined:
    Jun 9, 2014
    Posts:
    123
    Hi again,

    Is there any way to make Cinemachine Brain ignore timescale? I've got slow motion events in my game and I don't want the camera input to slow down when those happen.

    Right now, I need to modify the source code in CinemachineBrain.cs like this:

    Code (CSharp):
    1.         private float GetEffectiveDeltaTime(bool fixedDelta)
    2.         {
    3.             OverrideStackFrame activeOverride = GetActiveOverride();
    4.             float deltaTime = (Application.isPlaying || SoloCamera != null)
    5.                 ? (fixedDelta ? Time.fixedDeltaTime : Time.deltaTime) : 0;
    6.             if (ignoreTimeScale)
    7.                 deltaTime = (Application.isPlaying || SoloCamera != null)
    8.                 ? (fixedDelta ? Time.fixedUnscaledDeltaTime : Time.unscaledDeltaTime) : 0;
    9.             if (activeOverride != null)
    10.                 deltaTime = activeOverride.deltaTime;
    11.             return deltaTime;
    12.         }
    I'd prefer if Cinemachine would support this natively :)
     
  33. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Yes this is a known issue, which has been fixed on the CM trunk. The fix will be in the next CM point release, coming soon.
     
  34. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    I like your fix. I assume ignoreTimeScale is a checkbox on the brain inspector. Is it working for you?
     
  35. xDavidLeon

    xDavidLeon

    Joined:
    Jun 9, 2014
    Posts:
    123
    Yes, currently working with no issues so far. Really useful for game rigs when I want to add a short slowmo effect but want to stick to normal camera behavior.
     
    theANMATOR2b likes this.
  36. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Sweet. We will absorb this into the next CM release. Thanks!
     
  37. xDavidLeon

    xDavidLeon

    Joined:
    Jun 9, 2014
    Posts:
    123
    Regarding the timescale fix, the only bug I've noticed is that camera behavior becomes jittery when using a Free Look camera in slow motion with a Follow target (that is a rigidbody) and the camera is selected in the Scene (so that you see the blue guidelines in the Game window). The jitter disappears if I unselect the camera, so it's probably related to showing guidelines + lowered Time.timescale + Fixed Update mode?

    Hope that helps.
     
  38. IronManBK

    IronManBK

    Joined:
    Jul 12, 2017
    Posts:
    7
    Hi everyone, i built 2 timelines, but how do i merge them together ? Thanks
     
  39. xtyler

    xtyler

    Joined:
    Dec 8, 2012
    Posts:
    12
    I have found that you can set default duration via override. However I'm still looking for a good way to reference the Track's Binding from the PlayableAsset (not a clip's exposed reference). I'm using a hacky work-around by setting it on the PlayableBehaviour from within the Mixer.

    Code (CSharp):
    1.  
    2.    public class CustomMixer : PlayableBehaviour
    3.    {
    4.       public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    5.       {
    6.          var skeleton = (Skeleton) playerData;
    7.          if (customAnimation == null)
    8.             return;
    9.  
    10.          int inputCount = playable.GetInputCount();
    11.          for (int i = 0; i < inputCount; i++)
    12.          {
    13.             var inputPlayable = (ScriptPlayable<CustomAnimationBehaviour>)playable.GetInput(i);
    14.             var behaviour = inputPlayable.GetBehaviour();
    15.  
    16.             behaviour.skeleton = skeleton;
    17.          }
    18.       }
    19.    }
    20.  
    Code (CSharp):
    1.  
    2.    public class CustomAnimation : PlayableAsset
    3.    {
    4.       public string animationName;
    5.       public CustomAnimationBehaviour data;
    6.  
    7.       public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    8.       {
    9.          var playable = ScriptPlayable<CustomAnimationBehaviour>.Create(graph);
    10.          data = playable.GetBehaviour();
    11.          return playable;
    12.       }
    13.  
    14.       public override double duration
    15.       {
    16.          // skeleton is being set by Mixer
    17.          get { return data.skeleton.GetAnimation(animationName).duration; }
    18.       }
    19.    }
    20.  
     
  40. xtyler

    xtyler

    Joined:
    Dec 8, 2012
    Posts:
    12
    I have been unable to find any information on how to use DirectorUpdateMode.Manual. From the docs: "You need to manually call PlayerController.Tick with your own deltaTime." PlayerController is part of Unity's networking. I've tried advancing PlayableDirector.time directly but while it advances the playhead, it doesn't execute the timeline clips.
     
  41. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548
    Hi there!

    Can we set "foot ik" on the timeline clips when adding animations?

    Thanks!
     
  42. zeb33

    zeb33

    Joined:
    Nov 17, 2014
    Posts:
    95
    Hi
    I've seen other posts with same/similar question but cannot see an answer.
    My scene looks fine when scrubbing the timeline but is messed up (offsets change) in playmode. Is there an obvious cause I'm missing? Thanks.
     
  43. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548
    Maybe you ar making changes with the preview mode on. Some times it is a bit confusing when the preview turns on automaticly. Turn it off, do some changes to be the default and then edit the timeline with prview on. On the top left corner, in case you don't know.

    Hope this help.
     
  44. spiraloid

    spiraloid

    Joined:
    Aug 11, 2015
    Posts:
    7
    hey all. I appreciate these unity forums so much I thought I'd give back a little.

    below is a crude script that generates a Timeline, sets up a director, searches the scene for all objects with a tag and then creates an activation track foreach gameObject with that tag.

    sort of like doing replacement animation with activation tracks. I'm doing a lot of trial and error as I get more familiar with playables. It was mainly from me coding by bumpercar, but with lots of handy snippets from this forum and the docs. It's a crude work in progress as I learn, but It's got some handy bits in it others might find usefull.

    these were the questions I answered making this (for the googlers):

    how do I make a Timeline with a script?
    how do I make clips with a script?
    how do I make create a sequence of activating gameObject with a script and playables?

    it's mostly working.. (but for some reason the activation tracks do not activate the objects, only deactivate?) odd bug I'm not sure how to solve yet.

    if you want to check them out, be sure to install the both the scripts somewhere in your project and call them:

    SnapshotByTag.cs
    SnapshotByTagInspectorUI.cs

    usage:
    make a scene with lots of objects tagged.
    add SnapshotByTag.cs onto a gameObject in the scene.
    Enter the string you tagged all your objects with and push the Snapshot button.
    this will generate a timeline with all the activation clips setup.

    Code (CSharp):
    1. Assets/generated_snapshotTimelineAsset.playable
    in the Hierarchy, reselect your gameObject and in the timeline you will see a trackGroup called ActivationTrackGroup. It should look like this when openned.








    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.Timeline;
    4. using UnityEngine.Animations;
    5. using UnityEngine.Playables;
    6. using UnityEngine.SceneManagement;
    7. using UnityEditor;
    8. using UnityEditorInternal;
    9. using UnityEditor.SceneManagement;
    10. using System.Collections.Generic;
    11. using System.Reflection;
    12. using System.Linq;
    13.  
    14. [ExecuteInEditMode]
    15. public class SnapshotByTag : MonoBehaviour {
    16.     public string searchByTag = "myTag";
    17.     private GameObject[] taggedObjects;
    18.     private string timelineAssetFilePath = "Assets/generated_snapshotTimelineAsset.playable";
    19.     TimelineAsset newTimelineAsset;
    20.     private GroupTrack activationGroupTrack;
    21.     private ActivationTrack activationTrack;
    22.     private PlayableDirector director;
    23.     private TimelineAsset timeline;
    24.  
    25.     public void Snapshot()
    26.     {
    27.         // delete the playable director if one exists.
    28.         director = this.gameObject.GetComponent<PlayableDirector>();
    29.         if (director != null)
    30.         {
    31.             DestroyImmediate(director);
    32.         }
    33.  
    34.         // delete the generated timeline playable asset if one exists.
    35.         if (System.IO.File.Exists(timelineAssetFilePath))
    36.         {
    37.             FileUtil.DeleteFileOrDirectory(timelineAssetFilePath);
    38.         }
    39.  
    40.         // find all objects by tag and sort them
    41.         taggedObjects = GameObject.FindGameObjectsWithTag(searchByTag).OrderBy(go => go.name).ToArray();
    42.  
    43.         //create new timeline.playable asset and attach it to a new playable director on current gameobject.
    44.         newTimelineAsset = CreateTimelineAsset(timelineAssetFilePath);
    45.         timeline = CreatePlayableAsset<TimelineAsset>(newTimelineAsset, "newTimeline");
    46.         director = this.gameObject.AddComponent<PlayableDirector>();
    47.         this.gameObject.GetComponent<PlayableDirector>().playableAsset = newTimelineAsset;
    48.  
    49.         // create activation trackgroup
    50.         activationGroupTrack = CreateTrackAsset<GroupTrack>(newTimelineAsset, "ActivationTrackGroup");
    51.  
    52.         // process all tagged objects
    53.         for (int i = 0; i < taggedObjects.Length; ++i)
    54.         {
    55.             var activationTrackAsset = CreatePlayableAsset<ActivationTrack>(newTimelineAsset, (taggedObjects[i].name));
    56.             activationTrack = CreateTrackAsset<ActivationTrack>(newTimelineAsset, "Activate_" + (taggedObjects[i].name), activationGroupTrack);
    57.             TimelineClip activationClip = CreateTimelineClip(activationTrack, activationTrackAsset);
    58.             activationClip.start = i;
    59.             activationClip.duration = 1;
    60.             director.SetGenericBinding(activationTrack, (taggedObjects[i]));
    61.         }
    62.  
    63.         // rehash
    64.         AssetDatabase.SaveAssets();
    65.         AssetDatabase.Refresh();
    66.         UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
    67.  
    68.         //tbd
    69.         //set game window size.
    70.         //export images
    71.  
    72.     }
    73.  
    74.  
    75.     // borrowed web scripts with a slightly better object interface.
    76.     public static TimelineAsset CreateTimelineAsset(string path)
    77.     {
    78.         var timelineAsset = ScriptableObject.CreateInstance<TimelineAsset>();
    79.         AssetDatabase.CreateAsset(timelineAsset, path);
    80.         return timelineAsset;
    81.     }
    82.  
    83.     public static T CreateTrackAsset<T>(TimelineAsset timelineAsset, string trackName, TrackAsset parent = null) where T : TrackAsset
    84.     {
    85.         return (T)timelineAsset.CreateTrack(typeof(T), parent, trackName);
    86.     }
    87.  
    88.     // this seems to have a bug if AnimationClip is passed to it as a type.
    89.     public static T CreatePlayableAsset<T>(TimelineAsset timelineAsset, string playableAssetName) where T : PlayableAsset
    90.     {
    91.         var playableAsset = (T)ScriptableObject.CreateInstance(typeof(T));
    92.         playableAsset.name = playableAssetName;
    93.         AssetDatabase.AddObjectToAsset(playableAsset, timelineAsset);
    94.         return playableAsset;
    95.     }
    96.  
    97.     public static TimelineClip CreateTimelineClip(TrackAsset parent, PlayableAsset playableAsset)
    98.     {
    99.         var timelineClip = parent.CreateDefaultClip();
    100.         timelineClip.asset = playableAsset;
    101.         return timelineClip;
    102.     }
    103.  
    104.     public static void AddAnimationClip(AnimationTrack trackAsset, TimelineClip timelineClip, AnimationClip clip)
    105.     {
    106.         if (timelineClip.asset as AnimationPlayableAsset == null)
    107.         {
    108.             Debug.LogError("null AnimationPlayableAsset");
    109.             return;
    110.         }
    111.         var setClipFieldInfo = typeof(TrackAsset).GetField("m_AnimClip", BindingFlags.NonPublic | BindingFlags.Instance);
    112.         setClipFieldInfo.SetValue(trackAsset, clip);
    113.         var setRecordableFieldInfo = typeof(TimelineClip).GetField("m_Recordable", BindingFlags.NonPublic | BindingFlags.Instance);
    114.         setRecordableFieldInfo.SetValue(timelineClip, true);
    115.         (timelineClip.asset as AnimationPlayableAsset).clip = clip;
    116.         AssetDatabase.AddObjectToAsset(clip, trackAsset.timelineAsset);
    117.     }
    118.  
    119.     static void TimelineCreateTest()
    120.     {
    121.         var timelineAsset = CreateTimelineAsset("Assets/test.playable");
    122.         var groupTrack = CreateTrackAsset<GroupTrack>(timelineAsset, "Parent");
    123.         var animationTrack = CreateTrackAsset<AnimationTrack>(timelineAsset, "Child", groupTrack);
    124.         var animationPlayableAsset = CreatePlayableAsset<AnimationPlayableAsset>(timelineAsset, "AnimationPlayableAsset");
    125.         var timelineClip = CreateTimelineClip(animationTrack, animationPlayableAsset);
    126.  
    127.         AddAnimationClip(animationTrack, timelineClip, new AnimationClip { name = "TestRecordable" });
    128.         AssetDatabase.SaveAssets();
    129.     }
    130.  
    131. }
    132.  

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEditor;
    4.  
    5. [ExecuteInEditMode]
    6. [CustomEditor(typeof(SnapshotByTag))]
    7. public class SnapshotByTagInspectorUI : Editor
    8. {
    9.     public override void OnInspectorGUI()
    10.     {
    11.         DrawDefaultInspector();
    12.  
    13.         GUILayout.BeginVertical();
    14.         GUILayout.Space(20);
    15.         GUILayout.BeginHorizontal();
    16.  
    17.         GUILayout.FlexibleSpace();
    18.  
    19.         SnapshotByTag myScript = (SnapshotByTag)target;
    20.         if (GUILayout.Button("Snapshot", GUILayout.Width(80), GUILayout.Height(40)))
    21.         {
    22.             myScript.Snapshot();
    23.         }
    24.         GUILayout.FlexibleSpace();
    25.         GUILayout.EndHorizontal();
    26.         GUILayout.Space(20);
    27.         GUILayout.EndVertical();
    28.     }
    29. }
     
    julienb likes this.
  45. zeb33

    zeb33

    Joined:
    Nov 17, 2014
    Posts:
    95
    Thanks for reply. What do you mean by 'do some changes to be the default'? Is this editing the timeline with preview off? (it turns on as soon as I try)
     
  46. Nanorock

    Nanorock

    Joined:
    Dec 2, 2012
    Posts:
    41
    Hi there,
    I like the idea of timeline, letting my animator sync multiple actors without me having to code much.
    However in our use case, I'm not sure how we can handle animation override.
    Let's say we have a desk, and two actor coming to sit down and chat.
    I know how to inject the proper animator from each actor.
    But now, how can I can make the elf actually play the sit elf animation, and the orc play the orc sit animation ?
    With mecanim I solve that with an override controller, but how would one do that with Timeline ?
     
  47. Carwashh

    Carwashh

    Joined:
    Jul 28, 2012
    Posts:
    762
    Is it possible to assign/ create a ControlTrack/ Clip at runtime and assign the source object? Our use case is having timelines in multiple scenes and wanting to control them from a master timeline in the MainScene.
     
  48. julienb

    julienb

    Unity Technologies

    Joined:
    Sep 9, 2016
    Posts:
    177
    Yes, you can do that. However, in order to add tracks/clips, the timeline (playable director) needs to be stopped, otherwise the changes won't be updated until you stop the director.
     
  49. Carwashh

    Carwashh

    Joined:
    Jul 28, 2012
    Posts:
    762
    How? I spent (wasted?) a few work hours yesterday trying to figure it out and got no where :(
     
  50. Danirey

    Danirey

    Joined:
    Apr 3, 2013
    Posts:
    548