UE4的范围伤害函数为
/** Hurt locally authoritative actors within the radius. Will only hit components that block the Visibility channel.
...
* @param DamagePreventionChannel - Damage will not be applied to victim if there is something between the origin and the victim which blocks traces on this channel
...
*/
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Game|Damage", meta=(WorldContext="WorldContextObject", AutoCreateRefTerm="IgnoreActors"))
static bool ApplyRadialDamageWithFalloff(const UObject* WorldContextObject, float BaseDamage, float MinimumDamage, const FVector& Origin, float DamageInnerRadius, float DamageOuterRadius, float DamageFalloff, TSubclassOf DamageTypeClass, const TArray& IgnoreActors, AActor* DamageCauser = NULL, AController* InstigatedByController = NULL, ECollisionChannel DamagePreventionChannel = ECC_Visibility);
if (DamagePreventionChannel == ECC_MAX || ComponentIsDamageableFrom(Overlap.Component.Get(), Origin, DamageCauser, IgnoreActors, DamagePreventionChannel, Hit))
{
TArray& HitList = OverlapComponentMap.FindOrAdd(OverlapActor);
HitList.Add(Hit);
}
但是这里有一个点,就是这个通道是在检测完球体内的component后才进行过滤的,而这个检测是调用的physics的检测,
TArray Overlaps;
UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
World->OverlapMultiByObjectType(Overlaps, Origin, FQuat::Identity, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects), FCollisionShape::MakeSphere(DamageOuterRadius), SphereParams);
这个会检测到所有非worldstatic的component
如图,abc为伤害范围内Actor的component,引擎首先获取到这些component放到TArray
如果想要某个特定component不接受RadiusDamage而其他component又不受范围内物体阻挡不修改引擎是没有办法实现的,一种简单粗暴的方法是给这个特定的component设置拿一个单独的碰撞类型到Overlaps后判断其碰撞类型为这个特定类型则不处理后续的伤害
if (Overlap.Component->GetCollisionObjectType()!=ECC_GameTraceChannel3)//to filter RadiusDamage ObjectType
这里ECC_GameTraceChannel3即使特定的碰撞类型,在C++里定义在EngineTypes.h里,注意ECC_EngineTraceChannel1与ECC_GameTraceChannel1的区别。
UENUM(BlueprintType)
enum ECollisionChannel
{
ECC_WorldStatic UMETA(DisplayName="WorldStatic"),
ECC_WorldDynamic UMETA(DisplayName="WorldDynamic"),
ECC_Pawn UMETA(DisplayName="Pawn"),
ECC_Visibility UMETA(DisplayName="Visibility" , TraceQuery="1"),
ECC_Camera UMETA(DisplayName="Camera" , TraceQuery="1"),
ECC_PhysicsBody UMETA(DisplayName="PhysicsBody"),
ECC_Vehicle UMETA(DisplayName="Vehicle"),
ECC_Destructible UMETA(DisplayName="Destructible"),
/** Reserved for gizmo collision */
ECC_EngineTraceChannel1 UMETA(Hidden),
ECC_EngineTraceChannel2 UMETA(Hidden),
...
ECC_EngineTraceChannel6 UMETA(Hidden),
ECC_GameTraceChannel1 UMETA(Hidden),
ECC_GameTraceChannel2 UMETA(Hidden),
ECC_GameTraceChannel3 UMETA(Hidden),
...
ECC_GameTraceChannel18 UMETA(Hidden),
/** Add new serializeable channels above here (i.e. entries that exist in FCollisionResponseContainer) */
/** Add only nonserialized/transient flags below */
// NOTE!!!! THESE ARE BEING DEPRECATED BUT STILL THERE FOR BLUEPRINT. PLEASE DO NOT USE THEM IN CODE
ECC_OverlapAll_Deprecated UMETA(Hidden),
ECC_MAX,
};
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,Name="RadiusDamage",...