xxxCast(캐스트)를 이용하면 콜라이더를 감지할 수 있다.
레이캐스트 외에도 Cube, Sphere, Capsule 모양의 캐스트를 사용해보자.
Ctrl + Shift + N으로 빈 오브젝트를 만든 후, 아래의 CastTest.cs를 추가하자.
그리고 (0, 0, 0)에서 Y값이 양수가 되도록 배치하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CastTest : MonoBehaviour
{
public GameObject capsuleMesh;
void OnDrawGizmos()
{
RaycastHit hit;
float rayLength = 20.0f;
Mesh cm = capsuleMesh.GetComponent<MeshFilter>().sharedMesh;
Vector3 pos = this.transform.position;
Vector3 rayPos = pos + new Vector3(3, 0, 3);
Vector3 cubePos = pos + new Vector3(3, 0, -3);
Vector3 spherePos = pos + new Vector3(-3, 0, 3);
Vector3 capsulePos = pos + new Vector3(-3, 0, -3);
if(Physics.Raycast(rayPos, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(rayPos, Vector3.down * hit.distance);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
Vector3 boxSize = new Vector3(1, 1, 1);
if(Physics.BoxCast(cubePos, boxSize / 2, Vector3.down, out hit, Quaternion.identity, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(cubePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireCube(cubePos + Vector3.down * hit.distance, boxSize);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
float radius = 0.5f;
if (Physics.SphereCast(spherePos, radius, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(spherePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(spherePos + Vector3.down * hit.distance, radius);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
Vector3 p1 = capsulePos + Vector3.left / 2;
Vector3 p2 = capsulePos + Vector3.right / 2;
float capRadius = 0.5f;
if (Physics.CapsuleCast(p1, p2, capRadius, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(capsulePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireMesh(cm, 0, capsulePos + Vector3.down * hit.distance, Quaternion.Euler(new Vector3(90, 0, 0)));
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
}
}
위 코드는 네 개의 Cast를 아래로 쏘는 코드다.
Plane을 적절히 배치하면 아래의 결과를 얻을 수 있다.
(0, 0, 0) 중심으로 x = 3, -3 / z = 3, -3으로 좌표를 나누었다.
RayCast / BoxCast
SphereCast / CapsuleCast
RayCast
모든 캐스트는 사용하는 방법이 여러가지가 있다.
레이캐스트는 아래와 같은 메서드를 제공한다.
여기에서는 현재 빈 오브젝트의 위치에서 (x = 3, z = 3) 떨어진 곳에서 down 방향으로 rayLength만큼 레이저를 쏜다.
if(Physics.Raycast(rayPos, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(rayPos, Vector3.down * hit.distance);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
RayCast로 인해 hit이 감지되는 경우 distance(Color.red)와 point(Color.blue)를 알 수 있다.
rayLength = 20.0f 보다 평면이 아래에 있는 경우는 감지할 수 없으므로 Draw로 아무것도 그리지 않는다.
길이를 제한하고 싶지 않다면 Mathf.Infinity를 사용하면 된다.
BoxCast
박스 형태의 RayCast다.
박스캐스트는 큐브의 사이즈가 필요하고, 큐브가 얼만큼 회전했는지도 알려줘야 한다.
물론 레이캐스트처럼 다른 방식으로 사용할 수 있는 메서드가 많다.
Vector3 boxSize = new Vector3(1, 1, 1);
if(Physics.BoxCast(cubePos, boxSize / 2, Vector3.down, out hit, Quaternion.identity, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(cubePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireCube(cubePos + Vector3.down * hit.distance, boxSize);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
BoxCast에 boxSize / 2가 들어가는 것에 주의해야 한다.
내부적으로 절반의 사이즈를 줘야 정상 크기로 사용하게 만든 것으로 보인다.
박스캐스트와 레이캐스트의 큰 차이점은 hit.point가 일정하지 않다는 것이다.
레이캐스트는 점으로 검출하지만, 박스캐스트는 박스채로 검출하기 때문에 파란색 점(hit.point)이 불안정하다.
하지만 박스 범위 내에 있다면 중심 점을 벗어나도 여전히 검출된다.
박스캐스트는 그리드(Grid) 기반으로 장애물을 검출할 때 유용하다.
레이캐스트로만으로는 그리드 한 칸에 모든 장애물을 검출하기 까다롭다.
SphereCast
박스캐스트와 비슷하지만 구 모양의 레이캐스트다.
따라서 큐브의 사이즈 대신 반지름(radius)이 필요하다.
float radius = 0.5f;
if (Physics.SphereCast(spherePos, radius, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(spherePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(spherePos + Vector3.down * hit.distance, radius);
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
구와 평면은 항상 접점을 이루기 때문에 hit.point가 큐브보다 잘 검출될 수 있다.
CapsuleCast
캡슐캐스트는 사용방법이 까다롭다.
먼저 DrawCapsule이나 DrawWireCapsule을 제공하지 않는다.
따라서 캡슐 메시를 public으로 받은 후 메시를 얻어서 Gizmos.DrawWireMesh로 그림을 그린다.
메시는 아래의 코드로 가져올 수 있다.
Mesh cm = capsuleMesh.GetComponent<MeshFilter>().sharedMesh;
그리고 아래와 같이 캡슐을 그린다.
public GameObject capsuleMesh;
void OnDrawGizmos()
{
RaycastHit hit;
float rayLength = 20.0f;
Mesh cm = capsuleMesh.GetComponent<MeshFilter>().sharedMesh;
...
Vector3 p1 = capsulePos + Vector3.left / 2;
Vector3 p2 = capsulePos + Vector3.right / 2;
float capRadius = 0.5f;
if (Physics.CapsuleCast(p1, p2, capRadius, Vector3.down, out hit, rayLength))
{
Gizmos.color = Color.red;
Gizmos.DrawRay(capsulePos, Vector3.down * hit.distance);
Gizmos.color = Color.green;
Gizmos.DrawWireMesh(cm, 0, capsulePos + Vector3.down * hit.distance, Quaternion.Euler(new Vector3(90, 0, 0)));
Gizmos.color = Color.blue;
Gizmos.DrawSphere(hit.point, 0.1f);
}
}
먼저 캡슐을 그리는 방법에 대해 알아보자.
캡슐은 아래와 같이 Cube(의 높이)와 Sphere 두 개로 이루어져 있다.
따라서 캡슐을 만들기 위한 point1, point2, radius의 의미를 쉽게 이해할 수 있다.
첫 번째 구의 중심, 두 번째 구의 중심, 그리고 구의 반지름이 된다.
즉 여기에서는 Vector.left / right로 캡슐을 만들었으므로 캡슐을 눕힌 채로 캡슐캐스트를 쏘게 된다.
DrawWireMesh에서 Quaternion.Euler(new Vector3(90, 0, 0))을 설정한 이유이기도 하다.
Vector3 p1 = capsulePos + Vector3.left / 2;
Vector3 p2 = capsulePos + Vector3.right / 2;
float capRadius = 0.5f;
캡슐의 경우 평면과 직선이 만나므로 옆으로 이동할 때, hit.point가 불안한 것을 알 수 있다.
실제로 각 캐스트들이 어떻게 검출되는지 직접 검토해보자.
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
'개발 > Unity' 카테고리의 다른 글
유니티 - Missing Component 찾기 (0) | 2022.07.28 |
---|---|
유니티 Attribute - AddComponentMenu로 Script 메뉴 관리하기 (0) | 2022.07.27 |
유니티 에디터 - OnValidate와 Reset으로 디버깅하기 (0) | 2022.07.25 |
유니티 에디터 - 속성으로 인스펙터 정리하기 (Customizing the Inspector with Attributes) (0) | 2022.07.25 |
유니티 - 스크립트 모양을 톱니 바퀴 아이콘으로 바꾸기 (Replace Script Icon) (0) | 2022.07.22 |
댓글