【Unity】Timelineで敵の”出現タイミング”や”動き”を制御してみる
今回はUnity Advent Calendar 2017 のネタで、「Timelineがカットシーンを作るだけのツールではない事を教えてやる!という妄想を書きなぐる」内容です。
要するに、TImelineでゲームの進行を管理してみようぜ!というお話
Timelineを動画作成以外に使用する
Timelineは所謂カットシーンエディタとして紹介されることが多いです。例えばAdamやUltimate Bowlのような高級デモ。もしくはドアや宝箱の解放といった特定ギミックアクションで。
ただ、最近のUniteの講演動画を見てふと思いました。
別に、TImelineをカットシーン以外に使っても構わんだろう?
Timelineは時間を制御する
Timelineは時間を制御するシステムで、Playableは本質的には時間を与えたら結果を返してくれる機能です。
そのため、時間がある程度固定的な動きであればTimeline上から動作を制御することも可能なんじゃないか?と考えたわけです。
思いついたので早速試作。
ではどんなゲームが良いか・・・となる訳ですが、ゲーセンにあるタイムクライシス的なゲームを考えましたが、今回はサクッと単純な、本当に単純なシューティングを作って見ました。
ゲームを再生せず動きをプレビュー
実際に作ってみたところ、敵の出現タイミングや動き、ちゃんと作り込めば弾幕の生成などの動きも含めてゲームを再生せずTimelineのヘッドを動かすだけでプレビューができました。
。
本当はPlayableをガンガン拡張したものを紹介する予定でしたが、プロジェクトを日本に置きっぱなしにしてしまったので、先ほどサクッとプロジェクトを作成しました。
作ってみる
サクサクっと作ってみます。
- 敵の出現と動き、および量産
- 弾の発射
- 倒さないと次に進めない敵
敵の移動はAnimation
まず敵の出現と移動です。
これは以前Tweenを使っていたものを自作しましたが、データが自宅なので今はAnimationTrackを使用した動きでサクッと作り直しました。
プレビューの動作も安定しているので、割と楽に使えます。
レコードボタンを押している時に対象を動かせば、対象を移動させることができます。もし動かす対象が既にアニメーション再生しているようならば、OverrideTrackを使うことになるかもしれません。
アニメーションカーブをAnimationClipに変換のススメ
作ったアニメーションは、AnimationClipに変換します。
これには3つの理由があります。
一つはAnimationClipを複数配置する為です。
多くのシューティングゲームでは同じような動きのユニットが存在します。もし複数のユニットの動きに一々キーフレームを打っていたら非常に面倒です。
なのでアニメーションクリップに変換し、ソレをコピーする事で複数のオブジェクトに同じ動きをさせます。
二つ目は位置調整がやりやすくなる為です。
今回は敵の出現パターンや位置は完全にTImeline側で制御しています。
その上で、敵の出現タイミングを数ミリ秒ズラしたい場合、キーフレームで制御していると非常に面倒です。特にTimelineのアニメーションエディタはDopesheetモードが使えないので非常に面倒です。
Clipに変換する事で、クリップの位置を調整するだけで出現タイミングがずらせます。
最後の一つはAnimationCurveを編集するのにAnimationWindowが使えるようになる点です。位置調整が超ラクになります。
Convert to clip trackで変換
動きを量産
カーブエディタが使える&プレビューにも反映される
キャラクターの出現位置を変更する
アニメーションで移動を制御した訳ですが、このままだと同じ位置から同じようにユニットが移動します。できれば出現位置を変更したい所です。
これにはClip Root Motion Offsetを使用します。
ここでアニメーションの開始位置や向きを調整してやると、同じアニメーションでも異なる位置から開始する事ができます。
補足
AnimationClipの変換ですが、いくつか把握しておくべきことがあります。
- AnimationClipが保存されるタイミングは、File > Save Project (シーンの保存等も含むっぽい)のタイミングなので、それまでにクラッシュして落ちるとデータがパー。
- クリップを複製(Ctrl+D)した場合、元のアニメーションとは異なるアニメーション扱い。元アニメーションをD&Dで登録した場合は同一アニメーション扱い。
- 複製で作成したアニメーション・通常の手順で作成したアニメーションはOverideの座標系、元アニメーションをD&Dで登録したものはAdditiveの座標。バグっぽい
弾の発射タイミングを制御する。できればスクリプトで。
次に弾の発射の制御系です。弾をバンバラ出していきます。
流石に弾の発射にAnimationEventを使う訳には行かないので、PlayableAPIで制御しましょう!
と思いましたが、、今回はITimeControlを使用します。
ITimeControlでコンポーネントをTImelineから動かす
ItimeControlを使用すると、TImelineの時間を利用してコンポーネントを操作できます。
もし時間を渡したら弾の位置が(消えてなければ)わかる・・・みたいな実装になっている場合は、Timelineから弾のプレビューも可能になります。
今回は面倒だったので弾を発射するコンポーネントのON/OFFだけを行いました。
撃ってるのはパーティクルです。本当にありがとうございました。
ちなパーティクルは生成破棄を繰り返すのではなくEmitを呼び出してエフェクトを生成したりすると、かなり高速で動作します。というかパラメータが多いせいか生成破棄が
あとColliderも地味に高速です。スプライトアニメーションも(Animationと比べると)高速です。あれ、もうこいつだけでいいんじゃね?
倒さないと進行しない敵
最後に「倒さないと進行しない敵」です。
例えばボスやチュートリアルなど、何らかのアクションを行うまで操作を待つ・・・という事はよくあります。
ディレクターを止めろ!
もし停止中にゲームもしくはTimelineが進行しない・・・といった場合は、Timelineをポーズしてしまうのがいちばん手っ取り早いかもしれません。
ただしPlyableDirectorが停止するので、PlayableDirectorが制御していたアニメーションやカメラワークがニュートラルに戻ります。
もし会話シーンの入力待ち等に使用する場合は、停止の前後でアニメーションのウェイトを減らして通常時のモーションに戻しておくと違和感がなくなります。
タイムリープ系
逆に、条件が達成されるまで同じ動作を繰り返す・・・といったケースもあります。こちらはボス戦とか。
このケースでは、TimelineのTimeを巻き戻してしまうのが楽かもしれません。
クリップの長さを求めて、その時間分巻き戻してやれば、クリップの中でループができます。最早脱出条件を揃えるまでエンドレスエイトです。
ただこちらも一つ注意事項があります。というのも、どうやらTimeを巻き戻して移動した場合はExitやEnter系のコールバックが呼ばれない事があるというもので、もし入退場に何らかの重要な処理がある場合は、注意する必要があります。
まぁPlayableは入退場のコールバックがものすごく使いにくいのである意味問題ないのかもしr
見かけた問題
独自PlayableやControlPlayableで動かした場合、パラメータやActiveがリセットされない事が稀にあります。再現条件は不明ですが、ControlPlayableはActiveをリセット後戻さない事があるみたいです。
Timelineは基本的に「全てのアクセスするオブジェクトがロードし終わった状態」でしか動かせません。多彩なアセットや長いタイムラインを持つ場合、動的にアセットを追加・削除できるように間接的にTimelineで制御するようにした方が良いかもしれません。
負荷は?
エディターは遅い。プレイヤーは思ってたより早い
感想
色々と試しに作ってみました。
まぁ問題は色々とありますが、プレビューできて簡単に微調整できるのは強いですね。
次回は kaiware007氏が何かを書くそうです。
関連
クリップの動作を細かく制御したいなら独自Playable。ただ作るのが超絶スーパーウルトラグレートデリシャスミラクルワンダフル面倒なので、テンプレから作るのおすすめです。