在 Unreal Engine 中,DamageTaken
通常与角色或对象受到伤害的机制相关。处理伤害是游戏开发中常见的需求,例如角色受到攻击、敌人被击中、道具受到破坏等。为了实现这一机制,Unreal Engine 提供了几种处理伤害的方式,其中包括使用 TakeDamage
函数和 OnTakeAnyDamage
委托。
1. 处理伤害的基础机制
1.1 TakeDamage
函数
TakeDamage
是 AActor
类中的一个虚函数,用于处理角色或对象受到伤害的逻辑。可以在继承 AActor
的类中重写这个函数,以自定义处理伤害的行为。
// AMyCharacter.h class AMyCharacter : public ACharacter { GENERATED_BODY() public: // 重写 TakeDamage 函数 virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override; }; // AMyCharacter.cpp float AMyCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) { // 调用基类的 TakeDamage 函数,确保默认的伤害处理逻辑被执行 float ActualDamage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); // 实现自定义的伤害处理逻辑 Health -= ActualDamage; if (Health <= 0.0f) { // 角色死亡逻辑 Die(); } return ActualDamage; }
TakeDamage
函数参数:
DamageAmount
:伤害值,表示本次攻击的伤害量。DamageEvent
:伤害事件结构体,包含了伤害类型、伤害来源等信息。EventInstigator
:引发伤害的控制器(通常是玩家或 AI 控制器)。DamageCauser
:造成伤害的对象(如子弹、爆炸物)。
1.2 OnTakeAnyDamage
委托
OnTakeAnyDamage
是 AActor
类中的一个多播委托,当 Actor
受到任何类型的伤害时,都会触发这个委托。可以使用 OnTakeAnyDamage.AddDynamic
在运行时将函数绑定到这个委托上。
// 在构造函数或 BeginPlay 中绑定委托 AMyCharacter::AMyCharacter() { OnTakeAnyDamage.AddDynamic(this, &AMyCharacter::HandleDamage); } void AMyCharacter::BeginPlay() { Super::BeginPlay(); // 绑定委托 OnTakeAnyDamage.AddDynamic(this, &AMyCharacter::HandleDamage); } // 定义处理伤害的函数 void AMyCharacter::HandleDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser) { // 自定义伤害处理逻辑 UE_LOG(LogTemp, Warning, TEXT("Actor %s took %f damage"), *DamagedActor->GetName(), Damage); Health -= Damage; if (Health <= 0.0f) { Die(); } }
OnTakeAnyDamage
委托参数:
DamagedActor
:受到伤害的对象。Damage
:伤害值。DamageType
:伤害类型,通常继承自UDamageType
类。InstigatedBy
:引发伤害的控制器(如玩家控制器)。DamageCauser
:造成伤害的对象(如子弹、爆炸物)。
2. 伤害类型的处理
Unreal Engine 提供了 UDamageType
类,用于定义不同类型的伤害,例如物理伤害、火焰伤害、毒药伤害等。你可以继承 UDamageType
创建自定义的伤害类型,并在 TakeDamage
或 HandleDamage
函数中根据伤害类型做出不同的反应。
自定义伤害类型
// MyDamageType.h #pragma once #include "CoreMinimal.h" #include "GameFramework/DamageType.h" #include "MyDamageType.generated.h" UCLASS() class MYGAME_API UMyDamageType : public UDamageType { GENERATED_BODY() public: // 定义自定义的属性或方法 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Damage") bool bIsFireDamage = false; };
在 TakeDamage
函数中处理自定义伤害类型:
float AMyCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) { Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); // 获取伤害类型 const UDamageType* DamageType = DamageEvent.DamageTypeClass->GetDefaultObject<UDamageType>(); if (DamageType) { // 判断是否是自定义的火焰伤害 if (DamageType->IsA<UMyDamageType>() && Cast<UMyDamageType>(DamageType)->bIsFireDamage) { // 执行火焰伤害的逻辑 UE_LOG(LogTemp, Warning, TEXT("Character took fire damage!")); } } return DamageAmount; }
3. 触发伤害
为了触发伤害,可以使用 UGameplayStatics::ApplyDamage
或其他类似的函数。这些函数会调用 TakeDamage
和 OnTakeAnyDamage
,并传递伤害信息。
使用 ApplyDamage
#include "Kismet/GameplayStatics.h" // ApplyDamage 函数触发伤害 UGameplayStatics::ApplyDamage(TargetActor, 10.0f, InstigatorController, DamageCauser, UDamageType::StaticClass());
ApplyDamage
函数参数:
TargetActor
:受到伤害的对象。10.0f
:伤害值。InstigatorController
:引发伤害的控制器。DamageCauser
:造成伤害的对象(如子弹、爆炸物)。UDamageType::StaticClass()
:伤害类型,可以是自定义的UDamageType
子类。
使用其他触发函数
ApplyPointDamage
:应用点伤害,适合射线投射或子弹伤害。ApplyRadialDamage
:应用半径伤害,适合爆炸等影响范围内的伤害。ApplyRadialDamageWithFalloff
:应用带有衰减的半径伤害,适合爆炸中随着距离衰减的伤害。
// ApplyPointDamage UGameplayStatics::ApplyPointDamage(TargetActor, 15.0f, HitFromDirection, HitResult, InstigatorController, DamageCauser, UDamageType::StaticClass()); // ApplyRadialDamage UGameplayStatics::ApplyRadialDamage(GetWorld(), 20.0f, ExplosionLocation, DamageRadius, UDamageType::StaticClass(), IgnoreActors, DamageCauser, InstigatorController, true); // ApplyRadialDamageWithFalloff UGameplayStatics::ApplyRadialDamageWithFalloff(GetWorld(), 50.0f, 10.0f, ExplosionLocation, InnerRadius, OuterRadius, Falloff, UDamageType::StaticClass(), IgnoreActors, DamageCauser, InstigatorController, ECC_Visibility);
4. 蓝图中处理伤害
在蓝图中也可以处理伤害事件。你可以使用内置的事件节点,比如 Event AnyDamage
或 Event Point Damage
,来处理受到的伤害。
使用 Event AnyDamage
- 在蓝图角色中,右键搜索
Event AnyDamage
。 - 添加该事件节点。
- 在事件节点中添加自定义逻辑,例如减少生命值、播放受击动画、更新 UI 等。
使用 Event Point Damage
和 Event Radial Damage
Event Point Damage
处理点伤害事件,适合精确射击或刺击类攻击。Event Radial Damage
处理半径伤害事件,适合爆炸或范围攻击。
5. 总结
TakeDamage
和OnTakeAnyDamage
是 Unreal Engine 中处理伤害的主要机制。UDamageType
可以用于定义不同类型的伤害,以便在处理时区分。ApplyDamage
、ApplyPointDamage
、ApplyRadialDamage
等函数用于触发伤害事件。- 可以通过重写
TakeDamage
函数或绑定OnTakeAnyDamage
委托来自定义伤害处理逻辑。 - 蓝图中可以使用内置事件节点来处理伤害逻