5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GeekSalonAdvent Calendar 2023

Day 13

Unityで「三人称視点操作(TPP)」を作ってみよう!

Posted at

はじめに

受講生からもよく「三人称視点のゲーム作りたい!」という声を聞くので、この記事を読んだら、一発で実装できる記事を書こうと思います!(Unityの使い方は知ってる前提で書くよ~)

Unityには、便利な「Cinemachine」ってのがありますが、折角なら自分でプログラミング書いた方が楽しいだろ!!ということで、使いません🙅‍♂️
気軽に実装って人は、「Cinemachine」使ってみるのもありかと!

今回、qiitaの記事を初めて書くので、みにくかったら、ごめぇんねっ☆

完成

完成はこんな感じです!

ezgif.com-video-to-gif-converted.gif

今回の仕様は、

  • WASD入力でのカメラを基点とした移動
  • マウス入力で、プレイヤーを中心としてカメラが上下左右に回転する

といったものになっております。

それでは作っていくぅぅぅぅぅぅぅ!

1.事前準備

まず、なんでもOKなんですけど、

  • 動かすキャラクター(前後左右が分かるもの)
  • ステージ

の2点を用意しましょう

キャラクターはcapsuleにcubeを付けたり、ステージはcube引き伸ばしたりして適当に作れればOK!!

これは、capsuleとかcubeとかを組み合わせた"ポチタ"です。
今回は、こいつを動かしていきます!
image (55).png

2.プレイヤーの設定をする

プレイヤーにRigidBodyという物理演算をしてくれるコンポネントを追加しましょう!
image (56).png

画像の「Add Component」ってところ押してください。

image (57).png

検索欄に「ri」と打ったら、「Rigidbody」がでてくるので、左クリックで追加してあげてください。

image (58).png

追加ができたら

  • Interpolate → Interpolateに変更
  • Freeze Rotarion → x,y,zにチェックを入れる

と変更してください

3.カメラを移動させとく

最初のカメラの位置を常に保った状態で、カメラが動くので、良い感じの位置にしときましょう。

位置はお好みでOKですが、まあ、大体こんくらいかなって画像載せときます。
image.png

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」にアタッチ!!!

image.png

そして、Inspecterのほうで、「Player」のオブジェクトをドラック&ドロップで入れてあげましょう。
image.png

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()で回転をさせています。
後半にわちゃわちゃ書いてるのは、滑らかに回転させるためのものです。


コピペができたら、「自分が作ったプレイヤー」にアタッチ!!!
image.png

Inspecterから、数値を変更できるようにしてるのですが、好きに触ってみてください。
個人的に画像の設定くらいがちょうどよかったです。
image.png

おわり!!

これで、三人称視点移動のプレイヤーが完成です!
ただ、ゲームの仕様によっては、移動方法の実装を変える必要があるので、そこはがんばってね♡

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?