[Unity]TPSカメラの機能をつけたい( 3rd Person Controller + Fly Mode)

## 概要
現在、個人開発しているゲームはTPS視点のもの。
実装にあたって諸々調査し、最もコストがかからず、拡張性も高い手法を検討する。

## 検討
まず大きくは「自前で実装」か「アセットを利用」か。
アセットを利用する場合は、以下のメリット、デメリットがある。

**メリット**

- うまくいけば即時導入が可能で、時間を大幅に短縮できる。
- 公開されているアセットはプロが作成しているものと思われるので、クオリティが高いはず。

**デメリット**

- 有料の場合、費用がかかる。
- Unityのバージョンアップに応じてメンテされなくなったときに「自前で実装する」か、「代わりのアセットを探して採用する」かになる。どちらにせよ元の機能の完全なる再現は難しいだろう。
- 開発者ではないので、設計思想はコードを読んで感じ取るしかない。したがって細かな拡張が難しい。
- そもそも使い方がわかるのか怪しい。



無料のものとして見つかったのは、
Unity Starndard Assetと、レビュー数700を超え(2021/01/02時点)、★4の良さげなアセット[3rd Person Controller + Fly Mode](https://assetstore.unity.com/packages/templates/systems/3rd-person-controller-fly-mode-28647)。

後者のアセットは、[必携のアセット](https://assetstore.unity.com/lists/must-have-assets-25777)としてアセットストアで選出されているものの一つらしい。

Unity Starndard Assetは残念ながらサポート終了しており、アップデートもされていないので、後者のアセットを試して使い方をまとめてみる。

## 3rd Person Controller + Fly Mode の使い方
### インポート

愚直に自身が製作中のUnityプロジェクトへ本アセットをデフォルト設定のままインポートしたところ、
Project Settingｓが上書きされてプロジェクトが破壊された。

そもそもデフォルト設定ですべてインポートする必要はなく、以下をインポートすればいいらしい。
パッケージ全体をインポートする必要はなく、以下のみが必要

- 「Animations」フォルダ全て
- 「Animator」フォルダ全て
- 「Materials」配下のCharacter.PhysicMaterial
- 「Scripts」 > 「LevelScripts」内の「ThirdPersonOrbitCamBasic.cs」
- 「PlayerScripts」フォルダ全て
- 「ProjectSettings」配下の「InputManager.asset」


### 必要なもの、こと
**参考**
- [Getting started with your Third Person Game](https://homepages.dcc.ufmg.br/~allonman/thirdperson/)
- 本Asset内に含まれるREADME.pdf


1. 前提： TPS視点とする操作対象のモデル(★)： ヒューマノイド互換モデル(要調査)でなければならない
2. ★のシーンへの追加、設定
    - TagをPlayerに設定
    - Animator - ControllerでCharacterControllerを選択
3. ★へのColliderのアタッチ、設定
    - コライダーは地面とモデルの間にくるようにしないと、モデルが移動できないことに注意
4. ★へのRigidBodyのアタッチ、設定
    - Mass(質量)
    - Constraints - Freeze RotationでX,Y,Z軸へチェック (オブジェクトがその軸を中心として回転してしまわないようにする？)
5. ★へのScript(BasicBehavior.cs)のアタッチ(設定値は任意、詳細は後述)
    - Player Camera: Main CameraをD&D
6. ★へのScript(MoveBahaviour.cs)のアタッチ(設定値は任意、詳細は後述)
7. ★へのScript(AimBahaviour.cs)のアタッチ(設定値は任意、詳細は後述)
8. メインカメラへのScript(ThirdPersonOrbitCamBasic.cs)のアタッチ(設定値は任意、詳細は後述)
    - Player: ★のオブジェクトをD&DすればOK

#### ThirdPersonOrbitCamBasic
以下の全てのTPSカメラとしての機能を管理する

- プレイヤーの周りでカメラを動かす
- 視野の変更
- 衝突を回避するためのズームイン・ズームアウト

**外部パラメータ**

    パラメータ|説明
    ---|---
    Player|プレイヤーになるゲームオブジェクト(の参照)
    Pivot Offset|よくわからん・・・・とりあえずモデルに対するローカル座標あることは確か(※)
    Cam Offset|よくわからん・・・とりあえずモデルに対するローカル座標であることは確か(※)
    Smooth|カメラの動きの反応の速さを表す係数(らしいが、いじってみても特に変化を感じなかった)
    Horizontal Aiming Speed|横方向のカメラの移動速度(これはユーザーにいじらせるべき設定値だろう)
    Vertical Aiming Speed|縦方向のカメラの移動速度(これはユーザーにいじらせるべき設定値だろう)
    Max Vertical Angle|縦方向のカメラの移動の最大角度。初期位置からカメラをどこまで下回転方向に動かせるか？を制限し、普通は正の値になるっぽい。角度は右ねじ方向が正。
    Min Vertical Angle|縦方向のカメラの移動の最小角度。初期位置からカメラをどこまで上回転方向に動かせるか？を制限し、普通は負の値になるっぽい。角度は右ねじ方向が正。
    X Axis|ジョイパッド用。デフォルトのX軸入力名
    Y Axis|ジョイパッド用。デフォルトのY軸入力名

※試してわかったこととして、
Cam Offsetを0,0,0 Pivot Offsetを0,1.5,-2 にすると、
カメラをマウスで上下にふってもカメラ自身の座標は動かず、視野のみ移動した。

逆に、Cam Offsetを0,1.5,-2 Pivot Offsetを0,0,0にするとカメラもついてきた。
しかし、上に振りすぎるとモデル自身が見えなくなる・・・

すごくバランスがいいのが
Cam Offsetを0,1,0 Pivot Offsetを0,0.5,-2
のパターンで、これぞTPSという視点。

理由はよくわからんが、
初期位置で置きたいカメラの高さをY, カメラをモデルから後ろ-Zの位置に置きたいならば、
とりあえず
Cam Offset = 0,Y*2/3,0
Pivot Offset = 0, Y*1/3, -Z
という座標に調整しておけばいい感じのTPS視点になるっぽい。



#### BasicBehaviour

プレイヤーの動作を管理する。

**外部パラメータ**

    パラメータ|説明
    ---|---
    Player Camera|ユーザーが操作するプレイヤーに紐づくTPSカメラ(の参照)
    Turn Smoothing|カメラの視点変化に合わせてプレイヤーの移動が追随する反応スピード。1が即時で、0〜1の値っぽい。
    Sprint FOV|プレイヤーがスプリント中のカメラの視野。通常時視野を100とした、0〜100の値っぽい
    Sprint Button|プレイヤーにスプリントさせるためのデフォルトの入力名(多分スクリプトで特定の入力があったときにこの名前を割り当てるようにすれば、任意の入力でのスプリント動作が可能ってことだろう)

BasicBehaviorでは、Unityのデフォルトの水平、垂直入力軸を使用してプレイヤーの動作を制御する。

#### MoveBehaviour
ウォーク、ラン、スプリント、ジャンプの動作に対応する。

**外部パラメータ**

    パラメータ|説明
    ---|---
    Walk Speed|プレーヤーのデフォルトのウォーク時の移動速度（ブレンドツリーによって制御される）
    Run Speed|プレーヤーのデフォルトのラン時の移動速度（ブレンドツリーによって制御される）
    Sprint Speed|プレーヤーのデフォルトのスプリント時の移動速度（ブレンドツリーによって制御されます）。
    Speed Damp Time|ウォーク⇔ラン⇔スプリントへのアニメーションの変化に影響する遅延速度。大きいほど次の動作アニメーションを始めるのが遅れる
    Jump Height|ジャンプの高さのデフォルト値
    Jump Inertial Force|プレイヤーがジャンプしてから着陸するまでの間に適用される水平方向の慣性の力。値が大きいほど、ジャンプ距離がのびる。

この動作スクリプトでは、Unityのデフォルトのジャンプ入力軸を使ってジャンプ動作を処理する。
移動速度はマウスホイール軸によって制御される。

#### AimBehaviorBasic
照準とカニ歩き移動を処理する。

**外部パラメータ**

    パラメータ|説明
    ---|---
    Aim Button|照準を覗く動作をするための入力名
    Shoulder Button|肩の方向を変更するための入力名
    Crosshair|デフォルトの照準のクロスヘア。パラメータなしの場合は、クロスヘアは表示されない。
    Aim Turn Smoothing|いろいろいじってみたがよくわからない！！
    Aim Pivot Offset|エイム中にカメラが見つめる頂点のデフォルトの座標(プレイヤーのローカル座標におけるオフセット値)
    Aim Cam Offset|エイム中のカメラのデフォルトの座標(プレイヤーのローカル座標におけるオフセット値。いじってみてわかったイメージとしては、x,y,z = 対象のモデルを左右方向にどのくらい映すか, 対象のモデル上下方向にどのくらい映すか, カメラをどのくらい後ろにおくか)

### 所感
**日本語訳して実際に試してと時間をかけてしまったが、わかってしまえば非常に簡単で有用そう** だと感じた。
・・・デメリットで挙げた部分については個人開発なので、ある程度妥協すればまぁ・・・ね。

なお、スマホアプリ版は有料で$13程度っぽい。
スクリプトの中身をいじればスマホアプリ向けに拡張はできるんだろうが・・・
その手間を$13で買えるならばそうした方が圧倒的によさげ。