Help us understand the problem. What is going on with this article?

UnityのTimelineでクリップが一つだけのトラックを作る

こんにちは、ZeniZeniです。
最近Unityのタイムラインをよくいじっています。

やりたいこと

Unityのタイムラインをいじっていると、トラック上にクリップが一つだけしか存在してはいけないような制限を設けたいときがあります。(私はありました。)

さぁ作ろうと思って色々調べてみると、カスタムPlayable Trackでタイムラインのトラックを自作しないといけないことがわかりました。
こちらの動画が参考になります。
https://youtu.be/6SPpjSKy9LI

上の動画を参考にしながら、トラックにクリップが二つ以上置けない制限を設けた、シーン遷移を行うカスタムトラックを作成しました。
プロジェクトはこちらにあります。
https://github.com/Zeni-Y/TimelineCustomTrackTest

実装方法

まず、作製したMixerとTrackのコードはこちらです。(プラスClipとBehaviourのコードもありますが、長くなるので割愛します)

SceneManagementMixer
using System.Collections.Generic;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using System.Linq;
using UnityEngine.SceneManagement;

namespace ZeniZeni.CustomTrack
{
    public class SceneManagementMixer : PlayableBehaviour
    {

        internal PlayableDirector m_playableDirector;

        internal string m_scene;
        internal LoadSceneMode m_mode;

        internal IEnumerable<TimelineClip> m_clips;
        private bool oneShot = true;

        // NOTE: This function is called at runtime and edit time.  Keep that in mind when setting the values of properties.
        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            if (m_clips.Count() >= 2) return;

            int inputCount = playable.GetInputCount<Playable>();
            if (inputCount == 0) return;

            var time = m_playableDirector.time;
            var enumulator = m_clips.GetEnumerator();
            enumulator.MoveNext();

            for (int i = 0; i < inputCount; i++, enumulator.MoveNext())
            {
                var clip = enumulator.Current;

                var asset = clip.asset as SceneManagementClip;

                m_scene = asset.m_scene;
                m_mode = asset.m_mode;
                if (clip.start <= time && time <= clip.end  && oneShot)
                {
                    SceneManager.LoadSceneAsync(m_scene, m_mode);
                    oneShot = false;
                }
                else if (time < clip.start || time > clip.end)
                {
                    if (!oneShot) oneShot = true;
                }
            }

        }
    }
}
SceneManagementTrack.cs
using System.Linq;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

namespace ZeniZeni.CustomTrack
{
    [TrackColor(0.3523021f, 1f, 0f)]
    [TrackClipType(typeof(SceneManagementClip))]
    public class SceneManagementTrack : TrackAsset
    {

        public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
        {

            var mixer = ScriptPlayable<SceneManagementMixerBehaviour>.Create(graph, inputCount);
            var director = go.GetComponent<PlayableDirector>();
            if (director != null)
            {
                SceneManagementMixerBehaviour bh = mixer.GetBehaviour();
                //Track上のクリップを取得
                bh.m_clips = GetClips();

                //Clipが二つ以上あれば一つだけになるようにClipを新しい順に消す
                if (bh.m_clips.Count() >= 2)
                {
                    for (int i = 0; i < bh.m_clips.Count()-1; i++)
                    {
                        timelineAsset.DeleteClip(bh.m_clips.Last());
                    }
                    Debug.Log("You can put only one SceneManagementClip in this Track.");
                }
                bh.m_playableDirector = director;
            }

            return mixer;
        }
    }
}

クリップを二つ以上置けないようにする機能の実装方法ですが、クリップを作成したときに、そのトラック上にクリップが二つ以上存在すれば、一つだけになるようにClipを新しい順に消すような形で実装しています。

クリップを二つ以上置こうとすると以下のGIFのようになります。
ダウンロード.gif

ただ問題がありまして、インスペクターを表示した状態でこの動作を行うと、下の画像のようなエラーが発生します。
bandicam 2019-12-01 23-32-49-404.jpg

一応Clearで簡単に消せますが、気になっちゃいますよね。

理想としては、クリップが一つ存在すれば追加でクリップを作成できないような形にしたかったんですが、実装方法がわからず断念しました。
方法がわかり次第、追記していきます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした