Documentation
6.反射改变多播参数输出中文.md
2025/12/16预计阅读 10 分钟
关键代码
构造函数中编辑
注意判断空指针 nullptr, 不然会报错
UTrapDetectionComponent::UTrapDetectionComponent()
{
PrimaryComponentTick.bCanEverTick = true;
auto ClassType = UTrapDetectionComponent::StaticClass();
auto OnEnemyEnterFun = (FMulticastDelegateProperty*)ClassType->FindPropertyByName("OnEnemyEnter");
if (OnEnemyEnterFun)
{
auto Param = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("Actor");
if (Param)
{
Param->NamePrivate = TEXT("怪物");
}
auto Param2 = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("bIsFirst");
if (Param2)
{
Param2->NamePrivate = TEXT("是否首次进入的目标");
}
}
}
更加推荐的安全方式,使用CastFieldChecked,在编译期间检测断言错误
UTrapDetectionComponent::UTrapDetectionComponent()
{
PrimaryComponentTick.bCanEverTick = true;
const auto ClassType = StaticClass();;
if (const auto OnEnemyEnterFun = CastFieldChecked<FMulticastDelegateProperty>(
ClassType->FindPropertyByName("OnEnemyEnter")))
{
if (const auto Param = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("Actor"))
{
Param->NamePrivate = TEXT("进入攻击范围内的怪物");
}
if (const auto Param2 = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("bIsFirst"))
{
Param2->NamePrivate = TEXT("是否首次进入的怪物");
}
}
if (const auto OnEnemyExitFun = CastFieldChecked<FMulticastDelegateProperty>(
ClassType->FindPropertyByName("OnEnemyExit")))
{
if (const auto Param = OnEnemyExitFun->SignatureFunction->FindPropertyByName("Actor"))
{
Param->NamePrivate = TEXT("离开攻击范围内的怪物");
}
}
}
完整的示例
头文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MyEnemyBase.h"
#include "Components/ActorComponent.h"
#include "TrapDetectionComponent.generated.h"
/**
* 陷阱检测逻辑
*/
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class DEMO2_API UTrapDetectionComponent : public UActorComponent
{
GENERATED_BODY()
public:
UTrapDetectionComponent();
//绑定碰撞
UFUNCTION(BlueprintCallable, Category = "Detection")
void BindToCollider(UShapeComponent* Collider);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEnemyEnter, AActor*, Actor, bool, bIsFirst);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEnemyExit, AActor*, Actor);
UPROPERTY(BlueprintAssignable, Category="Trap|Event", DisplayName="当怪物进入碰撞区域时")
FOnEnemyEnter OnEnemyEnter;
UPROPERTY(BlueprintAssignable, Category="Trap|Event", DisplayName="当怪物离开碰撞区域时")
FOnEnemyExit OnEnemyExit;
UPROPERTY(Blueprintable, BlueprintReadOnly, Category = "Detection")
TArray<AMyEnemyBase*> OverlapedEnemys;
protected:
virtual void BeginPlay() override;
private:
UFUNCTION()
void OnEnemyDeath(AMyEnemyBase* MyEnemyBase);
UFUNCTION()
void HandleBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void HandleEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex);
public:
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
};
cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "Components/Trap/TrapDetectionComponent.h"
#include "Components/ShapeComponent.h"
UTrapDetectionComponent::UTrapDetectionComponent()
{
PrimaryComponentTick.bCanEverTick = true;
auto ClassType = UTrapDetectionComponent::StaticClass();
auto OnEnemyEnterFun = (FMulticastDelegateProperty*)ClassType->FindPropertyByName("OnEnemyEnter");
if (OnEnemyEnterFun)
{
auto Param = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("Actor");
if (Param)
{
Param->NamePrivate = TEXT("怪物");
}
auto Param2 = OnEnemyEnterFun->SignatureFunction->FindPropertyByName("bIsFirst");
if (Param2)
{
Param2->NamePrivate = TEXT("是否首次进入的目标");
}
}
}
void UTrapDetectionComponent::BindToCollider(UShapeComponent* Collider)
{
if (!Collider)
{
UE_LOG(LogTemp, Warning, TEXT("UTrapDetectionComponent::BindToCollider collider is null!"));
return;
}
Collider->OnComponentBeginOverlap.AddDynamic(this, &UTrapDetectionComponent::HandleBeginOverlap);
Collider->OnComponentEndOverlap.AddDynamic(this, &UTrapDetectionComponent::HandleEndOverlap);
}
void UTrapDetectionComponent::BeginPlay()
{
Super::BeginPlay();
}
void UTrapDetectionComponent::OnEnemyDeath(AMyEnemyBase* MyEnemyBase)
{
if (OverlapedEnemys.Contains(MyEnemyBase))
{
OverlapedEnemys.Remove(MyEnemyBase);
}
}
void UTrapDetectionComponent::HandleBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult)
{
if (OtherActor && OtherActor != GetOwner())
{
if (const auto Enemy = Cast<AMyEnemyBase>(OtherActor); Enemy != nullptr && !OverlapedEnemys.Contains(Enemy))
{
const bool bIsFirst = OverlapedEnemys.IsEmpty();
OverlapedEnemys.Add(Enemy);
OnEnemyEnter.Broadcast(Enemy, bIsFirst);
//注册监听怪物死亡事件
if (const bool bIsRegisterDeathEvent = Enemy->OnEnemyDeathEvent.IsAlreadyBound(
this, &UTrapDetectionComponent::OnEnemyDeath); !bIsRegisterDeathEvent)
{
Enemy->OnEnemyDeathEvent.AddDynamic(this, &UTrapDetectionComponent::OnEnemyDeath);
}
}
}
}
void UTrapDetectionComponent::HandleEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (OtherActor && OtherActor != GetOwner())
{
if (const auto Enemy = Cast<AMyEnemyBase>(OtherActor); OverlapedEnemys.Contains(Enemy))
{
OverlapedEnemys.Remove(Enemy);
OnEnemyExit.Broadcast(Enemy);
//移除死亡事件监听
Enemy->OnEnemyDeathEvent.RemoveDynamic(this,&UTrapDetectionComponent::OnEnemyDeath);
}
}
}
void UTrapDetectionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
效果
