はじめに
受講生からもよく「三人称視点のゲーム作りたい!」という声を聞くので、この記事を読んだら、一発で実装できる記事を書こうと思います!(Unityの使い方は知ってる前提で書くよ~)
Unityには、便利な「Cinemachine」ってのがありますが、折角なら自分でプログラミング書いた方が楽しいだろ!!ということで、使いません🙅♂️
気軽に実装って人は、「Cinemachine」使ってみるのもありかと!
今回、qiitaの記事を初めて書くので、みにくかったら、ごめぇんねっ☆
完成
完成はこんな感じです!
今回の仕様は、
- WASD入力でのカメラを基点とした移動
- マウス入力で、プレイヤーを中心としてカメラが上下左右に回転する
といったものになっております。
それでは作っていくぅぅぅぅぅぅぅ!
1.事前準備
まず、なんでもOKなんですけど、
- 動かすキャラクター(前後左右が分かるもの)
- ステージ
の2点を用意しましょう
キャラクターはcapsuleにcubeを付けたり、ステージはcube引き伸ばしたりして適当に作れればOK!!
これは、capsuleとかcubeとかを組み合わせた"ポチタ"です。
今回は、こいつを動かしていきます!
2.プレイヤーの設定をする
プレイヤーにRigidBodyという物理演算をしてくれるコンポネントを追加しましょう!
画像の「Add Component」ってところ押してください。
検索欄に「ri」と打ったら、「Rigidbody」がでてくるので、左クリックで追加してあげてください。
追加ができたら
- Interpolate → Interpolateに変更
- Freeze Rotarion → x,y,zにチェックを入れる
と変更してください
3.カメラを移動させとく
最初のカメラの位置を常に保った状態で、カメラが動くので、良い感じの位置にしときましょう。
位置はお好みでOKですが、まあ、大体こんくらいかなって画像載せときます。
4.メインカメラの制御プログラム作る
まず、「CameraController」って名前でScriptを作成します。
作成できたら、開いて以下のプログラムをコピペ!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
[SerializeField] GameObject player;
Vector3 currentPos;//現在のカメラ位置
Vector3 pastPos;//過去のカメラ位置
Vector3 diff;//移動距離
private void Start()
{
//最初のプレイヤーの位置の取得
pastPos = player.transform.position;
}
void Update()
{
//------カメラの移動------
//プレイヤーの現在地の取得
currentPos = player.transform.position;
diff = currentPos - pastPos;
transform.position = Vector3.Lerp(transform.position, transform.position + diff, 1.0f);//カメラをプレイヤーの移動差分だけうごかすよ
pastPos = currentPos;
//------カメラの回転------
// マウスの移動量を取得
float mx = Input.GetAxis("Mouse X");
float my = Input.GetAxis("Mouse Y");
// X方向に一定量移動していれば横回転
if (Mathf.Abs(mx) > 0.01f)
{
// 回転軸はワールド座標のY軸
transform.RotateAround(player.transform.position, Vector3.up, mx);
}
// Y方向に一定量移動していれば縦回転
if (Mathf.Abs(my) > 0.01f)
{
// 回転軸はカメラ自身のX軸
transform.RotateAround(player.transform.position, transform.right, -my);
}
}
}
ちょい解説。
やってることは2つ!
- カメラ自身の移動
- プレイヤーを中心としたカメラの回転
『カメラ自身の移動』では、
プレイヤーが移動する前の位置、後の位置の差を取って、その分だけカメラも移動させてるだけです!
『カメラの回転』では、
マウスのX方向の入力、Y方向の入力を取得してきて、入力された分だけプレイヤーを中心に回転させてるだけです!
オブジェクトを中心に回転は、transform.RotateAround()で実装できます。
コピペができたら、「MainCamera」にアタッチ!!!
そして、Inspecterのほうで、「Player」のオブジェクトをドラック&ドロップで入れてあげましょう。
5.プレイヤーの制御プログラム作る
まず、「PlayerController」って名前でScriptを作成します。
作成できたら、開いて以下のプログラムをコピペ!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
float moveSpeedIn;//プレイヤーの移動速度を入力
Rigidbody playerRb;//プレイヤーのRigidbody
Vector3 moveSpeed;//プレイヤーの移動速度
Vector3 currentPos;//プレイヤーの現在の位置
Vector3 pastPos;//プレイヤーの過去の位置
Vector3 delta;//プレイヤーの移動量
Quaternion playerRot;//プレイヤーの進行方向を向くクォータニオン
float currentAngularVelocity;//現在の回転各速度
[SerializeField]
float maxAngularVelocity = Mathf.Infinity;//最大の回転角速度[deg/s]
[SerializeField]
float smoothTime = 0.1f;//進行方向にかかるおおよその時間[s]
float diffAngle;//現在の向きと進行方向の角度
float rotAngle;//現在の回転する角度
Quaternion nextRot;//どんくらい回転するか
void Start()
{
playerRb = GetComponent<Rigidbody>();
pastPos = transform.position;
}
void Update()
{
//------プレイヤーの移動------
//カメラに対して前を取得
Vector3 cameraForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
//カメラに対して右を取得
Vector3 cameraRight = Vector3.Scale(Camera.main.transform.right, new Vector3(1, 0, 1)).normalized;
//moveVelocityを0で初期化する
moveSpeed = Vector3.zero;
//移動入力
if (Input.GetKey(KeyCode.W))
{
moveSpeed = moveSpeedIn * cameraForward;
}
if (Input.GetKey(KeyCode.A))
{
moveSpeed = -moveSpeedIn * cameraRight;
}
if (Input.GetKey(KeyCode.S))
{
moveSpeed = -moveSpeedIn * cameraForward;
}
if (Input.GetKey(KeyCode.D))
{
moveSpeed = moveSpeedIn * cameraRight;
}
//Moveメソッドで、力加えてもらう
Move();
//慣性を消す
if(Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.D))
{
//playerRb.velocity = Vector3.zero;
// playerRb.angularVelocity = Vector3.zero;
}
//------プレイヤーの回転------
//現在の位置
currentPos = transform.position;
//移動量計算
delta = currentPos - pastPos;
delta.y = 0;
//過去の位置の更新
pastPos = currentPos;
if (delta == Vector3.zero)
return;
playerRot = Quaternion.LookRotation(delta, Vector3.up);
diffAngle = Vector3.Angle(transform.forward, delta);
//Vector3.SmoothDampはVector3型の値を徐々に変化させる
//Vector3.SmoothDamp (現在地, 目的地, ref 現在の速度, 遷移時間, 最高速度);
rotAngle = Mathf.SmoothDampAngle(0, diffAngle, ref currentAngularVelocity, smoothTime, maxAngularVelocity);
nextRot = Quaternion.RotateTowards(transform.rotation, playerRot, rotAngle);
transform.rotation = nextRot;
}
/// <summary>
/// 移動方向に力を加える
/// </summary>
private void Move()
{
//playerRb.AddForce(moveSpeed, ForceMode.Force);
playerRb.velocity = moveSpeed;
}
}
ちょい解説。
やってることは2つ!
- カメラを基点とした、プレイヤーの移動
- 移動方向にプレイヤーを回転
『プレイヤーの移動』では、
「MainCamera」の正面、右方向を取得することによって、カメラに対して前後左右に進むように実装してます
『プレイヤーの回転』では、
プレイヤーの進む前の位置、進んだ後の位置から、移動量を計算し、Quaternion.LookRotation()で回転をさせています。
後半にわちゃわちゃ書いてるのは、滑らかに回転させるためのものです。
コピペができたら、「自分が作ったプレイヤー」にアタッチ!!!
Inspecterから、数値を変更できるようにしてるのですが、好きに触ってみてください。
個人的に画像の設定くらいがちょうどよかったです。
おわり!!
これで、三人称視点移動のプレイヤーが完成です!
ただ、ゲームの仕様によっては、移動方法の実装を変える必要があるので、そこはがんばってね♡