わかゲームスタジオ

ゲーム制作初心者専門学生の備忘録

Unity カメラの位置リセットを追加する

前回スティックでカメラを動かしたので、今回はカメラの位置リセットを設定しようと思います。
↓前回↓
wakagamestudio.hatenablog.jp

↓今回できること↓

Unity var2019.3.4f1

①InputManagerを編集する

f:id:WakaiGames:20200904174149p:plain

  • カメラ向きリセット用のインプットを設定しておきます。

②変数を宣言する

    [Header("カメラ位置リセットする遷移時間")]
    [SerializeField]
    private float camReset;     //カメラ位置リセットする遷移時間

    private bool reset;     //カメラリセット
    private float resetTime;
    private float resetAngle;
    private float nowTime;
    private float[] camnum;
    private float[] before;
    private Vector2 initRotate; //初期角度X
  • 向きリセットに使う変数たちです。

③Startで初期化する

        initRotate.x = transform.localEulerAngles.x;
        initRotate.y = transform.localEulerAngles.y;
        reset = false;
        resetTime = camReset;
        resetAngle = initRotate.x;
        camnum = new float[2];
        before = new float[2];
  • Startで初期化しておきます。

④Updateに処理を追加する

        //カメラ位置リセット中
        if (reset && nowTime <= resetTime)
        {
            nowTime += Time.deltaTime;
            transform.RotateAround(target.transform.position, Vector3.down, ResetCalc(0));
            transform.RotateAround(target.transform.position, transform.right, ResetCalc(1));
        }
        else
        {
            reset = false;
        }

        //カメラ位置リセット開始
        if (Input.GetButtonDown("JoyR") && !reset)
        {
            resetTime = camReset;
            resetAngle = initRotate.x;
            ResetStart();
        }
  • Updateでリセット回転中の動きを書きます。

⑤関数を追加する

    private void ResetStart()
    {
        camnum[0] = transform.localEulerAngles.y;
        if (camnum[0] >= 180)
        {
            camnum[0] -= 360;
        }
        float pnum = target.transform.localEulerAngles.y;
        if (pnum >= 180)
        {
            pnum -= 360;
        }
        camnum[0] -= pnum;
        if (camnum[0] >= 180)
        {
            camnum[0] -= 360;
        }
        else if (camnum[0] < -180)
        {
            camnum[0] += 360;
        }
        camnum[1] = -transform.localEulerAngles.x + resetAngle;
        if (camnum[1] < 0)
        {
            camnum[1] += 360;
        }
        if (camnum[1] >= 180)
        {
            camnum[1] -= 360;
        }
        nowTime = 0;
        before[0] = 0;
        before[1] = 0;
        reset = true;
    }

    private float ResetCalc(int sel)
    {
        float Percentage = nowTime / resetTime;
        float[] num = new float[2];
        float[] pos = new float[2];

        num[sel] = camnum[sel] * Percentage;
        pos[sel] = num[sel] - before[sel];
        before[sel] = num[sel];
        return pos[sel];
    }
  • リセット開始時に初期化する関数と、向きを360°に変換する用の計算関数です。

