게임을 하다 보면 WASD를 통해 이동하는 것 말고도 마우스 클릭을 통해 이동하는 게임도 종종 있다.
이번에는 Raycast를 이용해서 구현해 보았다.
간단한 원리부터 보자면, 유니티의 Camera에는 ScreenPointToRay라는 함수가 존재한다. 인자로 Input.mousePosition을 넣어준다면 게임 화면에서의 2D 좌표를 3D 공간에서 발사한 Ray의 원점(origin), 방향(direction)을 Vector3의 형태로 반환해준다. Ray 구조체를 Raycast 함수의 인자로 넣어서 RaycastHit 구조체에 정보를 저장해준다. RaycastHit 구조체에 있는 point는 발사한 Ray가 부딪힌 오브젝트의 지점을 좌표로 가지고 있다. 마지막으로 플레이어는 point 지점으로 이동을 하기만 하면 마우스 클릭으로 이동을 하는 것이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
enum PlayerState
{
Idle,
Moving,
}
[SerializeField]
float _speed = 10;
PlayerState _state = PlayerState.Idle;
Vector3 _destPos;
void Start()
{
Managers.Input.MouseAction -= OnMouseClicked;
Managers.Input.MouseAction += OnMouseClicked;
}
private void Update()
{
switch (_state)
{
case PlayerState.Idle:
UpdateIdle();
break;
case PlayerState.Moving:
UpdateMoving();
break;
}
}
void UpdateIdle()
{
}
void UpdateMoving()
{
Vector3 dir = _destPos - transform.position;
if (dir.magnitude < 0.01f)
{
_state = PlayerState.Idle;
}
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), 0.2f);
}
}
void OnMouseClicked()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.yellow, 1.0f);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100.0f))
{
_destPos = hit.point;
_state = PlayerState.Moving;
}
}
}
이번 코드에서는 State 패턴을 이용하였다. 플레이어의 상태에 따라 함수를 실행함으로써 관리가 편리해진다.
'UNITY' 카테고리의 다른 글
UNITY - Scene (1) | 2024.01.12 |
---|---|
UNITY - Animation - Animator Controller를 활용한 애니메이션 전환 (3) | 2024.01.12 |
UNITY - ResourceManager (0) | 2024.01.12 |
UNITY - UI 자동화(2) - 인벤토리 구현 (0) | 2024.01.11 |
UNITY - UI 자동화(1) - 인벤토리 구현 (0) | 2024.01.11 |