poi’s tech blog

3D多人数同時接続型球体アクション成人向けゲーム開発のためのアイデア、ナレッジ

Timelineで指定したMarkerの位置にジャンプするMarkerを作った。

Unity2019.3.14f1

ググってもいい感じのMarkerが見つからなかったので自作した。

f:id:poipoipoip:20210307185257g:plain

MarkerReceiver

Timelineの"Jump Track"という名前のトラックを探すようにしているので適宜変更して下さい。

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

// Jumpするよーという情報を受信するマーカー
public class JumpFromMarkerReceiver : MonoBehaviour, INotificationReceiver
{
    private PlayableDirector director;
    private IEnumerable<IMarker> markers;

    private void Awake()
    {
        director = GetComponent<PlayableDirector>();

        // Timelineのトラック一覧を取得
        IEnumerable<TrackAsset> tracks = (director.playableAsset as TimelineAsset).GetOutputTracks();

        // 指定した名前のトラックを取得
        TrackAsset track = tracks.FirstOrDefault(x => x.name == "Jump Track");

        // トラック内のマーカー一覧を取得
        markers = track.GetMarkers().ToArray();
    }

    public void OnNotify(Playable origin, INotification notification, object context)
    {
        var element = notification as JumpFromMarker;
        if (element == null)
            return;

        // タグが一致したマーカーの位置にジャンプ
        foreach (var m in markers)
        {
            JumpToMarker j = m as JumpToMarker;
            if(j == null) continue;

            if (j.jumpTag == element.jumpTo)
            {
                Debug.Log(element.jumpTo);

                director.time = j.time;
                break;
            }
        }
    }
}

f:id:poipoipoip:20210307182942p:plain
Playable Directorと同じオブジェクトに設定してください

Jump元となるMarker

using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

// Jumpするよーという情報を送信するマーカー
[System.Serializable, DisplayName("Jump From Marker")]

public class JumpFromMarker : Marker, INotification
{
    public string jumpTo;

    public PropertyName id
    {
        get
        {
            return new PropertyName("method");
        }
    }
}

f:id:poipoipoip:20210307183031p:plain
Jump先MarkerのJump Tagと同じ文字列を入力してください。

Jump先となるMarker

using System.ComponentModel;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

// Jump先情報を記録するためのマーカー
[System.Serializable, DisplayName("Jump To Marker")]

public class JumpToMarker : Marker, INotification
{
    public string jumpTag;

    public PropertyName id
    {
        get
        {
            return new PropertyName("method");
        }
    }
}

f:id:poipoipoip:20210307183135p:plain
Jump先Marker

メモ

  • 同じタグのJump先が複数ある場合は最初に作成したMarkerのほうに飛ぶはず

  • 適当に条件式追加してあげれば「特定の状態を満たしていればジャンプ」みたいな使い方ができるはず

ジャンプした時にまたいだ別のSignalが全部動いてしまう

こまった…

directorをPause→ジャンプ→Resumeはダメ、

Signal Trackの動的Muteしようとdirector.RebuildGraph()を叩くとジャンプ地点がバグるからダメ
https://forum.unity.com/threads/mute-unmute-a-track-via-scripting.509604/

いい方法が思い浮かばないので以下のような最悪な実装方法をしている。

  • 標準のSignalではなく独自Markerを作成してUnityEvent発生させる
  • 独自Marker内の処理で、特定のフラグがONの場合はUnityEvent発生させない
  • ジャンプの手前でフラグをON、ジャンプ終わって1秒後とかにフラグをOFF