유니티에서 터널링 현상을 방지하는 기술

2025. 1. 4. 23:17·유니티

터널링 현상(Tunneling)은 빠르게 움직이는 객체가 충돌을 감지하지 못하고 다른 객체를 통과하는 문제를 의미합니다.

 

FixedUpdate 이벤트 메서드 활용

Update() 대신 일정한 시간 간격으로 호출되는 FixedUpdate()를 사용하여 물리 연산의 정확도를 높일 수 있습니다.

public class MovementController : MonoBehaviour
{
    public float moveSpeed = 5f;
    private Vector3 direction;

    void FixedUpdate()
    {
        // 일정한 시간 간격으로 이동 처리
        transform.position += direction * moveSpeed * Time.fixedDeltaTime;
    }
}

 

Time.fixedDeltaTime 조절

물리 연산의 정확도를 높이기 위해 FixedUpdate의 호출 간격을 조절할 수 있습니다.

  • Time.fixedDeltaTime 값을 너무 작게 설정하면 전체적인 게임 성능에 영향을 줄 수 있습니다.
public class PhysicsTimeController : MonoBehaviour
{
    void Start()
    {
        // 기본값(0.02초)보다 더 작은 간격으로 설정
        Time.fixedDeltaTime = 0.01f;
    }
}

 

Rigidbody의 Collision Detection 모드 설정

Rigidbody 컴포넌트의 충돌 감지 모드를 상황에 맞게 설정합니다.

 

충돌 감지 모드의 종류

  1. Discrete (기본값)
    • 가장 기본적인 충돌 감지 방식
    • 각 물리 업데이트 단계에서 현재 위치만을 기준으로 충돌 검사
    • 성능이 좋지만, 빠른 움직임에서 터널링 현상 발생 가능
    • 일반적인 움직임의 오브젝트에 적합
  2. Continuous
    • 이동 경로를 고려한 연속적인 충돌 검사
    • 정적(Static) 콜라이더와의 충돌만 연속적으로 감지
    • Discrete보다 더 많은 CPU 리소스 사용
    • 투사체나 빠르게 움직이는 물체에 적합
  3. Continuous Dynamic
    • 가장 정확한 충돌 감지 방식
    • 동적(Dynamic) 콜라이더를 포함한 모든 충돌을 연속적으로 감지
    • 가장 많은 CPU 리소스 사용
    • 매우 빠른 속도로 움직이는 물체들 간의 상호작용에 적합
public class CollisionController : MonoBehaviour
{
    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        
        // 상황에 따른 충돌 감지 모드 설정
        switch(objectType)
        {
            case ObjectType.Normal:
                rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
                break;
            case ObjectType.FastMoving:
                rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
                break;
            case ObjectType.VeryFastMoving:
                rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
                break;
        }
    }
}

 

Rigidbody Interpolation 설정

물리 연산과 렌더링 사이의 불일치를 보완하기 위한 보간 설정입니다.

 

Interpolation 모드의 종류

  1. None (기본값)
    • 보간을 사용하지 않음
    • 물리 업데이트 시점의 위치를 그대로 사용
    • CPU 부하가 가장 적음
    • 움직임이 다소 부자연스러울 수 있음
  2. Interpolate
    • 이전 프레임과 현재 프레임의 위치를 보간
    • 부드러운 움직임 제공
    • 약간의 지연이 발생할 수 있음
    • 대부분의 일반적인 상황에 적합
  3. Extrapolate
    • 현재와 이전 프레임을 기반으로 다음 위치를 예측
    • 지연이 적고 반응성이 좋음
    • 예측이 빗나가면 움직임이 불안정해질 수 있음
    • 빠른 반응성이 필요한 물체에 적합
public class InterpolationController : MonoBehaviour
{
    public enum MovementType
    {
        Regular,
        Smooth,
        Responsive
    }

    public MovementType movementType = MovementType.Regular;

    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        
        // 움직임 타입에 따른 보간 설정
        switch(movementType)
        {
            case MovementType.Regular:
                rb.interpolation = RigidbodyInterpolation.None;
                break;
            case MovementType.Smooth:
                rb.interpolation = RigidbodyInterpolation.Interpolate;
                break;
            case MovementType.Responsive:
                rb.interpolation = RigidbodyInterpolation.Extrapolate;
                break;
        }
    }
}

 

Rigidbody의 조합 예시

  1. 일반 오브젝트
    • rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
    • rb.interpolation = RigidbodyInterpolation.None;
  2. 플레이어 캐릭터
    • rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
    • rb.interpolation = RigidbodyInterpolation.Interpolate;
  3. 고속 투사체
    • rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
    • rb.interpolation = RigidbodyInterpolation.Extrapolate;

 

Raycast를 활용한 충돌 감지

이동 경로상의 충돌을 미리 감지하여 터널링을 방지합니다.

  • Raycast를 사용할 때는 레이어 마스크를 적절히 설정하여 불필요한 충돌 검사를 피하는 것이 좋습니다.
public class RaycastController : MonoBehaviour 
{
    public float moveSpeed = 5f;
    public LayerMask collisionLayer;
    private Vector3 direction;

    void Update() 
    {
        Vector3 nextPosition = transform.position + direction * moveSpeed * Time.deltaTime;
        
        // 이동 전에 Raycast로 충돌 체크
        RaycastHit hit;
        if (Physics.Raycast(transform.position, direction, out hit, 
            moveSpeed * Time.deltaTime, collisionLayer)) 
        {
            // 충돌이 예상되는 경우 처리
            direction = Vector3.zero;
        } 
        else 
        {
            // 안전한 경우 이동
            transform.position = nextPosition;
        }
    }
}

 

 

'유니티' 카테고리의 다른 글
  • 유니티에서 메모리 누수를 방지
  • 유니티에서 리소스 관리 도구
  • InputField 간 Tab 탐색 구현
  • 슬립모드 방지
뇌장하드 주인장
뇌장하드 주인장
  • 뇌장하드 주인장
    뇌장하드
    뇌장하드 주인장
    • 분류 전체보기 (86)
      • C++ (9)
      • C# (15)
      • CS (9)
      • 유니티 (38)
      • 유니팁 (7)
      • 유니티 패턴 (8)
      • - (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
뇌장하드 주인장
유니티에서 터널링 현상을 방지하는 기술
상단으로

티스토리툴바