前書き
今回紹介する議題は他のサイトや、他Qiitaユーザーの皆様も紹介されている「Unity3dでTPS視点操作をどのように実装するか?」です。今回紹介する視点操作は以下のとおりです。
- シューティング系
- メタルギアソリッド系
注意:正規表現があまりキレイなコードではありません。ご指摘いただけますと幸いです。
gif内でカメラ操作がカクついているのは、トラックボールマウスを使用しているからです。
Unity3Dでの視点操作の種類別コード
シューティング系
良くTPSシューティングゲームに採用されているカメラ操作方法です。PUBGやFortnightの標準操作はこれですね。マウスをY軸(上下)方向に動かすとはカメラは上下に動き、X軸に動かすと__キャラクターの向きが左右に動きます__
using UnityEngine;
public class MouseController : MonoBehaviour
{
[SerializeField]
private Transform character; //キャラクターをInspectorウィンドウから選択してください
[SerializeField]
private Transform pivot; //キャラクターの中心にある空のオブジェクトを選択してください
void Start()
{
//エラーが起きないようにNullだった場合、それぞれ設定
if(character == null)
character = transform.parent;
if(pivot == null)
pivot = transform;
}
//カメラ上下移動の最大、最小角度です。Inspectorウィンドウから設定してください
[Range(-0.999f, -0.5f)]
public float maxYAngle = -0.5f;
[Range(0.5f, 0.999f)]
public float minYAngle = 0.5f;
// Update is called once per frame
void Update()
{
//マウスのX,Y軸がどれほど移動したかを取得します
float X_Rotation = Input.GetAxis("Mouse X");
float Y_Rotation = Input.GetAxis("Mouse Y");
//Y軸を更新します(キャラクターを回転)取得したX軸の変更をキャラクターのY軸に反映します
character.transform.Rotate(0, X_Rotation, 0);
//次はY軸の設定です。
float nowAngle = pivot.transform.localRotation.x;
//最大値、または最小値を超えた場合、カメラをそれ以上動かない用にしています。
//キャラクターの中身が見えたり、カメラが一回転しないようにするのを防ぎます。
if (-Y_Rotation != 0)
{
if (0 < Y_Rotation)
{
if (minYAngle <= nowAngle)
{
pivot.transform.Rotate(-Y_Rotation, 0, 0);
}
}
else
{
if (nowAngle <= maxYAngle)
{
pivot.transform.Rotate(-Y_Rotation, 0, 0);
}
}
}
}
}
上記のスクリプトを動かしたいカメラにアタッチし、unitychanの胴体の中心部分に空のオブジェクトを作成(Pivotと呼びます)し、カメラをその子要素にしてください。↓
その後InspectorウィンドウからCharacter
とPivot
にそれぞれのオブジェクトを設定してください。
上のGifではunitychan本体をCharacter
に、上で作ったPivotをpivot
に設定しました。↓
Pivotがあることで、カメラが上下に移動しても、しっかりとキャラクターを映す様になっています。TPSの目的は可愛い/カッコいいキャラクターが画面に映ることも利点の一つですからね。多くの紹介サイトではこれを忘れています。
Min Y Angle
とMax Y Angle
ですが、これを調整することで、カメラの上下移動範囲を広げることが出来ます。カメラ操作でもっと上まで見えるようにしたかったら、Max Y Angle
を大きく設定するといいでしょう。
メタルギア・ソリッド系
メタルギア・ソリッドVを参考にしたカメラ操作方法です。スニーキングミッションは隠れることが重要で、後ろに敵が居るか確認したいときなどに視点を移動すると体の向きが変わり、物音を発したりや体が物陰からはみ出てしまうと大問題です。そのため、このカメラ操作で
はマウスをY軸(上下)方向に動かすとはカメラは上下に動き、X軸に動かすと__カメラがキャラクターの周りを回ります__
using UnityEngine;
public class MetalGearMouseController : MonoBehaviour
{
[SerializeField]
private Transform pivot = null;
void Start()
{
if (pivot == null)
pivot = transform.parent;
}
[Range(-0.999f, -0.5f)]
public float minYAngle = -0.5f;
[Range(0.5f, 0.999f)]
public float maxYAngle = 0.5f;
void Update()
{
//マウスのX,Y軸がどれほど移動したかを取得します
float X_Rotation = Input.GetAxis("Mouse X");
float Y_Rotation = Input.GetAxis("Mouse Y");
//Y軸を更新します(キャラクターを回転)取得したX軸の変更をキャラクターのY軸に反映します
pivot.transform.Rotate(0, X_Rotation, 0);
//次はY軸の設定です。
float nowAngle = pivot.transform.localRotation.x;
//最大値、または最小値を超えた場合、カメラをそれ以上動かない用にしています。
//カメラが一回転しないようにするのを防ぎます。
if (-Y_Rotation != 0)
{
if (0 < Y_Rotation)
{
if (minYAngle <= nowAngle)
{
pivot.transform.Rotate(Y_Rotation, 0, 0);
}
}
else
{
if (nowAngle <= maxYAngle)
{
pivot.transform.Rotate(Y_Rotation, 0, 0);
}
}
}
//操作していると、Z軸がだんだん動いていくので、0に設定してください。
pivot.eulerAngles = new Vector3(pivot.eulerAngles.x, pivot.eulerAngles.y, 0f);
}
}
Inspectorウィンドウからの設定方法は上記シューティング系コードとほぼ同じです。ですが、今回はCharacter
を回転させる必要がないので、Pivot
のみとなっております。
終わりに
QiitaのMDってアンダーライン出来ないんですね…。また、マウスX,YがTransformのX,yと逆になっているのに、なぜ正しく動くのか謎です…ご存知の方はぜひ教えてください。