Unity
timeline
Unity2017.1

TimelineAssetをEditor用Scriptから生成するメモ

Editor用ScriptからTimelineAssetを作ったときの要点メモです
Unity2017.1.0f3
(ver上がるとAPIはいろいろ変わったり増えたりしそう)

要点

TrackAssetはTimelineAsset.CreateTrackで生成
PlayableAssetやRecordableなAnimationClipはAssetDatabase.AddObjectToAssetを使ってTimelineAssetの子にする
https://docs.unity3d.com/ScriptReference/AssetDatabase.AddObjectToAsset.html
(通常UI操作で追加されるPlayableAssetはasset.hideFlags = HideFlags.HideInHierarchy;してある)

Timelineの構成

TimelineAsset.png
参考: http://www.shibuya24.info/entry/timeline_basis

TimlineAsset

TrackAssetを束ねる長
あとは全体の再生時間設定ぐらいしか持ってない
https://docs.unity3d.com/2017.1/Documentation/ScriptReference/Timeline.TimelineAsset.html

TrackAsset

シーン上のObjectとバインドする
TimelineClipを束ねて保持している
継承していろいろ種類がある
https://docs.unity3d.com/2017.1/Documentation/ScriptReference/Timeline.TrackAsset.html

TimelineClip + PlayableAsset

TimelineClipは、いつからいつまで どうブレンドするか という情報だけを持っている
https://docs.unity3d.com/2017.1/Documentation/ScriptReference/Timeline.TimelineClip.html

PlayableAssetはTimelineClipが具体的に何をするかの情報を持っている
例えばAnimationPlayableAssetなら"どのアニメーションをどの位置で行うか"
https://docs.unity3d.com/2017.1/Documentation/ScriptReference/Timeline.AnimationPlayableAsset.html

サンプル

備考

作ったあとはAssetDatabase.SaveAssets()やAssetDatabase.Refresh()をしないとUnityが検知できないかも

TimelineAssetを生成して保存する

       public static TimelineAsset CreateTimelineAsset(string path) {
              var timelineAsset = ScriptableObject.CreateInstance<TimelineAsset>();
              AssetDatabase.CreateAsset(timelineAsset, path);
              return timelineAsset;
       }

TrackAssetをTimelineAssetに追加する

何かのTrackの子にしたいならparentを指定する
GruopTrackなんかはこれで親子関係にする前提のTrack

       public static T CreateTrackAsset<T>(TimelineAsset timelineAsset, string trackName, TrackAsset parent = null) where T : TrackAsset {
              return (T)timelineAsset.CreateTrack(typeof(T), parent, trackName);
       }

PlayableAssetを生成し、TimelineAssetの子に追加する

       public static T CreatePlayableAsset<T>(TimelineAsset timelineAsset, string playableAssetName) where T : PlayableAsset {
              var playableAsset = (T)ScriptableObject.CreateInstance(typeof(T));
              playableAsset.name = playableAssetName;
              playableAsset.hideFlags = HideFlags.HideInHierarchy;
              AssetDatabase.AddObjectToAsset(playableAsset, timelineAsset);
              return playableAsset;
       }

TimelineClipを生成し、TrackAssetに追加する

       public static TimelineClip CreateTimelineClip(TrackAsset parent, PlayableAsset playableAsset) {
              var timelineClip = parent.CreateDefaultClip();
              timelineClip.asset = playableAsset;
              return timelineClip;
       }

AnimationTrackのRecordableなAnimationClipを追加する

Recordable.png

編集できるAnimationClipとして追加する
たぶんもっとマシな方法もあるはず

       public static void AddAnimationClip(AnimationTrack trackAsset, TimelineClip timelineClip, AnimationClip clip) {
              if (timelineClip.asset as AnimationPlayableAsset == null) {
                     Debug.LogError("null AnimationPlayableAsset");
                     return;
              }
              var setClipFieldInfo = typeof(TrackAsset).GetField("m_AnimClip", BindingFlags.NonPublic | BindingFlags.Instance);
              setClipFieldInfo.SetValue(trackAsset, clip);
              var setRecordableFieldInfo = typeof(TimelineClip).GetField("m_Recordable", BindingFlags.NonPublic | BindingFlags.Instance);
              setRecordableFieldInfo.SetValue(timelineClip, true);
              (timelineClip.asset as AnimationPlayableAsset).clip = clip;
              AssetDatabase.AddObjectToAsset(clip, trackAsset.timelineAsset);
       }

作成テスト

    [MenuItem("Test/TimelineCreateTest")]
    static void TimelineCreateTest() {
        var timelineAsset = CreateTimelineAsset("Assets/test.playable");
        var groupTrack = CreateTrackAsset<GroupTrack>(timelineAsset, "Parent");
        var animationTrack = CreateTrackAsset<AnimationTrack>(timelineAsset, "Child", groupTrack);
        var animationPlayableAsset = CreatePlayableAsset<AnimationPlayableAsset>(timelineAsset, "AnimationPlayableAsset");
        var timelineClip = CreateTimelineClip(animationTrack, animationPlayableAsset);

        AddRecordableAnimationClip(animationTrack, timelineClip, new AnimationClip { name = "TestRecordable" });
        AssetDatabase.SaveAssets();
    }