今回はUnityのAnimatorの保存機能と再生機能を使ってみようと思います。
Animatorの保存機能と再生機能を使うとゲーム中のキャラクターのアニメーションを保存して再生する事が出来ます。
この保存機能はAnimatorの保存なのでAnimatorControllerのアニメーションの動きしか保存できない為、キャラクターのアニメーションの動きをゲーム中に反映させていない場合(AnimatorのApply Root Motionにチェックを入れていない場合)は移動値等を再現出来ません。
ただゲーム中に実行したアニメーションを即座に再生したい時などは便利かもしれません。
↑のようなキャラクターのアニメーションの保存と再生の機能が出来ました。
アニメーションの動きは保存してますが、キャラクターの向き等は保存できない為、録画開始時の位置と向きになります(アニメーションで向きを変えなければ)。
Animatorの保存と再生機能
Animatorには元々保存と再生の機能が備わっているのでその機能を呼び出して実行するだけで出来ます。
ただ、再生をする時にはAnimatorControllerのアニメーションパラメータのデータを使う必要があるみたいなので、キャラクターのAnimatorとは別にレコーダーのAnimatorを作り、
そこにfloat型のアニメーションパラメータを用意してその数値を使用する必要があります。
Recorderオブジェクトの作成
まずは保存と再生を扱うゲームオブジェクトを作成しそこにAnimatorやスクリプトを設定するようにします。
ヒエラルキー上に空のゲームオブジェクトを作成し名前をRecorderとします。
RecorderにはインスペクタのAdd ComponentからMiscellaneous→Animatorを取り付けます。
Assetsフォルダで右クリックからCreate→AnimatorControllerを選択し名前をRecorderAnimatorとして、アニメーションパラメータにfloat型のSpeedを作成します。
RecorderAnimatorはアニメーションパラメータのSpeedを使うだけなので特に状態や遷移は作成しません。
RecorderゲームオブジェクトのAnimatorにこのRecorderAnimatorをドラッグ&ドロップします。
Animator保存スクリプトの作成
次にAnimatorRecorderスクリプトを作成しRecorderゲームオブジェクトに取り付けます。
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class AnimatorRecorder : MonoBehaviour { private bool isPlayBack; [SerializeField] private Animator animator; [SerializeField] private Animator recorderAnimator; private Vector3 defaultPos; private Quaternion defaultRot; void Start() { recorderAnimator.SetFloat ("Speed", 1f); } public void StartRecord() { if (isPlayBack) { animator.StopPlayback (); recorderAnimator.StopPlayback (); } // キャラクターの初期位置を保存 defaultPos = animator.transform.position; defaultRot = animator.transform.rotation; animator.StartRecording (0); recorderAnimator.StartRecording (0); isPlayBack = false; Debug.Log ("アニメーションの録画開始"); } public void StopRecord() { Debug.Log ("アニメーションの録画停止"); isPlayBack = false; animator.StopRecording (); recorderAnimator.StopRecording (); } public void PlayBack() { // 録画してなければ何もしない if (animator.recorderStopTime <= 0) { return; } if (animator && recorderAnimator && !isPlayBack) { animator.Rebind (); recorderAnimator.Rebind (); animator.StartPlayback (); recorderAnimator.StartPlayback (); animator.playbackTime = animator.recorderStartTime; animator.transform.position = defaultPos; animator.transform.rotation = defaultRot; isPlayBack = true; Debug.Log ("アニメーションの再生"); } } public void StopPlayBack() { isPlayBack = false; animator.StopPlayback (); recorderAnimator.StopPlayback (); Debug.Log ("アニメーションの停止"); } void Update () { if (isPlayBack) { Debug.Log (animator.playbackTime + ":" + animator.recorderStopTime); float playBackTime = recorderAnimator.playbackTime + recorderAnimator.GetFloat ("Speed") * Time.deltaTime; if (playBackTime >= recorderAnimator.recorderStopTime) { playBackTime = animator.recorderStartTime; animator.transform.position = defaultPos; animator.transform.rotation = defaultRot; } recorderAnimator.playbackTime = playBackTime; animator.playbackTime = playBackTime; } } } |
isPlayBackはAnimatorを再生中かどうかのフラグ。
animatorはキャラクターのAnimatorを指定し、recorderAnimatorには先ほど作成したRecorderAnimatorを設定します。
defaultPosとdefaultRotはキャラクターのAnimatorを録画する前の位置と角度を入れておくフィールドとして使用します。
Startメソッドでレコーダー用のAnimatorのアニメーションパラメータのSpeedを1にして通常の速度で再生するようにします。
スロー再生や早送りをしたい時はこの値を操作します。
StartRecordメソッドは保存ボタンを押した時に実行するメソッドです。
ここでキャラクターの位置や角度をデフォルトの値として保持しておきます。
Animatorの保存は
1 2 3 | animator.StartRecording(保存フレーム数); |
↑のように保存フレーム数を指定して保存を開始させます。
指定出来る数は10000までで0を指定するとStopRecordingメソッドが呼ばれるまで保存します。
キャラクターのAnimatorとRecorderのAnimatorの両方のStartRecordingを呼び出して同期させます。
StopRecordメソッドは保存を停止ボタンを押した時に呼び出すメソッドでこちらはStopRecordingメソッドを呼び出して保存を停止しているだけです。
PlayBackメソッドでは
1 2 3 4 5 6 | // 録画してなければ何もしない if (animator.recorderStopTime <= 0) { return; } |
のようにAnimatorのrecorderStopTimeプロパティで保存を終了した位置を取得出来るのでそれが0以下だと保存してないのでreturnでその後の処理をさせません。
その後Rebindメソッドで再配置します。
その後
1 2 3 | animator.StartPlayBack(); |
でAnimatorの再生をします。
再生をする時に保存の最初の位置から再生したいので
1 2 3 | animator.playbackTime = animator.recorderStartTime; |
とanimator.recorderStartTimeで最初の位置を取得しそれをanimator.playbackTimeに入れることで最初から再生させます。
StopPlayBackメソッドは再生を停止ボタンを押した時に呼び出すメソッドで
1 2 3 | animator.StopPlayback (); |
のようにStopPlayBackメソッドを呼び出して再生を停止させます。
Updateメソッドでは再生中にplaybackTimeの値を更新して保存したAnimatorを徐々に再生させています。
1 2 3 | float playBackTime = recorderAnimator.playbackTime + recorderAnimator.GetFloat ("Speed") * Time.deltaTime; |
再生位置はRecorderAnimatorのplaybackTimeにRecorderAnimatorのアニメーションパラメータのSpeed値にTime.deltaTimeをかけて再生位置を計算します。
保存した位置を超えた場合は最初に戻り、また再生していくという形になります。
Recorderゲームオブジェクトのインスペクタは
↑のようになります。
animatorには操作するキャラクターのAnimatorを設定します。
Recorderの機能を呼び出すUIの作成
先ほど作成したAnimatorRecorderスクリプトのメソッドを呼び出すUIのボタンを作成します。
↑のように4つのボタンを作成し、それぞれのボタンのOnClickでStartRecordメソッド、StopRecordメソッド、PlayBackメソッド、StopPlayBackメソッドを指定します。
これで機能が完成しました。
終わりに
今回の記事の機能を作成するとAnimatorの保存が出来ますが、保存したデータの出力やキャラクターの動いた位置を記録するのは難しいので、自前のキャラクターの動きを保存する機能を作成しました。
というか・・・、このAnimatorの機能を知らずに先にそちらを作ってしまったんですが・・・・(^_^;)
その機能は

の記事を参照してください。
参考サイト
今回の機能を作成するにあたり
のフォーラムのスクリプトを参考にさせて頂きました。
そちらのスクリプトはアニメーションスピードを変更する部分まで作成されています。