在做子弹穿透功能时对部分源码的一点分析。
在UProjectileMovementComponent::TickComponent()中,当遇到阻挡时候,也就是Hit.bBlockingHit = true的情形,会调用UProjectileMovementComponent::HandleBlockingHit()方法,然后根据其返回值EHandleBlockingHitResult进行相依的处理
if( !Hit.bBlockingHit )
{
//处理没有阻挡的逻辑
}
else
{
.......................
// Handle blocking hit
.....................
const EHandleBlockingHitResult HandleBlockingResult = HandleBlockingHit(Hit, TimeTick, MoveDelta, SubTickTimeRemaining);
if (HandleBlockingResult == EHandleBlockingHitResult::Abort || HasStoppedSimulation())
{
break;
}
else if (HandleBlockingResult == EHandleBlockingHitResult::Deflect)
{
NumBounces++;
HandleDeflection(Hit, OldVelocity, NumBounces, SubTickTimeRemaining);
PreviousHitTime = Hit.Time;
PreviousHitNormal = ConstrainNormalToPlane(Hit.Normal);
}
else if (HandleBlockingResult == EHandleBlockingHitResult::AdvanceNextSubstep)
{
// Reset deflection logic to ignore this hit
PreviousHitTime = 1.f;
}
else
{
// Unhandled EHandleBlockingHitResult
checkNoEntry();
}
.............................
}
EHandleBlockingHitResult指在HandleBlockingHit()被调用后模拟应该如何进行
// Enum indicating how simulation should proceed after HandleBlockingHit() is called.
enum class EHandleBlockingHitResult
{
Deflect, /** Assume velocity has been deflected, and trigger HandleDeflection(). This is the default return value of HandleBlockingHit(). */
AdvanceNextSubstep, /** Advance to the next simulation update. Typically used when additional slide/multi-bounce logic can be ignored,
such as when an object that blocked the projectile is destroyed and movement should continue. */
Abort, /** Abort all further simulation. Typically used when components have been invalidated or simulation should stop. */
};
- Deflect: 假设速度已经偏转,并触发HandleDeflection()。HandleBlockingHit()的默认返回值。
- AdvanceNextSubstep: 提前到下一个仿真更新。通常用于附加滑动/多次弹跳逻辑可以忽略的情况,例如当阻挡弹丸的物体被摧毁而运动应该继续时。因此实现弹丸穿透可以重写HandleBlockingHit方法并返回该值。
- Abort: 中止所有进一步的模拟。通常在组件失效或应停止模拟时使用。