📘Unreal Engine/📝Unreal Engine

[Unreal Engine] 충돌 판정 / 트레이싱 (Tracing)

주으기 2024. 8. 9. 14:07
728x90
반응형

트레이싱 함수를 사용하여 물체의 충돌을 감지하는 방법에 대한 설명 글이다.

 

트레이싱 함수

물체의 충돌을 감지하는 방법 중 가장 대표적으로 트레이싱 함수가 있다.

트레이싱 함수의 이름은 세 가지 카테고리의 이름을 붙여 결정된다.

 

1. 충돌 방법

  • LineTrace : 지정한 방향으로 선을 투사하여, 이 선이 물체와 충돌하는지 감지한다.
  • Sweep : 선이 아닌 도형(구체, 박스 등)을 투사하여 충돌을 감지한다.
  • Overlap : 지정한 영역(구체, 박스 등) 내에 충돌하는 물체가 있는지 감지한다.

 

 

2. 충돌 대상

  • Test : 충돌 여부를 단순히 테스트하여 반환한다.
  • Single : 충돌이 감지된 단일 물체에 대한 정보를 반환한다.
  • Multi : 충돌이 감지된 모든 물체의 정보를 배열로 반환한다.

LineTrace와 Sweep의 경우 Single이 붙는다.

Overlap의 경우 AnyTest가 붙는다.

 

 

3. 충돌 설정

  • ByChannel : 물체의 트레이스 채널 정보를 사용하여 충돌 대상을 감지한다.
  • ByObjectType : 물체의 오브젝트 타입을 사용하여 충돌 대상을 감지한다.
  • ByProfile : 물체의 콜리전 프로필 정보를 사용하여 충돌 대상을 감지한다.

 

위 세 가지 이름 분류를 연결하여 함수 이름이 완성된다. {충돌 방법}{충돌 대상}{충돌 설정}

// ex.1
// 캐릭터의 시선 방향으로 작은 구체를 투사하여 구체 범위 내의 물체를 감지
// 처음 충돌하는 하나의 물체만 감지하고, 트레이스 채널 정보를 통해 분별
GetWorld()->SweepSingleByChannel()
// ex.2
// 캐릭터 주위에 가상의 구체를 생성하고, 구체 안의 들어오는 물체를 감지
// 충돌하는 모든 물체를 배열로 받고 물체의 오브젝트 타입을 통해 분별
GetWorld()->OverlapMultiByObjectType()

 

 


 

 

트레이싱 함수 사용

SweepSingleByChannel 트레이스 함수를 사용하여 충돌 감지 구현을 해보자.

캐릭터의 시선 방향으로 가상의 구체를 투사하여 트레이스 채널이 적합한 충돌 물체를 반환

 

구현 단계

  • 1. 충돌한 물체에 대한 결괏값을 저장할 FHitResult 구조체 선언
  • 2. 트레이싱의 시작점과 끝점의 위치 구하기
  • 3. 원하는 충돌 물체인지 분별할 트레이스 채널 정하기
  • 4. 충돌 영억을 지정할 가상의 도형 정하기
    FCollisionShape에서 제공하는 MakeSphere 함수를 사용하여 즉석으로 생성함
  • 5. 충돌을 무시할 쿼리 파라미터 정하기, FCollisionParams 구조체를 사용한다.
    첫 번째 인자 : 콜리전 분석에서 태그를 통해 분석할 때 식별자 정보로 사용
    두 번째 인자 : 콜리전 분석을 복잡한 형태로 계산할지 여부
    세 번째 인자 : 충돌을 무시할 물체 (보통 this를 넣음)
    일반적으로 DefaultQueryParam으로 기본값 지정 후, 제외 대상에 자신을 추가하는 방식 사용 추천

 

void AABCharacterBase::Test()
{
	// 충돌 결과를 저장할 구조체
	FHitResult HitResult;

	// 충돌 무시 대상을 지정할 쿼리 파라미터
	FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
	Params.AddIgnoredActor(this);

	const float AttackRange = 40.f;  // 공격 사거리
	const float AttackRadius = 50.f; // 공격 반경
	const float AttackDamage = 30.f; // 공격 피해량

	// 트레이싱 시작점 : 캐릭터 위치 + (전방 방향 * 캡슐 반지름)
	const FVector Start = GetActorLocation() + (GetActorForwardVector() * GetCapsuleComponent()->GetScaledCapsuleRadius());
	// 트레이싱 끝점 : 시작점 + (전방 방향 * 공격 사거리)
	const FVector End = Start + (GetActorForwardVector() * AttackRange);

	bool HitDetected = GetWorld()->SweepSingleByChannel(
		HitResult,				// 충돌 결과를 저장할 변수
		Start,					// 트레이싱 시작 위치
		End,					// 트레이싱 끝 위치
		FQuat::Identity,		// 회전 정보 (없음)
		ECC_GameTraceChannel1,	// 트레이스 채널
		FCollisionShape::MakeSphere(AttackRadius),	// 충돌 영역 (구체)
		Params);				// 쿼리 파라미터

	// 충돌 여부에 따라 디버그 구체를 그린다
	if (HitDetected)
	{
		DrawDebugSphere(GetWorld(), End, AttackRadius, 8, FColor::Green, false, 5.f);
	}
	else
	{
		DrawDebugSphere(GetWorld(), End, AttackRadius, 8, FColor::Red, false, 5.f);
	}
}

 

 

 

 

 

728x90
반응형