跳到主内容
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);
}

效果

img.png

返回顶部