개발/Unity

유니티 - 1인칭 시점 조작 first person view controller

피로물든딸기 2022. 3. 6. 14:02
반응형

Unity 전체 링크

 

참고

 시네머신 튜토리얼 링크 (시네머신을 이용하여 카메라 간편하게 조작하기)

 

카메라 회전을 하였으므로, 이제 카메라를 Player 아래로 둔다.

 

여기서 front는 player가 제대로 회전하는지 확인하기 위해 만들어둔 좌표다.

빈 오브젝트를 설정하여 플레이어보다 약간 앞 (Z=10)에 맞춰두자.

 

front를 스크립트에 설정해두고 DrawLine을 설정한다.

Debug.DrawLine(transform.position, objectFrontVector.position, Color.red);

 

Player 앞에 line이 생겨서 방향을 구분할 수 있게 되었다.


Camera에 회전을 하는 스크립트는 해제한다.

카메라는 Player의 자식이므로 Player가 회전하면 같이 회전하기 때문이다.

 

Player의 스크립트에 Translate 코드와 클릭시 회전 코드를 추가한다.

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

public class PlayerCtrl : MonoBehaviour
{
    public Transform objectFrontVector;

    private float h = 0.0f;
    private float v = 0.0f;
    public float moveSpeed = 10.0f;

    private float xRotate, yRotate, xRotateMove, yRotateMove;
    public float rotateSpeed = 500.0f;

    void Update()
    {
        /* debug */
        Debug.DrawLine(transform.position, objectFrontVector.position, Color.red);

        /* player 이동 */
        h = Input.GetAxis("Horizontal");
        v = Input.GetAxis("Vertical");

        Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);

        transform.Translate(moveDir.normalized * Time.deltaTime * moveSpeed, Space.Self);

        /* 회전 */
        if (Input.GetMouseButton(0)) // 클릭한 경우
        {
            xRotateMove = -Input.GetAxis("Mouse Y") * Time.deltaTime * rotateSpeed;
            yRotateMove = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;

            yRotate = transform.eulerAngles.y + yRotateMove;
            //xRotate = transform.eulerAngles.x + xRotateMove; 
            xRotate = xRotate + xRotateMove;

            xRotate = Mathf.Clamp(xRotate, -90, 90); // 위, 아래 고정

            transform.eulerAngles = new Vector3(xRotate, yRotate, 0);
        }
    }
}

 

WASD로 이동하고, 마우스로 회전을 해서 이동 방향을 바꿀 수 있지만

오브젝트가 y축으로 회전하기 때문에 아래와 같은 버그가 생긴다.


카메라와 Player는 따로 구분하고, Player Script에서 Camera가 Player를 따라다니도록 한다.

LateUpdate는 Scene의 모든 Update가 완료된 후 호출된다.

카메라의 움직임은 Player의 움직임이 완료된 후 호출되어야 버벅이지 않게된다.

    private void LateUpdate()
    {
        Camera.main.transform.position = this.transform.position;
    }

 

즉, 카메라는 눈으로서의 역할로만 방향전환을 하고, Player 스크립트에서 카메라가 독립적으로 Player를 따라다닌다.

Camera의 Script도 다시 활성화하면 된다.

 

Player의 움직임에서 xRotate는 불필요하므로 삭제한다.

        /* 회전 */
        if (Input.GetMouseButton(0)) // 클릭한 경우
        {
            yRotateMove = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;
            yRotate = transform.eulerAngles.y + yRotateMove;
          
            transform.eulerAngles = new Vector3(transform.eulerAngles.x, yRotate, 0);
        }

 

최종 코드는 아래와 같다.

 

player

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

public class PlayerCtrl : MonoBehaviour
{
    public Transform objectFrontVector;

    private float h = 0.0f;
    private float v = 0.0f;
    public float moveSpeed = 10.0f;

    private float yRotate, yRotateMove;
    public float rotateSpeed = 500.0f;

    void Update()
    {
        /* debug */
        Debug.DrawLine(transform.position, objectFrontVector.position, Color.red);

        /* player 이동 */
        h = Input.GetAxis("Horizontal");
        v = Input.GetAxis("Vertical");

        Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);

        transform.Translate(moveDir.normalized * Time.deltaTime * moveSpeed, Space.Self);

        /* 회전 */
        if (Input.GetMouseButton(0)) // 클릭한 경우
        {
            yRotateMove = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;

            yRotate = transform.eulerAngles.y + yRotateMove;
          
            transform.eulerAngles = new Vector3(transform.eulerAngles.x, yRotate, 0);
        }
    }

    private void LateUpdate()
    {
        Camera.main.transform.position = this.transform.position;
    }
}

 

camera

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

public class FirstPersonView : MonoBehaviour
{
    private float xRotate, yRotate, xRotateMove, yRotateMove;
    public float rotateSpeed = 500.0f;
    
    void Update()
    {
        if (Input.GetMouseButton(0)) // 클릭한 경우
        {
            xRotateMove = -Input.GetAxis("Mouse Y") * Time.deltaTime * rotateSpeed;
            yRotateMove = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;

            yRotate = transform.eulerAngles.y + yRotateMove;
            //xRotate = transform.eulerAngles.x + xRotateMove; 

            xRotate = xRotate + xRotateMove;

            xRotate = Mathf.Clamp(xRotate, -90, 90); // 위, 아래 고정

            transform.eulerAngles = new Vector3(xRotate, yRotate, 0);
        }
    }
}

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형