今回はUnity2017.1から導入されたTimelineの機能を使ってみたいと思います。
このTimelineはキャラクターの動きや他のゲームオブジェクトの動き、音声の再生、と言った複数のゲームオブジェクトをタイムライン上で管理することが出来ます。
映画シーンやゲームでのイベントシーンの動き等を作成する時に便利かもしれませんね。
またタイムラインの終了の検知も出来ますので、通常のゲームシーン→イベントシーン→ゲームシーンといったシームレスなイベントの遷移も作成出来そうです。
既存のAnimation機能と似ていますが、Animationの場合は一つのゲームオブジェクトのアニメーションクリップを作成するのに対してタイムラインは複数のオブジェクトのタイミングを管理出来ます。
そこら辺の違いは記事の最後に記載しているUnityマニュアルのタイムラインの項目を見ると詳しく載っています。
TimeLine
TimeLineウインドウを開きます。
UnityメニューからWindow→Timelineを選択し、タイムラインウインドウを開きます。
すると以下のようなウインドウのタブが表示されます。
現時点ではタイムラインのファイル(タイムラインアセット)を作成していないので↑のように表示されます。
タイムラインアセットとタイムラインインスタンス
タイムラインを作成するにはタイムラインアセットとタイムラインインスタンスが必要になります。
タイムラインアセットはトラックとクリップ、シーケンスを保持しています。
↑ではAnimation Clipのトラックを追加し、キャラクターアニメーションクリップを配置していますが、どのキャラクターに対して適用するかの情報は保持していません。
どのゲームオブジェクトに対して行うかという情報はタイムラインインスタンスが保持します。
↑ではEthanをヒエラルキー上に配置しPlayable Directorコンポーネント(Playable Directorに関しては後で取り上げます)を取り付け、EthanのAnimatorをAnimation Clipに設定しています。
タイムラインアセットとタイムラインインスタンスを繋げるにはPlayable Directorコンポーネントを取り付ける必要があり、取り付けた後にTimelineウインドウのCreateボタンを押すとタイムラインアセットとタイムラインインスタンスが作成されます。
プレハブと同じように考えるとわかりやすいですが、ゲームオブジェクトのPlayable Directorに既に作成しているタイムラインアセットを設定し、オブジェクトを変更するだけで元の流れは同じままにキャラクターや音楽を変更することが出来ます。
説明だけ見ても分かりづらいので実際に使ってみましょう。
Cubeのアニメーション作成でTimeline機能を学ぶ
まずはCubeの動きをTimelineで作成する事でTimelineの使い方を覚えていきましょう。
ヒエラルキー上にCubeを作成します。
Cubeを配置したらインスペクタのAdd ComponentからPlayables→Playable Directorを取り付けます。
Playable Directorコンポーネント
Timelineを使用するには何らかのゲームオブジェクトにPlayable Directorコンポーネントを取り付けます。
Playableにタイムラインアセットを設定するとタイムラインインスタンスとの関連付けがされます。
UpdateMethodを見ていきます。
UpdateMethodはタイミングを更新する時に使用するクロックを選択します。
DSP Clockはオーディオを処理するときのクロックを使用。
Game Timeはゲームクロックを使用でタイムスケールの影響を受ける。
Unscaled Game Timeはゲームクロックを使用でタイムスケールの影響を受けない。
Manualはクロックソースを使用せずスクリプトで指定します。
Play On Awakeにチェックを入れるとシーン開始するとすぐにタイムラインを再生します。
Wrap Modeはタイムラインの再生を終了する時の動作の設定です。
Holdはタイムラインの最後の状態を維持。
Loopはタイムラインを繰り返し再生。
Noneはタイムライン再生前に戻す。
Initial Timeは再生を開始するまでの時間を設定出来ます。
Playable Directorコンポーネントに関してはこんな感じです。
とりあえずCubeに設定したPlayable Directorは変更せずデフォルト値を使用する事にします。
タイムラインアセットの作成
タイムラインアセットはゲームオブジェクトを選択した状態でTimelineウインドウのCreateを押すことで作成出来ます。
またはAssetsフォルダ内で右クリック→Create→Timelineを選択する事でも作成出来ます。
今回はAssetsフォルダで右クリックしTimelineを作成し、名前をCubeTimelineに変更します。
CubeTimeLineを選択した状態でインスペクタを見ると↑のような設定項目が現れます。
Frame Rateは1秒間にタイムラインが流れるフレーム数。
Duration Modeは
Based On Clipsの場合はタイムラインアセットの長さを最後のクリップに合わせ、Fixed Lengthは指定した秒数またはフレーム数に合わせます。
CubeTimelineはBased On Clipsにしておきます。
作成したらCubeゲームオブジェクトのPlayable DirectorのPlayableにドラッグ&ドロップします。
Playable DirectorのPlayableにタイムラインアセットを設定するとこのCubeのタイムラインインスタンスが作成されTimelineウインドウで操作が出来るようになります。
Animation Trackの追加
Cubeの動きを作成する為にTimelineのAddからAnimation Trackを選択しアニメーショントラックを追加します。
Animation Trackを追加すると以下のようになります。
ゲームオブジェクトにAnimatorを設定する必要がある為、CubeのインスペクタのAdd ComponentからMiscellaneous→Animatorを取り付けます。
取り付けたらTimelineのAnimation TrackにCubeゲームオブジェクトをドラッグ&ドロップします(Animatorをドラッグ&ドロップしてはダメです)。
以下はCubeゲームオブジェクトをドラッグ&ドロップした場合で、こちらが正解。
CubeのAnimatorコンポーネントをドラッグ&ドロップすると
↑のようになりますが、こちらではCubeのAnimator事態にアニメーションが設定されていないと、アニメーションをさせることが出来ません。
Cubeの動きを作成する
それではCubeの動きをTimelineで作成していきましょう。
人間型のキャラクター以外のゲームオブジェクトは録画ボタンを押すことが出来ます。
↑の録画ボタンを押します。
次にCubeのインスペクタを表示し、録画したいプロパティ上で右クリックしAdd Keyを選択します。
今回の場合は位置を動かしたいのでPosition上で右クリックしAdd Keyを選択しキーを作成します。
変化できるプロパティ値は赤く変色します。
Cubeの0フレーム時の位置にキーが打たれたので、次はTimelineの再生ヘッドを右にドラッグし60フレームの位置に移動させます。
↑のようにフレーム数が表示されている所にある白い矢印を60フレームの位置にドラッグします(録画状態にしたまま)。
次にCubeのゲームオブジェクトを選択し、X軸の矢印をドラッグして移動させます。
これで60フレームのCubeの位置のキーが打たれました。
録画ボタンを押し、録画を解除した状態でTimelineの再生ボタンを押してみます。
↑の再生ボタンを押すとTimelineが再生されます。
GameビューでCubeを確認すると
↑のようにCubeが移動するアニメーションが再生されました。
キーの編集
Timeline上のキーは直接変更出来ませんが、録画ボタン横のカーブビューを使ってカーブを操作出来ます。
↑のカーブビューのボタンを押すと下にキーとカーブが表示されるので編集することが出来ます。
また、Timeline上で右クリック→Edit in Animation Windowを選択しAnimationウインドウで編集することが出来ます。
単純にタイムライン上でダブルクリックしてもAnimation Windowが開きます。
Animation WindowとTimelineのリンクを解除する時は↑の赤い四角部分を押します。
キーの削除
追加したキーはゲームオブジェクトのインスペクタのプロパティ上で右クリック→Remove Key。
カーブビューのキー上で右クリック→Delete Key。
Animation Windowを開いた時のキーを選択し、右クリック→Delete Keysで削除する事で出来ます。
ゲームオブジェクトのインスペクタでのキーの削除はプロパティ項目が残ってしまうので(ここでの消し方がわからない)、Animation Windowを開いてプロパティ項目を削除すると良いです。
カーブのキーが見えなくて操作出来ない
カーブビューでプロパティの値が大きく変わって左側の値の範囲外にキーが出てしまった場合にキーが選択出来なくなります。
↑のように元々の値の範囲を超えるX軸の値を設定した為、キーが見えない。
そんな時はゲームオブジェクトのインスペクタで該当するプロパティ上で右クリック→Update Keyを選択します。
するとカーブビューでキーが見えるようになります。
アニメーションクリップに変換
ここまででCubeをX軸に動かすアニメーションが出来ましたが、このクリップは無限クリップと呼ばれるもので、このままでは配置や分割等が出来ないため無限クリップをアニメーションクリップに変換します。
Animation TrackのCubeを選択した状態かタイムライン上で右クリック→Convert To Clip Trackを選択します。
すると以下のようにアニメーションクリップへと変換されます。
無限クリップに戻したいときはAnimation TrackのCubeを選択した状態で右クリック→Convert To Infinite Clipを選択します。
ゲームイベント部分の作成
Cubeを使ってTimelineを使ってみましたが、次はキャラクターの動きや音声の再生、カメラの移動などをTimelineに載せてゲーム途中のイベント部分を作成してみます。
キャラクターの動きを作成する
まずはキャラクターを配置し、Animation TrackにAnimatorを設定し時間経過でアニメーションクリップが再生されるようにします。
タイムラインアセットの作成
Assetsフォルダ→Standard Assets→Characters→Third Person Character→Models→Ethanをヒエラルキー上にドラッグ&ドロップします。
EthanのインスペクタのAdd ComponentからPlayables→Playable Directorを選択し取り付けます。
Ethanを選択した状態でTimelineのCreateボタンを押します(今回はこちらのやり方でタイムラインアセットを作成してみます)。
保存ダイアログが表示されるのでEthanTimelineという名前を付けて保存したいフォルダに保存します。
この時Playable DirectorのPlayableにはEthanTimelineが設定されます。
Ethanを選択するとTimelineウインドウでは
↑のようにEthanゲームオブジェクトが設定されていますが、今回はキャラクターのAnimatorをクリップとして使いたいのでEthanのAnimatorをAnimation Trackに設定します。
EthanのAnimatorをAnimation Trackにドラッグ&ドロップすると以下のようにAnimation TrackにAnimatorが設定されます。
アニメーションクリップの配置
次にAnimation Trackにキャラクターのアニメーションクリップを配置してみます。
Animation Trackを選択した状態で右クリック→Add From Animation Clipを選択します。
追加したいアニメーションクリップを選択すると以下のように追加されました。
今回はスタンダードアセットのキャラクターに設定されているHumanoidIdleとHumanoidWalkを追加しました。
Timelineの再生ボタンを押すとキャラクターがブラブラその場で動いた後、前方に向かって歩いていくようになります。
EthanのAnimatorではApply Root Motionのチェックを入れたままにしている為、アニメーションの移動値がそのまま反映されキャラクターが動きます。
Apply Root Motionのチェックを外しているとその場でアニメーションをするだけです。
Apply Root Motionのチェックを外して動かす
AnimatorのApply Root Motionのチェックを外した場合はアニメーションの動きが反映されずその場から動きません。
ですが、Cubeの動きを作った時と同じようにAnimation Trackを作りそこにEthanのゲームオブジェクトを設定しTransformのPositionを動かしていけばApply Root Motionのチェックを外しても動きを作れます。
↑のようにAnimation Trackを作り、そこにEthanのゲームオブジェクトを設定しPositionの移動を作成していく事で出来るようになります。
タイムラインのアニメーションクリップコンテキストメニュー
アニメーションクリップを選択した状態で右クリックをするとアニメーションクリップを操作するコンテキストメニューが表示されます。
アニメーションクリップを配置しクリップの端をドラッグするとアニメーションクリップの再生を長くする事が出来ます。
しかしアニメーション途中でぶつ切りになってしまいます。
部分的なアニメーションのループを完成させるにはEditingの
Complete Last Loopを選択するとループの最後までを考慮したクリップの長さに調整されます。
Trim Last Loopを選択するとクリップの最後の部分的なループを削除できます。
これらの設定はEditingのReset Editingを選択すると解除されます。
Speed項目では
Double Speedで倍の速さ
Half Speedで半分の速さ
Reset Speedで元の速さ
にアニメーションスピードを変更出来ます。
これはタイムラインのアニメーションクリップを選択してインスペクタに表示されるSpeed Multiplierの値を操作しますので、インスペクタでも設定出来ます。
Match Offsets To Previous Clipは現在のクリップを前のクリップ(今回の場合はHumanoidIdle)にオフセット値を合わせます。
これを選択するとアニメーションの開始位置が違う場合に現在のクリップを前のクリップの位置と合わせる事が出来ます。
これもアニメーションクリップのインスペクタで操作出来ます。
Reset Offsetsはオフセット値を元に戻します。
アニメーションクリップのインスペクタ
先ほどのアニメーションクリップのコンテキストメニューからクリップの操作も出来ますが、インスペクタからも操作出来ます。
それぞれの項目のsは秒数でfはフレーム数での指定が出来、相互に値が変わります(どちらかで設定)。
Clip Timingはそのアニメーションクリップのタイミングの設定です。
Startは始まりの位置
Endは終わりの位置
Durationは再生時間(フレーム)
Ease In Durationはクリップに入る時の補間時間
Ease Out Durationはクリップに出る時の補間時間
Clip Inはこのクリップに入るまでの時間
Speed Multiplierはクリップの再生スピード
Animation Extrapolationはギャップ補外の設定です。
ギャップ補外は前後のアニメーションとのギャップをアニメーションデータに近似させる事みたいです。
Noneはゲームオブジェクトのシーン上の状態に
Holdはクリップ終了時の状態を維持
Loopはクリップを最初から最後までを繰り返す
Ping Pongは最初から最後まで再生したら最後から最初に戻します
Continueはソースアセットの設定によって変わるみたいですが、アニメーションをそのまま維持するかループをするかみたいです。
Animation Playable Assetではオフセット値を設定し、前後のアニメーションクリップとの位置や角度の差を調整します。
とりあえずタイムラインのアニメーションクリップはこんな感じになります。
キャラクターの動きを調整していきましょう。
アニメーションの調整
先ほどHumanoidIdleとHumanoidWalkのクリップをAnimation Trackに追加しましたが、まだ何も調整していません。
まずはHumanoidWalkのクリップを選択し、右クリックからMatch Offsets To Previous Clipを選択し前のクリップに位置を合わせます。
次にIdle→Walkへのアニメーションの切り替わりがブレンドされていない為、いきなりWalkへと切り替わってしまいます。
そこでHumanoidWalkのクリップを左にドラッグし、補間されるようにします。
↑のようにHumanoidIdleの終わり部分とHumanoidWalkの始まりが重なるようにします。
キッカリとクリップを分けている場合は
↑のようにアニメーションの切り替わりがパッと変わってしまいますが、先ほどのように重ねると
↑のようにアニメーションが補間され流れるようなアニメーションになります。
アニメーションのオーバーライド
ここまででアニメーションクリップの配置と再生が出来ましたが、例えばキャラクターの上半身だけアニメーションを変更したいという事もあると思います。
これはAnimatorControllerのLayerとAvatarMaskを使ったやり方と似た感じで実現することが出来ます。
Animation Trackを選択した状態で右クリック→Add Override Trackを選択します。
するとOverrideトラックが作成されるので、Overrideトラックを選択した状態から右クリック→Add From Animation Clipを選択します。
追加したアニメーションクリップはHumanoidWalkの再生タイミングと合うように長さを調整します。
↑のような感じに調整しました。
わたくしはOverrideトラックに銃を構えている状態のアニメーションクリップを設定しました。
このままだとHumanoidWalkを今配置したアニメーションクリップで上書きしてしまうので、Overrideトラックのアニメーションにはアバターマスクを設定し、上半身のアニメーションだけを再生するようにします。
Assetsフォルダで右クリック→Create→AvatarMaskを選択し名前をUpperBodyとします。
UpperBodyアバターマスクを選択するとインスペクタで設定が出来るので、以下のように体の部位をクリックして上半身部分だけ緑色にします。
次にOverrideトラックを選択しインスペクタのAvatar MaskにUpperBodyを設定します。
するとタイムラインでAvatarMaskのアイコンが表示されます。
↑のアバターマスクのアイコンをクリックするとアバターマスクのオン・オフが出来ます。
オーバーライドしたクリップの補間
このままだとオーバーライドするアニメーションは補間されずにいきなり切り替わってしまいます。
そこでオーバーライドしたクリップの前後で補間されるようにしてみます。
Overrideトラックのクリップを選択し、インスペクタを表示します。
Ease In DurationとEase Out Durationの値を変更し、補間されるようにします。
タイムラインでは
↑のように表示されます。
キャラクターの動きを確認する
これでとりあえずキャラクターのタイムラインの設定が出来たので再生してみましょう。
↑のような感じでキャラクターの動きが出来上がりました。
補間時間がちょっと短かったかも・・・・(^_^;)
Audio Trackの追加
キャラクターはIdle状態から銃を構えて歩き始める状態へと変化させていますが、銃声が聞こえたので銃を構えて歩き出すという風にしてみたいと思います。
TimelineのAddからAudio Trackを選択します。
Audio Trackが追加されたらAudio Sourceを設定する必要があります。
そこでMainCameraのインスペクタでAdd Component→Audio→Audio Sourceを取り付けて、TimelineのAudio TrackにMainCameraをドラッグ&ドロップします。
次にAudio Trackにオーディオクリップを配置します。
Audio Trackを選択した状態で右クリック→Add From Audio Clipを選択しオーディオクリップを選択します。
Main Camera用のAnimation Trackを作成
TimelineのAddからAnimation Trackを追加します。
Main CameraにAnimatorコンポーネントを追加し、Cubeの時と同じようにPositionやRotationのキーを打ってカメラの動きを作成していきます。
キャラクターの移動先を追いかけるようにカメラを移動させたり回転させたりします。
やり方は同じなので割愛します・・・・(^_^;)
カメラをCubeと同じように位置や角度を変える事でも出来ますが、Cinemachineというアセット(Unityさんが作ったやつ)を使うともっと簡単にカメラワークを作ることが出来ます。
Cinemachineについては
を参照してください。
オーディオの音量を変更
MainCamera用のAnimation Trackで最初の銃声が聞こえた時にMainCameraに取り付けてあるAudio SourceのVolumeを下げておき、次の銃声の時にVolumeを上げるようにします。
最初の銃声が鳴るちょっと前にAudio SourceのVolumeを少し下げておきます。
次の銃声のちょっと前にVolumeを1に戻します。
これで音量の変更が出来ました。
イベント終了の検出
タイムラインを使用して再生が終わったら別のシーンに移動させたいとなると思います。
そんな時はPlayable Directorコンポーネントの再生中かどうかを調べて再生が止まっていたら次のシーンを読み込むというような処理を書くと良さそうです。
今回はPlayable DirectorコンポーネントはEthanに取り付けているので、それを取得し次のシーンを読み込むスクリプトを同じEthanに設定するとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.SceneManagement; public class CheckTimelineEnd : MonoBehaviour { private PlayableDirector playableDirector; // 終了を検知したかどうか private bool isEnd; // Use this for initialization void Start () { playableDirector = GetComponent<PlayableDirector> (); isEnd = false; } // Update is called once per frame void Update () { // タイムラインが終了したら次のシーンを読み込む if (!isEnd && playableDirector.state != PlayState.Playing) { isEnd = true; StartCoroutine (LoadNextScene ()); } } // 次のシーンの読み込み IEnumerator LoadNextScene() { AsyncOperation async = SceneManager.LoadSceneAsync ("TimeLine2"); while (true) { if (!async.isDone) { yield return null; } } } } |
PlayableDirectorコンポーネントを取得しplayableDirector.stateで現在の状態を取得します。
再生中でなければコルーチンでTimeLine2シーンを読み込みます。
今回はPlayable DirectorコンポーネントのPlay On Awakeにチェックを入れている為、シーンが開始されると共にタイムラインの再生が始まっていますが、playableDirectorにPlayableDirectorの参照が入っているとすれば、
1 2 3 4 5 6 7 8 9 10 | // タイムラインの再生 playableDirector.Play (); // タイムラインの一時停止 playableDirector.Pause (); // タイムラインの再開 playableDirector.Resume (); // タイムラインの停止 playableDirector.Stop (); |
のようにタイムラインを操作する事が出来るので、タイムラインの開始や一時停止、停止もスクリプトから操作できます。
画面がアクティブでないとすぐに次のシーンに遷移してしまう
このスクリプトの処理だと例えばスタンドアロン形式でファイルを出力し、ゲーム開始とともにウインドウを非アクティブ状態にするとすぐにTimeLine2シーンに遷移してしまいます。
その為、非アクティブ状態でもゲームが進行するように設定しておかなければいけません。
UnityメニューのEdit→Project Settings→PlayerのResolutionでRun In Backgroundにチェックを入れるとウインドウ等が非アクティブでもゲームが進行します。
ですがイベントシーンであっても非アクティブな状態であれば進行を止めたい事もあると思います。
そこでやり方を変え、Activation Trackを使用して次のシーンに遷移するようにしてみます。
ヒエラルキー上に空のゲームオブジェクトを作成し、名前をNextSceneとします。
インスペクタで名前の横のチェックを外し非アクティブにしておきます。
TimelineのAddからActivate Trackを追加し、NextSceneをActivation Trackに追加するとします。
Activation Trackを選択した状態で右クリック→Add Activation Clipを選択します。
タイムライン上の他のクリップが終了した後にActivation Clipをドラッグします。
NextSceneゲームオブジェクトにはGoToNextSceneスクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class GoToNextScene : MonoBehaviour { void OnEnable() { StartCoroutine (LoadNextScene ()); } // 次のシーンの読み込み IEnumerator LoadNextScene() { AsyncOperation async = SceneManager.LoadSceneAsync ("TimeLine2"); while (true) { if (!async.isDone) { yield return null; } } } } |
OnEnableメソッドでコルーチンを使って次のシーンを読み込むので、NextSceneゲームオブジェクトがアクティブになった時に次のシーンへと遷移するようになります。
こちらのやり方を使う場合はCheckTimelineEndスクリプトは使用しないのでEthanから削除します。
この処理はもっとかしこいやり方がありそうですが、とりあえず出来たものでいこう・・・・(-_-)
他のタイムラインを起動する
Timelineの流れの中で他のタイムラインの起動もすることが出来ます。
TimelineのAddからControl Trackを追加します。
Control Trackを選択した状態で右クリック→Add Control Playable Asset Clipを選択しクリップを追加します。
Control Trackのクリップを選択し、インスペクタでSource GameObjectに最初に作ったCubeを設定します。
これでEthanTimelineでControl Trackのクリップ部分に来たらCubeのTimelineが再生されます。
他のやり方があるかもしれませんがとりあえずこれで・・・・(-_-)
イベントの確認
銃声が聞こえたらキャラクターが銃を構えて前方に歩きだし、2回目の銃声が聞こえたら左側に走り抜けるようにキャラクターのAnimation Trackに追加しました。
タイムラインを再生するシーンをTimeLine、再生が終わったら遷移するシーンをTimeLine2として作りUnityメニューのFile→Build Settingsで2つのシーンをTimeLineが上になるようにドラッグ&ドロップします。
ゲーム中イベントの作成が終わったので確認してみます。
↑のようになりました。
ウインドウが非アクティブな状態になった時は止まり、アクティブになった時は再開しています。
シーンの遷移も問題なさそうですね。
終わりに
タイムラインを使うとキャラクターのアニメーションのタイミングや音声のタイミング等を合わせるのが簡単になりますね( `ー´)ノ
ですがまだ細かい使い方がよくわかりません・・・・。