ゆいブロ

自分の好きなことや知見をまとめていくブログです。

スポンサーリンク

【Unity】TimelineのTrackを別のTimelineなどにコピーする際に、VirtualCameraの参照を上手く付け替える方法

はじめに

https://docs.unity3d.com/ja/2018.4/uploads/Main/timeline_splash.jpg

前回、TimelineのTrackを別のTimelineにコピーする方法を書きました。

www.yui-tech-blog.com

この記事の最後の方にCinemachineTrack内のClipで、VirtualCameraのBindが上手く引き継げない問題をあげていましたので 今回はこれを解決していこうと思います。

VirtualCameraはどこに参照がある?

まず、VirtualCameraのBindは、PlayableDirectorのBindingsに情報があります。 むしろ、TimelineClipやCinemachineShot側には、VirtualCameraを参照しているように見せかけて、実は参照自体は持っていません。

PlayableDiretorを経由しないと参照が取得できないようになっています。

実際のEditorの画面を用いて説明していきます。

f:id:yui-frapper:20200204000920p:plain:w300

↑通常のInspectorだと参照が入っていますが

f:id:yui-frapper:20200204001017p:plain:w300

↑InspectorをDebugモードにし、CinemachineShotのアセットを開いてみると、DefaultValueにVirtualCameraの参照がありません。

f:id:yui-frapper:20200204001236p:plain

↑InspectorをDebugモードにした上で、PlayableDirectorを覗いてみると、VirtualCameraのオブジェクトと、 先ほどのCinemachineShotのExposedNameが紐づいて保存されていることがわかります。

このように、Bind設定は各Clip内ではなくPlayableDirectorに保存されていることがわかります。

解決方法

// CinemachineのBindされているオブジェクトだけ別途生成しBindする
foreach( TrackAsset source in fromTimelineAsset.GetOutputTracks() )
{
    if( source is CinemachineTrack cinemachineTrack )
    {
        foreach( TimelineClip timelineClip in cinemachineTrack.GetClips() )
        {
            // CinemachineShotがアセットの参照ならばCinemachineShotをコピー
            if( timelineClip.asset is CinemachineShot cinemachineShot )
            {
                foreach( TrackAsset trackAsset in toTimelineAsset.GetOutputTracks() )
                {
                    if( trackAsset is CinemachineTrack createdCinemachineTrack )
                    {
                        foreach( TimelineClip createdClip in createdCinemachineTrack.GetClips() )
                        {
                            if( createdClip.displayName == timelineClip.displayName && createdClip.asset is CinemachineShot createdShot )
                            {
                                // exposedNameをPropertyName化することで、PlayableDirectorからVirtualCameraの参照をもってこれる
                                PropertyName propertyName = new PropertyName( cinemachineShot.VirtualCamera.exposedName );

                                Object referenceValue = fromDirector.GetReferenceValue( propertyName, out bool result );

                                if( result && referenceValue is CinemachineVirtualCamera cinemachineVirtualCamera )
                                {
                                    // Cinemachineを作成し、exposedNameを新しく作成してPlayableDirectorに紐づける
                                    CinemachineVirtualCameraBase instanceVirtualCamera = Instantiate<CinemachineVirtualCamera>( cinemachineVirtualCamera, toDirector.gameObject.transform, false );
                                    createdShot.VirtualCamera.exposedName = UnityEditor.GUID.Generate().ToString();
                                    deleteObjects.Add( instanceVirtualCamera.gameObject );
                                    toDirector.SetReferenceValue( createdShot.VirtualCamera.exposedName, instanceVirtualCamera );
                                }
                            }
                        }
                    }
                }
            }
        }

    }
}

from〇〇が複製元で、to〇〇が複製先の変数です。

ネストが深くなってしまいましたが、とりあえずこの処理を書けば参照を探してきて、複製先のPlayableDirectorの下にVirtualCameraを複製し、Bind設定まで済ませることができます。