#27 1인칭 컨트롤러

국기웅·2024년 5월 24일

오늘 배운 1인칭 플레이어 제작이 은근 알아야 할 부분이 있어 TIL을 작성하며 적어보았다.
코드는 아래..

실제 구현 모습은 캐릭터가 걸어다니고, 마우스에 따라 화면이 회전하는 모습이다.

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    [Header("Movement")]
    public float moveSpeed;//접근제한자를 안쓰면 private 필요할때 public으로 바꿔주기?
    private Vector2 curMovementInput;

    [Header("Look")]
    public Transform cameraContainer;
    public float minxLook;
    public float maxXLook;
    private float camCurXRot;
    public float lookSensitivity;
    private Vector2 mouseDelta;

    private Rigidbody _rigidbody;

    private void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
    }

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        Move();
    }

    private void LateUpdate()
    {
        CameraLook();
    }

    void Move()
    {
        Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
        dir *= moveSpeed;
        dir.y = _rigidbody.velocity.y;

        _rigidbody.velocity = dir;
    }

    void CameraLook()
    {
        camCurXRot += mouseDelta.y * lookSensitivity; 
        camCurXRot = Mathf.Clamp(camCurXRot , minxLook, maxXLook);
        cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);

        transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        if(context.phase == InputActionPhase.Performed) 
        {
            curMovementInput = context.ReadValue<Vector2>();
        }
        else if(context.phase == InputActionPhase.Canceled)
        {
            curMovementInput = Vector2.zero;
        }
    }

    public void OnLook(InputAction.CallbackContext context)
    {
        mouseDelta = context.ReadValue<Vector2>();
    }
}

OnMove메서드에서는 InputAction.CallbackContext를 통해 입력받은 내용을 전달받는다
phase를 이용하면 그 동작의 상태를 알려주는데, 총 네가지가 있다.
1. performed - 동작이 계속되는 동안
2. started - 동작이 시작될 때
3. canceled - 동작이 끝날때

CallbackContext.ReadValue< Vector2 >를 통해 입력값을 받아올 수 있다.
값이 사라질 때는 움직임 벡터를 0으로 만든다

마우스를 통한 시점전환도 비슷하지만 조금 다르다
마우스좌표를 vector2로 받아오면, 이걸 CameraLook()메서드로 값을 변환한다.
camCurXRot += mouseDelta.y * lookSensitivity;
마우스 좌우 움직임은 mouseDelta 의 x값이 변화한다.
화면 전환을 좌우로 돌리려면 y축을 기준으로 회전시켜줘야한다.
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);
camCurXRot은 실제 회전 방향의 음의 값으로 가야 익숙한 회전 방향이 나오기 때문이다.

마우스y는 카메라 x로
마우스 x는 카메라 y로 들어가야 한다.
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);

...많이 어려웠지만 실제로 값을 변경해보고 시행착오를 거쳐가면서 해보는게 좋은 것 같다. 볼때는 이해가 안가는것 투성이지만 한번 시행해보면 바로 이해가 된다.

profile
게임개발호소인

2개의 댓글

comment-user-thumbnail
2024년 5월 24일

좋은 글 감사합니다

답글 달기
comment-user-thumbnail
2024년 5월 27일

잘 정리해주셨네요~

답글 달기