[BA] 유니티 플레이어블 캐릭터의 시선 처리(쿼터뷰 시점)

KYJ의 Tech Velog·2024년 6월 12일
0

개발 일지

목록 보기
5/5

Today I Develop

저번 [BA] 플레이어블 캐릭터의 시선 처리에 이어 포스팅해보도록 하겠습니다.

시선 처리를 작업한지 2주정도 되어 가는데요. 쉽지 않은 과정이었습니다. 저번 포스팅에 이어서 여러 가지 시도를 해보았습니다. 실패한 방법들이기 때문에 나열만 하고 넘어가도록 하겠습니다.

  1. 캐릭터의 발밑에 있는 회전 기준점을 목 부근으로 수정
    • 좌표를 기준으로 회전하는 지점을 찾기 때문에 결과가 다를 게 없음
  2. 마우스 포인터부터 쏜 Ray와 캐릭터 정면 방향으로 쏜 Ray의 교차점을 바라보도록 시도
    • 마우스 포인터부터 쏜 Ray는 마우스를 계속 따라다니는데 캐릭터 정면 방향으로 쏘는 Ray는 캐릭터가 마우스 포인터를 따라 회전한다는 전제 하에 움직이기 때문에 불가능
  3. 캐릭터의 목 부근에 보이지 않는 넓은 콜라이더를 배치하고 마우스 포인터부터 쏜 Ray가 해당 콜라이더와 충돌되는 지점을 바라보도록 시도
  4. 이외에도 다양한 자잘한 시도 실패…

Plane을 활용한 해결방안

수많은 시도 끝에 UnityEngine에 내장된 Plane 구조체를 활용해서 해결할 수 있었습니다. Plane 구조체와 관련된 내용은 따로 TIL로 기록할 예정입니다.

일단 몇 가지 조건은 있습니다. 앞선 포스팅처럼 플레이어의 머리 위치를 기준으로 회전하게 하고 싶다면 나열했던 실패 방법 중의 1번 방법은 적용이 되어야 합니다.

그리고 이 방법은 결국 실패 방법 중의 3번 방법과 원리는 비슷합니다. 목 부근에 Plane 구조체를 생성하고 마우스 포인터로부터 쏜 Ray가 Plane 구조체와 충돌되는 지점을 바라보도록 하는 것입니다.

다음은 충돌되는 지점을 구하는 코드입니다.

// 마우스 포인터로부터 Ray 생성
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue()); 

// 플레이어의 목 부근(0, 1.5, 0)에 Plane 구조체 생성
Plane plane = new Plane(Vector3.up, new Vector3(0, 1.5f, 0));

// 충돌된 곳까지의 거리
float rayLength;

if (plane.Raycast(ray, out rayLength))
{
	// 충돌된 곳의 위치 반환
    Vector3 point = ray.GetPoint(rayLength);
}

충돌되는 지점을 바라보게 하는 방법은 여러가지가 있습니다.

transform.LookAt()

transform.LookAt(point);

가장 간단한 방법으로 볼 수 있죠. 다만 이 방법을 활용할 시 마우스 포인터가 캐릭터의 가까워지면 캐릭터가 의도되지 않은 회전을 보여줍니다.

마우스 포인터가 가까울 때의 예외 처리를 따로 해주어야 한다는 얘기죠.

Quaternion

// 플레이어의 위치와 바라봐야할 곳 사이의 방향 벡터
Vector3 look = point - transform.position;

transform.rotation = Quaternion.LookRotation(look);

간단한 방법이 있는데도 불구하고 Quaternion을 사용한 이유는 부드러운 움직임을 구현하기 위해서입니다.

Quaternion.Slerp를 활용하면 캐릭터가 마우스를 따라 휙휙 돌아가는 것보다는 부드럽게 따라오며 조금 더 자연스럽게 보이는 효과를 낼 수 있습니다.

Vector3 look = point - transform.position;
float t = 0.2f;

transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(look), t);

t의 값이 0에 가까울수록 시작점에 가까운 상태로 보간하고 1에 가까울수록 도착점에 가까운 상태로 보간합니다.

Slerp가 삼각함수를 계산하는 것이기 때문에 성능에 문제를 야기하지 않을까싶어서 Profiler로 비교해보았는데 딱히 문제는 없어보였습니다.

이 사진을 보시면 플레이어와 마우스 포인터 사이에 선이 하나 보이실 겁니다. 보는 지점을 Line Renderer 활용해서 시각화한 사진입니다.

어제 밤에 이 기능을 구현한 뒤에는 정말 만세를 불렀습니다...며칠동안 직접 코딩한 시간보다 키보드 앞에 앉아서 머리 싸멘 시간이 더 많았던 것 같은데 겨우 성공할 수 있었죠.

정말 이런저런 자료를 찾아보며 하다가 우연찮게 발견한 한 블로그에서 이 Plane을 활용한 해결방안을 발견해서 해결할 수 있었습니다. 링크는 Reference에 남겨놓도록 하겠습니다.

Reference

0개의 댓글