전체 코드

🚀 1. 카메라가 플레이어를 따라다니게 만들기

플레이어가 움직일 때 카메라도 함께 따라오도록 설정하는 여러 가지 방법이 있습니다.

1️⃣ 방법 1: 카메라를 플레이어의 자식(Child)으로 만들기

📌 장점

  • 간단하게 구현할 수 있으며, 플레이어가 움직이면 카메라도 자동으로 이동.

📌 단점

  • 플레이어가 회전하면 카메라도 함께 회전하기 때문에 어지러운 현상 발생.
  • 특히 3D 게임에서는 비현실적으로 휙휙 움직여 불편함을 초래할 수 있음.

📝 사용 예시
1인칭(First-Person) 카메라를 구현할 때 사용 가능.

  • 플레이어는 RigidbodyConstraints(제약 설정) 을 통해 X, Y, Z 회전이 제한되어 있어야 함.

2️⃣ 방법 2: 별도의 스크립트를 활용하여 카메라가 자연스럽게 따라오도록 만들기

📌 방법

  • 카메라는 플레이어의 자식이 아닌 별도의 오브젝트로 두되, 항상 일정한 거리(Vector3)를 유지하며 플레이어를 바라보게 설정.
  • 플레이어가 이동할 때마다 LateUpdate()에서 카메라 위치를 업데이트.
  • LookAt() 함수를 사용하여 플레이어를 바라보도록 회전.

📌 장점

  • 플레이어가 회전하더라도 카메라는 영향을 받지 않음.
  • 자연스러운 3인칭(Third-Person) 뷰를 제공할 수 있음.

📜 2. 카메라 모드 정의 (Define.cs)

먼저, CameraMode를 정의하여 여러 카메라 모드를 관리할 수 있도록 설정합니다.

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

public class Define 
{
    public enum CameraMode
    {
        QuarterView,  // 쿼터뷰(롤, 디아블로 스타일)
    }
}

CameraMode의 역할

  • QuarterView: 상단에서 비스듬히 내려다보는 카메라 시점.
  • 추가적으로 1인칭(FPS), 3인칭(TPS) 모드도 확장 가능.

📜 3. 카메라 컨트롤러 구현 (CameraController.cs)

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

public class CameraController : MonoBehaviour
{
    [SerializeField]
    Define.CameraMode _mode = Define.CameraMode.QuarterView;  // 기본 모드를 쿼터뷰로 설정

    [SerializeField]
    Vector3 _delta = new Vector3(0, 8, -3.5f); // 플레이어와 카메라 사이의 거리

    [SerializeField]
    GameObject _player; // 따라갈 플레이어 객체

    void LateUpdate()
    {
        if (_mode == Define.CameraMode.QuarterView)
        {
            transform.position = _player.transform.position + _delta; // 플레이어 기준 거리 유지
            transform.LookAt(_player.transform); // 플레이어를 바라보도록 회전
        }
    }
}

코드 설명
1. LateUpdate()를 사용하여 플레이어 이동 후 카메라 위치 업데이트.
2. _delta 값은 카메라가 유지할 적절한 거리로 설정.

  • 예제에서는 (0, 8, -3.5), 즉 플레이어 머리 위에서 뒤쪽으로 약간 떨어진 위치.
  1. transform.LookAt(_player.transform);을 사용하여 항상 플레이어를 바라보도록 설정.

LateUpdate()를 사용하는 이유

  • Update()모든 게임 오브젝트가 동시에 실행되기 때문에, 플레이어 위치보다 카메라가 먼저 업데이트될 가능성이 있음.
  • LateUpdate()를 사용하면 플레이어 위치가 먼저 업데이트된 후, 이를 반영하여 카메라 위치가 갱신됨.

🖱 4. 클릭한 곳으로 이동 (RTS 스타일 이동)

RTS 게임(롤, 스타크래프트)처럼 바닥을 클릭하면 해당 위치로 자동 이동하는 시스템을 구현.

📜 Define.cs - 마우스 이벤트 추가

public class Define 
{
    public enum MouseEvent
    {
        Press,  // 마우스를 누르고 있는 상태
        Click,  // 마우스를 눌렀다 뗀 상태
    }
}

사용 예시

  • Press → 마우스를 누르고 있는 동안 처리할 이벤트.
  • Click → 마우스를 눌렀다가 뗐을 때 실행되는 이벤트.

📜 5. 입력 처리 (InputManager.cs)

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

public class InputManager
{
    public Action KeyAction = null;
    public Action<Define.MouseEvent> MouseAction = null;

    bool _pressed = false;

    public void OnUpdate()
    {
        if (Input.anyKey && KeyAction != null)
            KeyAction.Invoke();

        if (MouseAction != null)
        {
            if (Input.GetMouseButton(0))  // 마우스 좌클릭 중
            {
                MouseAction.Invoke(Define.MouseEvent.Press);
                _pressed = true;
            }
            else
            {
                if (_pressed)  // 마우스를 눌렀다 뗀 경우
                    MouseAction.Invoke(Define.MouseEvent.Click);
                _pressed = false;
            }
        }
    }
}

입력 처리
1. KeyAction → 키보드 입력을 처리하는 액션.
2. MouseAction → 마우스 입력을 처리하는 액션.
3. Input.GetMouseButton(0) → 마우스 클릭 감지 후, Press / Click 이벤트 구분.


📜 6. 플레이어 이동 구현 (PlayerController.cs)

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

public class PlayerController : MonoBehaviour
{
    [SerializeField]
    float _speed = 10.0f;

    bool _moveToDest = false;  
    Vector3 _destPos;

    void Start()
    {
        Managers.Input.MouseAction += OnMouseClicked;
    }

    void Update()
    {
        if (_moveToDest)
        {
            Vector3 dir = _destPos - transform.position;
            if (dir.magnitude < 0.1f)
            {
                _moveToDest = false;
            }
            else
            {
                float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude);
                transform.position += dir.normalized * moveDist;
                transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime);
            }
        }
    }

    void OnMouseClicked(Define.MouseEvent evt)
    {
        if (evt != Define.MouseEvent.Click)
            return;

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, 100.0f, LayerMask.GetMask("Ground")))
        {
            _destPos = hit.point;
            _moveToDest = true;
        }
    }
}

설명
1. 마우스를 클릭하면 Ray를 발사하여 바닥(Ground) 충돌 체크.
2. 클릭한 위치를 _destPos로 저장 후 플레이어가 이동.
3. Quaternion.Slerp()로 부드럽게 회전하여 목적지 방향을 바라봄.


profile
李家네_공부방

0개의 댓글