[Unity]Starter Assets - ThirdPersonでキャラクターを一時停止する（おまけでRigidbodyの場合も）

# 概要
Unityで一時停止をしたい時には

```cs
        Time.timeScale = 0;
```
このような記述が使われますが、ゲーム進行は止めたいけれどUIエフェクトの制御は継続したいみたいな「時間自体を止められると困る」場合もあります。
そんな時はキャラクターや各種オブジェクトを直接停止する方法がありますが、CharacterControllerやRigidbodyを停止するだけだと、例えばジャンプ中に一時停止した場合、再開するとジャンプが途中だったのに終わってしまうなんてことが起こったりします。

# 本文
Starter Assets - ThirdPersonに一時停止機能を追加します。
ThirdPersonController.csのUpdateを以下のように書き換えます。

```cs
        private bool _isStop;
        private Vector3 _temporaryVelocity;
        private float _temporaryGravity;

        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.Return))
            {
                if (!_isStop)
                {
                    _speed = 0;
                    // 行動停止
                    _animator.enabled = false;
                    _temporaryVelocity = _controller.velocity;
                    _controller.SimpleMove(Vector3.zero);
                    _temporaryGravity = Gravity;
                    Gravity = 0;
                }
                else
                {
                    // 行動再開
                    _animator.enabled = true;
                    Gravity = _temporaryGravity;
                    _controller.SimpleMove(_temporaryVelocity);
                }
                _isStop = !_isStop;
            }

            _hasAnimator = TryGetComponent(out _animator);

            JumpAndGravity();
            GroundedCheck();
            if (!_isStop) Move();
        }
```


![Movie_011.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/9abe5c09-c227-897a-31d3-d714115f7762.gif)



:::note info
一時停止する時の運動状態を覚えておいて、停止を解除するタイミングに復元することで動きの連続性を保たせています。
:::


# Rigidbodyの場合
Rigidbodyで動くキャラクターの場合も同じ考え方で実現できます。

```cs
using UnityEngine;

public class RigidbodyTest : MonoBehaviour
{
    private Rigidbody _myRigidbody;
    private bool _isStop;
    private Vector3 _temporaryVelocity;
    private Vector3 _temporaryAngularVelocity;
    private Animator _animator;

    private void Start()
    {
        _myRigidbody = GetComponent<Rigidbody>();
        _animator = GetComponent<Animator>();
        _myRigidbody.AddForce(new Vector3(1f, 1f, 0f) * 300f);
        _myRigidbody.angularVelocity = new Vector3(0f, 0f, 1f) * 100f;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Return))
        {
            if (!_isStop)
            {
                // 行動停止
                if (_animator != null) _animator.enabled = false;
                _temporaryVelocity = _myRigidbody.velocity;
                _temporaryAngularVelocity = _myRigidbody.angularVelocity;
                _myRigidbody.isKinematic = true;
            }
            else
            {
                // 行動再開
                if (_animator != null) _animator.enabled = true;
                _myRigidbody.isKinematic = false;
                _myRigidbody.velocity = _temporaryVelocity;
                _myRigidbody.angularVelocity = _temporaryAngularVelocity;
            }
            _isStop = !_isStop;
        }
    }
}
```


![Movie_007.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/166ad3a0-9988-0e77-0523-a4fe62bc4401.gif)

# 補足
実際に実装する時はポーズフラグをUniRxで購読するようにするといい感じになると思います！あと、Cinemachineを使っている時は追従を適宜止めるのが良さそうです。
トレイルやパーティクルなど、あえて停止させないことでおしゃれな演出を作ることもできると思います:star: