読者です 読者をやめる 読者になる 読者になる

Onoty3D

Unityに関するメモとか

アニメーションをじっくり見よう!

f:id:onoty3d:20150421190658p:plain

さて、前回EF-12さんの作成されたファイティング ユニティちゃんのモーションをプロ生ちゃんに適用させる、という記事を書いたのですが、ファイティング ユニティちゃんの各モーションは、さすが達人の技というか、素人の目にははやすぎてとらえられないパンチやキックもあります。

それをじっくり観察するにはどうしたらよいか。

ひとつはゲーム全体の時の流れをゆっくりにさせる、という方法があります。
UnityエディタでEdit>Project Settings>Timeと選び、TimeManagerを開きます。
f:id:onoty3d:20150421185753p:plain
Time Scaleという項目が時間の設定となり、数値を小さくすればするほどゆっくりとした時の流れになります。

また、全体の時の流れはそのままで特定アニメーションだけをゆっくり再生したい、という場合もあるかもしれません。
この場合は、まず特定アニメーションが含まれるAnimatorを開き、そのアニメーションのstateを選択します。
f:id:onoty3d:20150421185843p:plain
Speedという項目が時間の設定となり、数値を小さくすればするほどゆっくり再生されます。

毎回設定をいじるのも面倒なので、現在再生中のアニメーションを任意の速度に変更できるスクリプトを書きました。(ソースは最後)
f:id:onoty3d:20150421185911p:plain
AnimatorControllerと混同しやすいのでもっと違ったクラス名でもよかったかも…。

アニメーションの再生中にSpeed Valueの値を変化させると、その値に従って再生速度が変化します。
とりあえず0~5倍速の範囲で設定できるようにしています。

等倍
f:id:onoty3d:20150421190023g:plain

0.3倍
f:id:onoty3d:20150421190053g:plain

5倍
f:id:onoty3d:20150421190128g:plain

また、Seek Valueという項目は、現在再生中のアニメーションの任意の部分を表示させることができます。
Speed Valueを0にした状態で、Seek Valueの値を変化させると、任意の部分のポーズが表示できます。
0がアニメーション開始時点のポーズ、1がアニメーション終了時点のポーズです。
特定の瞬間の静止画を取りたいとき等に使えるかもしれません。

f:id:onoty3d:20150421190223g:plain

using UnityEngine;

namespace PronamaChan
{
    public class AnimationController : MonoBehaviour
    {
        [Range(0f, 5f)]
        public float SpeedValue = 1f;

        [Range(0f, 1f)]
        public float SeekValue = 0f;

        private Animator _animator;
        private bool _isStarted;

        // Use this for initialization
        private void Start()
        {
            this._animator = this.gameObject.GetComponent<Animator>();
            this._animator.speed = this.SpeedValue;
            this._isStarted = true;
        }

        // Update is called once per frame
        private void Update()
        {
        }

        public void ChangeSpeed()
        {
            if (this._animator == null) return;

            this._animator.speed = this.SpeedValue;
        }

        public void Seek()
        {
            if (this._animator == null) return;

            var currentState = this._animator.GetCurrentAnimatorStateInfo(0);
            this._animator.Play(currentState.fullPathHash, -1, this.SeekValue);
        }

        public void OnValidate()
        {
            if (Application.isPlaying && this._isStarted)
            {
                this.ChangeSpeed();

                if (this.SpeedValue == 0f)
                {
                    this.Seek();
                }
            }
        }
    }
}