前回分も含む全コード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraAction : MonoBehaviour
{
    [Header("カメラが向くターゲット")]
    [SerializeField]
    private GameObject target; //ターゲット

    [Header("回転するスピード")]
    [SerializeField]
    private Vector2 rotateSpeed;
    [Header("回転できる上限")]
    [SerializeField]
    private float rotateCeiling;//回転できる上限
    [Header("回転できる下限")]
    [SerializeField]
    private float rotateLower;  //回転できる下限
    [Header("スティックの入力制限")]
    [SerializeField]
    private float inputLimit;   //スティックの入力制限

    [Header("左右反転")]
    public bool LROpposite; //trueで反転
    [Header("上下反転")]
    public bool UDOpposite; //trueで反転

    [Header("カメラ位置リセットする遷移時間")]
    [SerializeField]
    private float camReset;     //カメラ位置リセットする遷移時間

    private bool reset;     //カメラリセット
    private float resetTime;
    private float resetAngle;
    private float nowTime;
    private float[] camnum;
    private float[] before;
    private Vector2 initRotate; //初期角度X

    private Vector3 beforePos;  //ターゲットの前位置

    private void Start()
    {
        //beforePosを初期化
        beforePos = target.transform.position;

        initRotate.x = transform.localEulerAngles.x;
        initRotate.y = transform.localEulerAngles.y;
        reset = false;
        resetTime = camReset;
        resetAngle = initRotate.x;
        camnum = new float[2];
        before = new float[2];
    }

    private void Update()
    {
        //ターゲットが動いた分移動
        transform.position += target.transform.position - beforePos;

        //入力値を判定
        Vector3 angle = new Vector3(Input.GetAxis("HorizontalR") * rotateSpeed.x, Input.GetAxis("VerticalR") * rotateSpeed.y, 0) * Time.deltaTime;

        //カメラを回転させる
        //横回転
        if (LROpposite)
        {
            transform.RotateAround(target.transform.position, Vector3.down, angle.x);
        }
        else
        {
            transform.RotateAround(target.transform.position, Vector3.up, angle.x);
        }

        //縦回転
        if (UDOpposite)
        {
            if ((transform.localEulerAngles.x <= rotateCeiling || transform.localEulerAngles.x >= 360 + rotateLower)
                || (Input.GetAxis("VerticalR") >= inputLimit && transform.localEulerAngles.x < 360 + rotateLower && 180 <= transform.localEulerAngles.x)
                || (Input.GetAxis("VerticalR") <= -inputLimit && transform.localEulerAngles.x < 180 && rotateCeiling < transform.localEulerAngles.x))
            {
                transform.RotateAround(target.transform.position, transform.right, angle.y);
            }
        }
        else
        {
            if ((transform.localEulerAngles.x <= rotateCeiling || transform.localEulerAngles.x >= 360 + rotateLower)
                || (Input.GetAxis("VerticalR") <= -inputLimit && transform.localEulerAngles.x < 360 + rotateLower && 180 <= transform.localEulerAngles.x)
                || (Input.GetAxis("VerticalR") >= inputLimit && transform.localEulerAngles.x < 180 && rotateCeiling < transform.localEulerAngles.x))
            {
                transform.RotateAround(target.transform.position, -transform.right, angle.y);
            }
        }

        //beforePosを更新
        beforePos = target.transform.position;

        //カメラ位置リセット中
        if (reset && nowTime <= resetTime)
        {
            nowTime += Time.deltaTime;
            transform.RotateAround(target.transform.position, Vector3.down, ResetCalc(0));
            transform.RotateAround(target.transform.position, transform.right, ResetCalc(1));
        }
        else
        {
            reset = false;
        }

        //カメラ位置リセット開始
        if (Input.GetButtonDown("JoyR") && !reset)
        {
            resetTime = camReset;
            resetAngle = initRotate.x;
            ResetStart();
        }
    }

    private void ResetStart()
    {
        camnum[0] = transform.localEulerAngles.y;
        if (camnum[0] >= 180)
        {
            camnum[0] -= 360;
        }
        float pnum = target.transform.localEulerAngles.y;
        if (pnum >= 180)
        {
            pnum -= 360;
        }
        camnum[0] -= pnum;
        if (camnum[0] >= 180)
        {
            camnum[0] -= 360;
        }
        else if (camnum[0] < -180)
        {
            camnum[0] += 360;
        }
        camnum[1] = -transform.localEulerAngles.x + resetAngle;
        if (camnum[1] < 0)
        {
            camnum[1] += 360;
        }
        if (camnum[1] >= 180)
        {
            camnum[1] -= 360;
        }
        nowTime = 0;
        before[0] = 0;
        before[1] = 0;
        reset = true;
    }

    private float ResetCalc(int sel)
    {
        float Percentage = nowTime / resetTime;
        float[] num = new float[2];
        float[] pos = new float[2];

        num[sel] = camnum[sel] * Percentage;
        pos[sel] = num[sel] - before[sel];
        before[sel] = num[sel];
        return pos[sel];
    }
}

以上です。
リセット中にもカメラを動かせるようになっているので、ゲームに合わせて制限する等してみてください。
次回はマウスでも動かせるようにしようと思います。