[Skill] 1인칭 카메라



1인칭 카메라 시점을 구현해 볼 것이다.

우선 카메라 오브젝트가 플레이어를 따라다니도록 플레이어의 자식오브젝트로 넣어준다. 그리고 카메라 오브젝트의 트랜스폼을 리셋해주고 높이만 플레이어의 머리쪽에 위치할 수 있도록 조금 올려준다. 그럼 다음과 같은 그림이 된다.

image

카메라 오브젝트의 움직임은 플레이어 오브젝트의 자식 오브젝트로 넣어서 해결하였고 카메라의 회전에 대한 기능을 추가하기 위해 CameraController스크립트를 작성해보자.

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

public class CameraController : MonoBehaviour
{
    private float rotateSpeedX = 3;
    private float rotateSpeedY = 5;
    private float limitMinX = -80;
    private float limitMaxX = 50;
    private float eulerAngleX;
    private float eulerAngleY;

    public void RotateTo(float mouseX, float mouseY)
    {
        //마우스를 좌/우로 움직이는 mouseX값을 y축에 대입하는 이유는
        //마우스를 좌/우로 움직일 때 카메라도 좌/우로 보려면 카메라 오브젝트의
        //y축이 회전되어야 하기 때문이다.
        eulerAngleY += mouseX * rotateSpeedX;

        //같은 개념으로 카메라가 위/아래를 보려면 카메라 오브젝트의 x축이 회전되어야 한다.
        //뺄셈을 하는 이유는 카메라가 아래를 보는건 양수인데,마우스의 움직임은 아래로 내려가면 음수이기 때문
        eulerAngleX -= mouseY * rotateSpeedY;

        //x축 회전 값의 경우 아래, 위를 볼 수 있는 제한 각도가 설정되어 있다.
        eulerAngleX = ClampAngle(eulerAngleX, limitMinX, limitMaxX);

        //실제 오브젝트의 쿼터니온 회전에 적용
        transform.rotation = Quaternion.Euler(eulerAngleX, eulerAngleY, 0);
    }

    private float ClampAngle(float angle, float min,float max)
    {
        if (angle < -360) angle += 360;
        if (angle > 360) angle -= 360;

        //Mathf.Clamp()를 이요해 angle이 min<= angle<=max를 유지하도록 설정
        return Mathf.Clamp(angle, min, max);
    }
}

카메라의 회전을 담당하는 스크립트는 완성 되었고 이제 PlayerController에서 마우스의 움직임을 받아서 CameraController에 넘겨주면 된다. 다음과 같이 말이다.

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

public class PlayerController : MonoBehaviour
{
    private Movement3D movement3D;
    [SerializeField]
    private CameraController cameraController;
    void Awake()
    {
        movement3D = GetComponent<Movement3D>();
    }
    void Update()
    {
        float hAxis = Input.GetAxisRaw("Horizontal");
        float vAxis = Input.GetAxisRaw("Vertical");
        Debug.Log(Input.GetAxisRaw("Horizontal"));
        movement3D.MoveTo(new Vector3(hAxis, 0, vAxis));

        if (Input.GetKeyDown(KeyCode.Space))
        {
            movement3D.JumpTo();
        }

        //왼쪽 이동 :-1 , 대기 : 0 , 오른쪽 이동 : +1
        float mouseX = Input.GetAxis("Mouse X"); //마우스 좌우 움직임

        //아래로 이동 : -1, 대기 : 0 , 위로 이동 : +1
        float mouseY = Input.GetAxis("Mouse Y");

        cameraController.RotateTo(mouseX, mouseY); 
    }
}

그리고 Movement3D에서 플레이어의 움직임 방향을 정할 때 카메라가 바라보고 있는 시점을 기준으로 움직이게 해야하므로 Movement3D 스크립트를 다음과 같이 수정한다.

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

public class Movement3D : MonoBehaviour
{
    [SerializeField]
    private float moveSpeed = 5.0f;     //이동 속도
    [SerializeField]
    private float jumpForce = 3.0f;       //점프하는 힘
    private float gravity = -9.81f;         //중력 계수
    private Vector3 moveDir;               //이동 방향

    [SerializeField]
    private Transform cameraTransform;

    private CharacterController characterController;
    void Awake()
    {
        characterController = GetComponent<CharacterController>();
    }
    void Update()
    {
        //characterController.isGrounded 
        //발 위치의 충돌을 체크해 충돌이 되면 true,충돌이 되지 않으면 false값을 나타내는 변수.
        if (characterController.isGrounded == false)
        {
            moveDir.y += gravity * Time.deltaTime;
        }
        characterController.Move(moveDir * moveSpeed * Time.deltaTime);
    }

    //PlayerController에서 호출하기 위해 public 설정
    public void MoveTo(Vector3 dir)
    {
        //앞, 뒤, 좌, 우 움직임은 매개변수로 넘어온 값을 사용하고
        //아래방향은 Update에서 계속 계산 되는 moveDir.y를 사용한다.
        //카메라가 보고있는 방향을 기준으로 움직일 수 있도록 movedis를 생성한다.
        Vector3 movedis=cameraTransform.rotation * dir;
        moveDir = new Vector3(movedis.x, moveDir.y, movedis.z);
    }

    //PlayerController에서 호출하기 위해 public 설정
    public void JumpTo()
    {
        if (characterController.isGrounded == true)//플레이어가 바닥에 붙어있으면
        {
            moveDir.y = jumpForce;
        }
    }
}

카메라의 Transform을 받아와 카메라의 회전값에 플레이어의 이동방향을 곱해준다.




© 2022. by KSC

Powered by sora