您的位置:首页 > 产品设计 > UI/UE

UE4 范围伤害RadiusDamage及碰撞检测通道ECollisionChanel

2017-10-28 17:16 651 查看
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<class UDamageType> DamageTypeClass, const TArray<AActor*>& IgnoreActors, AActor* DamageCauser = NULL, AController* InstigatedByController = NULL, ECollisionChannel DamagePreventionChannel = ECC_Visibility);


函数参数除伤害值和伤害范围外还有一个DamagePreventionChannel,该值是碰撞通道枚举值ECC类型的,作用是检测伤害中心与Actor在该通道上是否有阻挡,有的话不造成伤害,该值默认是ECC_Visibility,意味着编辑器里所有勾选了Visiblity的TraceChanel的Actor均会阻挡伤害,可以改成ECC_MAX来取消掉阻挡检测
if (DamagePreventionChannel == ECC_MAX || ComponentIsDamageableFrom(Overlap.Component.Get(), Origin, DamageCauser, IgnoreActors, DamagePreventionChannel, Hit))
{
TArray<FHitResult>& HitList = OverlapComponentMap.FindOrAdd(OverlapActor);
HitList.Add(Hit);
}

但是这里有一个点,就是这个通道是在检测完球体内的component后才进行过滤的,而这个检测是调用的physics的检测,

TArray<FOverlapResult> 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<FOverlapResult> Overlaps里,再通过在特定通道上的射线检测确定能否造成伤害,如图中a如果在特定通道上被阻挡将不会接受伤害。

如果想要某个特定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,
};


在编辑器里定义在Project\Config\DefaultEngine.ini里

+DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,Name="RadiusDamage",...


在编辑器里设置好默认值,默认对所有其他通道忽略,只有特定component的碰撞类型设置为这个"RadiusDamage"即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UE4 Collision RadiusDamage