본문 바로가기
개발/Unity

유니티 - 다양한 캐스트 사용하기 (RayCast, BoxCast, SphereCast, CapsuleCast)

by 피로물든딸기 2022. 7. 25.
반응형

Unity 전체 링크

 

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:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글