BoxCast, SphereCast, CapsuleCast 제대로 사용하기
지난 Physics 섹션에서는 매 프레임 콜라이더 충돌을 검출하지 않고 원하는 순간에만 콜라이더를 검출해낼 수 있는 Cast 계열의 함수들에 대해서 알아보았다. 이번 섹션에서는 그 중에서도 BoxCast, SphereCast, CapsuleCast를 제대로 사용하는 방법에 대해서 알아보자.
지난 섹션에서 설명했듯이 Cast 계열의 함수는 오브젝트에서 콜라이더 컴포넌트를 가질 필요도 없고, OnCollision이나 OnTrigger같은 이벤트를 통해 매 프레임 동작하는 낭비를 줄일 수 있다. 하지만 이러한 Cast 계열의 함수에는 작은 단점이 하나 존재한다.
게임 오브젝트가 콜라이더 컴포넌트를 가지고, 이벤트를 통해 작동하는 경우에는 Scene 뷰에서 콜라이더의 위치나 크기, 방향 등을 확인할 수 있지만, 이 Cast 계열의 함수의 경우에는 위치, 방향, 크기 등을 직관적으로 확인할 수 없다는 것이다. 즉, 이 Cast 계열 함수에 익숙하지 않은 사람이라면 이 Cast의 위치, 방향, 크기가 자신이 의도한대로 작동되고 있는지 확인하기가 쉽지가 않다는 의미이다. 당연하게도 이것은 확인하기 어려운 문제를 발생시킬 것이다.
그리고 이 Cast의 범위를 확인하기 어려운 문제는 함수의 매개변수의 이름이 불분명한 것과 함수의 매개변수 중 지정하지 않은 값의 기본값이 얼마라고 명시되어 있지 않은 점과 맞물려 전혀 예측하지 못한 형태로 작동하게 만들어 버린다.
문제
캐릭터 주변의 반지름 내의 범위에 존재하는 모든 적들을 찾아서 데미지를 입히는 스킬을 구현한다고 가정해보자. 이 스킬을 구현하기 위해서는 우선 SphereCastAll 함수를 사용해야 할 것이다. 우선 SphereCastAll 함수의 제일 간단한 형태를 보자면 다음과 같다.
RayCastHit[] Physics.SphereCastAll(Vector3 origin, float radius, Vector3 direction);
그림 1 : 파란색 화살표는 forward를 의미한다.
origin과 radius는 간단하게 이해할 수 있지만, 일반적으로 SphereCast가 위의 그림처럼 캐릭터 중심으로 구형으로 작동할 것이라고 받아들이기 쉽기 때문에 SphereCast에 익숙하지 않거나 처음 사용하는 사람의 경우에는 'Sphere가 방향이 바뀌면 뭐가 달라지지?'하는 생각에 direction에서 당황하게 될 것이다. 그리고 일반적으로 아래의 예시 코드와 같이 RayCast를 사용하듯이 direction에 character의 정면에 해당하는 transform.forward를 넣게 될 확률이 높다.
var hits = Physics.SphereCastAll(transform.position, radius, transform.forward);
이렇게 코드를 작성하면 잘 모르는 사용자는 위의 이미지처럼 캐릭터를 중심으로 구형의 범위 내에서만 캐스팅을 할 것이라고 생각하겠지만, 이것은 놀랍게도 전혀 다른 결과를 가져온다.
그림 2
첫번째 이미지처럼 동작할 것이라고 생각한 코드는 사실은 바로 위의 두번째 이미지처럼 구가 캐릭터의 전방으로 무한히 늘어선 형태로 캐스팅을 해버린다. 마치 드래곤볼의 손오공이 에너지파를 전방으로 쏘아낸 것처럼 말이다.
왜 이런 결과가 나왔는지에 대해서 알아보자면 다음의 좀 더 복잡한 매개변수를 가지는 SphereCastAll의 오버로드를 살펴보아야 한다.
RayCastHit[] Physics.SphereCastAll(Vector3 origin, float radius, Vector3 direction, float maxDistance, int layerMask);
위 코드를 살펴보면 제일 처음 보았던 매개변수에 maxDistance라는 매개변수가 추가된 것이 보인다. 이것은 원점인 origin으로부터 direction 방향으로 얼마나 되는 거리까지 캐스팅할 것인지를 의미한다. 그리고 이 값의 기본값은 Infinity, 즉 무한대이다. 그렇기 때문에 그림 2처럼 캐릭터의 정면을 향해서 무한히 확장되는 형태로 캐스팅이 되는 것이다.
이것들이 의미하는 바를 살펴보자면 BoxCast, SphereCast, CapsuleCast 등은 사실 가장 기본적인 RayCast와 똑같이 동작하며, 그 범위만 하나의 점에서 육면체, 구, 캡슐 모양으로 확장된 형태로 동작한다는 것이다.
그렇다면, Cast대신에 다시 콜라이더를 사용해야 하는가? 아니다. 몇가지 방법을 이용하면 충분히 캐릭터 주변의 반지름 내에서 적들을 찾아낼 수 있다.
1. direction을 Vector3.up으로
var hits = Physics.SphereCastAll(transform.position, radius, Vector3.up)
첫번째 방법은 매개변수 중에 direction 값을 Vector3.up으로 주는 것이다.
이렇게 하면 캐스팅이 위쪽으로 확장되면서 캐릭터의 주변에 있는 적들만 검출해낼 수 있게 된다. 다만, 이 방법을 썼을 때는 캐릭터의 위쪽에 있으면서 반지름 내의 범위에 있는 적도 검출되기 때문에, 캐릭터를 중심으로 완전히 구형 내에서만 적을 찾고자 한다면 다음의 방법을 쓰는게 좋다. 그리고 성능적인 면에서도 다음 방법이 훨씬 좋다.
2. maxDistance 값을 0으로
var hits = Physics.SphereCastAll(transform.position, radius, Vector3.up, 0f)
캐스팅의 범위를 캐릭터의 주변으로 제한하는 방법 중 가장 확실하고 좋은 방법은 maxDistance 값을 0으로 설정하는 것이다. 이렇게 하면 SphereCast나 BoxCast, CapsuleCast의 범위가 direction 방향으로 확장되지 않고 아래의 그림처럼 설정된 크기 내에서만 캐스팅이 이루어지게 된다.
이번 섹션에서 이야기한 문제는 예시를 보인 SphereCast뿐만 아니라 BoxCast, CapsuleCast에서도 똑같이 작용한다. 다만 SphereCast가 훨씬 간단하게 사용하고 예시를 보여줄 수 있기 때문에 SphereCast로만 예시를 보였다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
[투네이션]
[Patreon]
[디스코드 채널]
'Unity3D > Physics' 카테고리의 다른 글
[Unity3D] Cloth - 유니티 2019 버전에서의 Cloth 컴포넌트 문제 (0) | 2020.01.09 |
---|---|
[Unity3D] Physics - 컴포지트 콜라이더 2D(Composite Collider 2D) (2) | 2019.12.01 |
[Unity3D] 게임 오브젝트에 Collider 컴포넌트를 추가하지 않고 한번만 충돌체를 찾아내는 Physics의 Cast 계열 함수들의 사용법 (2) | 2017.09.07 |
[Unity3D] Character Joint - 캐릭터에 물리효과를 받는 본 추가하기 (0) | 2017.07.26 |
[Unity3D] Ragdoll 사용하기 - 게임에서 자연스럽게 적용하기 (0) | 2017.07.25 |