if (Hit.bBlockingHit)
{
// 이동을 실제로 막는 충돌이 발생함
}
true면 Blocking 충돌이 있었고, false라면 충돌이 없었거나 단순 Overlap일 수 있다.
즉 Hit.Normal 보기 전에 애초에 BlokingHit이 있었는지 부터 확인하기 위한 것
if (Hit.IsValidBlockingHit())
{
}
Bloking HIt이지만, 시작부터 이미 침투하고 있던 충돌이 아닌 경우 true가 된다.
다음과 같은 표로 bBLokingHIt과 구분 가능하다
| 상황 | bBlockingHit | IsValidBlockingHit() |
|---|---|---|
| 아무것도 안 부딪힘 | false | false |
| 이동하다 벽에 정상 충돌 | true | true |
| 시작부터 벽 안에 박혀 있음 | true | false |
| Overlap만 발생 | false | false |
if (Hit.bStartPenetrating)
{
}
이동해서 부딪힌 것이 아니라 Sweep을 시작할 때부터 이미 다른 Collision 안쪽에 들어가 있었다라는 뜻이다.
정상 충돌
□ → │
↑ 이동하다가 충돌
Start Penetrating
□│
│
처음부터 겹쳐 있음
두 상황은 똑같아 보이지만 해결 방법이 다르다.
정상 충돌은 Slide 처리할 수 있지만, 침투 상태인 bStartPenetrating == true && bBlockingHit == false에서는 먼저 밖으로 빠져나와야 한다.
SafeMoveUPdatedComponent()가 이름에 Safe가 붙은 이유 중 초기 침투를 ResolvePnetration()으로 처리하려 하기 때문에도 있다.
Hit.Time
범위는 대략 0.0 ~ 1.0
요청한 Delta 중 몇 %까지 이동하다가 충돌했는가? 라는 뜻이다.
TraceStart ~ TraceEnd까지의 충돌 시점을 정규화 한 값이다.
예를 들어
Delta = FVector(100.f, 0.f, 0.f);
Hit.Time = 0.3f;
// 100cm 이동하려고 했는데
// 약 30% 지점에서 벽에 부딪힘
// 그러면 남은 이동량은 개념적으로
const FVector RemainingDelta = Delta * (1.f - Hit.Time);
// RemainingDelta == 70%
이 남은 이동을 그대로 벽에 또 박으면 안 되니까 벽 방향 성분을 제거해서 Slide 시키는 것이다.
전체적인 흐름은
100cm 이동 시도
↓
30cm에서 벽 충돌
↓
70cm 이동이 남음
↓
남은 70cm 중 벽 안쪽 성분 제거
↓
벽과 평행한 이동만 실행
Hit Location -> Sweep을 하는 움직이는 Shape 자체가 충돌 없이 놓일 수 있는 위치(내 캐릭터 콜리전 위치)
Hit.ImpactPoint -> 실제로 표면과 접촉한 지점(실제 벽과 닿은 지점)
예시
ImpactPoint
↓
□──────●│ 벽
↑
Hit.Location = Box 중심 위치
Hit.Normal -> Sweep된 물체 쪽을 기준으로 한 충돌 Normal
Hit.ImpactNormal -> 실제로 충돌한 대상 표면의 Normal
이 둘은 평평한 벽에 정면 충도랗면 거의 똑같아 보여서 헷갈릴 수있따.
○ → │ 벽
←
Normal ≈ 왼쪽
ImpactNormal ≈ 왼쪽
차이는 모서리나 곡면에 Shape Sweep을 했을 때 잘 드러난다.
