【Unity】Virtual Cameraの視点操作をスクリプトで行う 【Cinemachine】



この記事はユニティちゃんライセンス条項の元に提供されています

ユニティちゃん1.2.1
Unity2019.3.1

やりたいこと

ゲームパッドの左アナログスティックでキャラクターを動かし、右アナログスティックでカメラの視点(映し出す方向)を操作したい(アクションゲームとかでありがちなやつ)。

大まかな流れ

追従:Virtual CameraのFollowとLookAtに対象のオブジェクトをアタッチすれば勝手に追従してくれる。
視点の操作:Virtual CameraのBiasとFollow Offsetの値をスクリプトで変化させることで実現。
※視点を操作することによってプレイヤーが意識する座標系とワールド座標系が異なるため補正をしなければならない。

Virtual Cameraの設定

1.Virtual CameraをHierarchyに追加

Window>Package ManagerからCinemachineをインポートした後、Cinemachine>Create Virtual Cameraを選択。

2.Virtual Cameraがキャラクターを追従するように設定

Follow(追いかける対象)とLookAt(注視する対象)にオブジェクトをアタッチ。

3.Bodyを設定


Input Axis Nameを空にすることでマウスで勝手に視点操作されないようにする。

4.視点の角度などを良い感じに設定

5.BiasとFollow Offset

BodyのBiasとFollow Offsetをいじるとカメラの視点がキャラクターを中心に変化していることが分かります。
[Bias]

[Follow Offset]

このBiasとFollow Offsetをスクリプトから操作します。

スクリプトからVirtual Cameraを操作して視点を回転させる

using Cinemachine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;

[RequireComponent(typeof(CharacterController))]

public class test : MonoBehaviour
{
    [SerializeField] private Animator _animator;
    private float moveSpeed = 7f;

    private CharacterController _characterController;
    [SerializeField] private CinemachineVirtualCamera _camera; //エディタでVirtual Cameraをアタッチ
    private CinemachineOrbitalTransposer _transposer;
    private Transform _transform;

    private Vector3 _moveVelocity;
    private Vector3 world_moveVelocity;
    private Vector3 _cameraRotation;

    void Start()
    {
        _characterController = GetComponent<CharacterController>();
        _transposer = _camera.GetCinemachineComponent<CinemachineOrbitalTransposer>();
        _transform = transform;

        _moveVelocity = Vector3.zero;
        world_moveVelocity = Vector3.zero;
        _cameraRotation = Vector3.zero;
    }

    void Update()
    {
        world_moveVelocity = Vector3.zero;
        _moveVelocity = Vector3.zero;

        _cameraRotation.x = Input.GetAxisRaw("Horizontal2");
        _cameraRotation.z = Input.GetAxisRaw("Vertical2");

        if (_cameraRotation.magnitude >= 0.1)
        {
            _transposer.m_Heading.m_Bias += _cameraRotation.x * 3f; //Biasを操作
            _transposer.m_FollowOffset.y -= _cameraRotation.z / 8f; //Follow Offsetを操作

        }

        _moveVelocity.x = Input.GetAxisRaw("Horizontal1") * moveSpeed;
        _moveVelocity.z = Input.GetAxisRaw("Vertical1") * moveSpeed;

        if (_moveVelocity.magnitude >= 0.01)
        {
            //座標系の補正
            world_moveVelocity = Quaternion.AngleAxis(_transposer.m_Heading.m_Bias, Vector3.up) * _moveVelocity;

            Vector3 targetPositon = _transform.position + world_moveVelocity;
            //向かせたい方向
            Quaternion targetRotation = Quaternion.LookRotation(targetPositon - _transform.position);

            _transform.rotation = Quaternion.Slerp(_transform.rotation, targetRotation, 0.2f);
        }

        _characterController.Move(world_moveVelocity * Time.deltaTime);

        _animator.SetFloat("Speed", new Vector3(_moveVelocity.x, 0, _moveVelocity.z).magnitude);

    }
}

Horizontal1とVertical1は左アナログスティック(移動)の軸で、Horizontal2とVertical2は右アナログスティック(視点)の軸。

1.BiasとFollow Offset

BiasとFollow Offsetは以下のように操作できます。

[SerializeField] private CinemachineVirtualCamera _camera;
_transposer = _camera.GetCinemachineComponent<CinemachineOrbitalTransposer>();
_transposer.m_Heading.m_Bias += _cameraRotation.x * 3f; //Biasを操作
_transposer.m_FollowOffset.y -= _cameraRotation.z / 8f; //Follow Offsetを操作

2.座標系の補正

Biasを操作して水平方向に視点を回転させると、プレイヤーが意識する座標系とワールド座標系にBias分の角度の差が生まれます。

プレイヤーが右移動を入力したとき、想定する挙動は赤色の矢印方向への移動なのに、
右上のワールド座標系のx軸(赤)方向への移動になってしまう。

移動入力ベクトルをy軸まわりにBias分だけ回転させることで解決できる。

//座標系の補正
world_moveVelocity = Quaternion.AngleAxis(_transposer.m_Heading.m_Bias, Vector3.up) * _moveVelocity;

参考リンク

Cinemachine公式リファレンス