中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
cpp
/** 当目标选择Actor拒绝目标确认时调用 */
DECLARE_MULTICAST_DELEGATE_OneParam(FTargetingRejectedConfirmation, int32);
一、这是一个C++中的多播委托声明,用于处理目标选择系统中当Actor拒绝目标确认时的回调机制。让我详细解释一下这个声明:
组成部分:
-
DECLARE_MULTICAST_DELEGATE_OneParam- 宏声明,创建一个可以绑定多个回调函数的多播委托,带有一个参数 -
FTargetingRejectedConfirmation- 委托类型名称 -
int32- 委托的参数类型,这里是一个32位整数
使用示例
1. 声明委托变量:
cpp
// 在类中声明
FTargetingRejectedConfirmation OnTargetingRejected;
2. 绑定回调函数
cpp
// 绑定Lambda表达式
OnTargetingRejected.AddLambda([](int32 TargetID) {
UE_LOG(LogTemp, Warning, TEXT("目标 %d 拒绝确认"), TargetID);
});
// 绑定成员函数
OnTargetingRejected.AddUObject(this, &AMyClass::HandleTargetRejection);
3. 触发委托
cpp
// 当目标拒绝确认时
void AMyTargetingSystem::RejectTargetConfirmation(int32 TargetID)
{
// 广播给所有绑定的回调函数
OnTargetingRejected.Broadcast(TargetID);
}
4. 完整的类示例
cpp
UCLASS()
class MYGAME_API ATargetingSystem : public AActor
{
GENERATED_BODY()
public:
// 委托声明
FTargetingRejectedConfirmation OnTargetingRejected;
// 触发目标拒绝的方法
void ProcessTargetRejection(int32 RejectedTargetID)
{
// 执行一些逻辑...
// 广播委托
OnTargetingRejected.Broadcast(RejectedTargetID);
}
private:
// 处理目标拒绝的成员函数
UFUNCTION()
void HandleTargetRejected(int32 TargetID)
{
UE_LOG(LogTemp, Warning, TEXT("处理目标 %d 的拒绝"), TargetID);
// 执行相应的游戏逻辑
}
public:
// 在BeginPlay中绑定委托
virtual void BeginPlay() override
{
Super::BeginPlay();
OnTargetingRejected.AddUObject(this, &ATargetingSystem::HandleTargetRejected);
}
};
应用场景
这种委托模式常用于:
-
目标选择系统 - 当玩家选择的目标无效或被拒绝时
-
UI交互 - 处理用户取消操作
-
任务系统 - 处理任务目标失败的情况
-
多人游戏 - 同步玩家间的目标选择状态
这种设计提供了很好的解耦,让不同的系统可以监听目标拒绝事件并做出相应反应。
二、在实战项目中,FTargetingRejectedConfirmation 这样的目标选择拒绝确认委托有着广泛的应用场景。以下是一些具体的实际应用案例:
1. 技能系统目标选择
技能目标选择器
cpp
// 技能组件
UCLASS()
class USkillComponent : public UActorComponent
{
GENERATED_BODY()
public:
FTargetingRejectedConfirmation OnTargetRejected;
// 开始选择技能目标
void StartTargetSelection(int32 SkillID)
{
CurrentSkillID = SkillID;
bIsSelectingTarget = true;
// 显示目标选择UI
ShowTargetingUI();
}
// 确认目标选择
void ConfirmTarget(int32 TargetID)
{
if (!IsValidTarget(TargetID))
{
// 目标无效,触发拒绝事件
OnTargetRejected.Broadcast(TargetID);
HandleTargetRejection(TargetID);
return;
}
ExecuteSkill(CurrentSkillID, TargetID);
}
private:
void HandleTargetRejection(int32 TargetID)
{
// 播放拒绝音效
PlayRejectionSound();
// 显示拒绝特效
ShowRejectionEffect(TargetID);
// 重置选择状态
bIsSelectingTarget = false;
}
};
2. UI 系统集成
目标选择UI控制器
cpp
// UI控制器绑定委托
void UTargetSelectionWidget::BindToSkillComponent(USkillComponent* SkillComponent)
{
if (SkillComponent)
{
SkillComponent->OnTargetRejected.AddUObject(
this,
&UTargetSelectionWidget::OnTargetRejected
);
}
}
void UTargetSelectionWidget::OnTargetRejected(int32 TargetID)
{
// 显示红色拒绝提示
ShowRejectionMessage(FText::FromString("Invalid target!"));
// 抖动目标图标
ShakeTargetIcon(TargetID);
// 更新UI状态,允许重新选择
SetSelectionState(ETargetSelectionState::CanReselect);
}
3. AI 命令系统
AI命令执行器
cpp
// AI命令组件
UCLASS()
class UAICommandComponent : public UActorComponent
{
GENERATED_BODY()
public:
FTargetingRejectedConfirmation OnCommandTargetRejected;
void ExecuteAttackCommand(int32 TargetEnemyID)
{
AAIController* AIController = GetAIController();
if (!AIController || !IsEnemyValid(TargetEnemyID))
{
// 目标无效,通知AI系统
OnCommandTargetRejected.Broadcast(TargetEnemyID);
AIController->HandleCommandFailure();
return;
}
// 执行攻击命令
AIController->IssueAttackCommand(TargetEnemyID);
}
};
// AI行为树服务中绑定
UBTTService_ExecuteCommand::UBTTService_ExecuteCommand()
{
CommandComponent = nullptr;
}
void UBTTService_ExecuteCommand::OnBecomeRelevant(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
Super::OnBecomeRelevant(OwnerComp, NodeMemory);
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController)
{
CommandComponent = AIController->FindComponentByClass<UAICommandComponent>();
if (CommandComponent)
{
CommandComponent->OnCommandTargetRejected.AddUObject(
this,
&UBTTService_ExecuteCommand::OnCommandRejected
);
}
}
}
void UBTTService_ExecuteCommand::OnCommandRejected(int32 TargetID)
{
// AI命令失败,切换到其他行为
UE_LOG(LogAI, Warning, TEXT("Attack command rejected for target %d"), TargetID);
// 可以触发寻找新目标、撤退等行为
FindAlternativeTarget();
}
4. 网络同步游戏
多人游戏中的目标验证
cpp
// 网络游戏中的技能系统
void UMultiplayerSkillSystem::Server_ConfirmTarget_Implementation(
APlayerController* PlayerController,
int32 SkillID,
int32 TargetID)
{
if (!ValidateTarget(PlayerController, TargetID))
{
// 服务器端验证失败
OnTargetRejected.Broadcast(TargetID);
// 通知客户端目标无效
Client_TargetRejected(PlayerController, TargetID);
return;
}
// 执行有效的技能
ExecuteSkillOnServer(SkillID, TargetID);
}
void UMultiplayerSkillSystem::Client_TargetRejected_Implementation(
APlayerController* PlayerController,
int32 TargetID)
{
// 客户端收到拒绝通知
OnTargetRejected.Broadcast(TargetID);
// 本地处理拒绝效果
PlayLocalRejectionEffects(TargetID);
}
5. 任务/任务系统
任务目标选择
cpp
// 任务系统
UCLASS()
class UQuestSystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
FTargetingRejectedConfirmation OnQuestTargetRejected;
void SelectQuestTarget(int32 QuestID, int32 TargetNPCID)
{
APlayerController* PlayerController = GetPlayerController();
if (!CanInteractWithQuestTarget(PlayerController, QuestID, TargetNPCID))
{
// 任务目标选择被拒绝
OnQuestTargetRejected.Broadcast(TargetNPCID);
// 显示拒绝原因
ShowQuestRejectionMessage(QuestID, TargetNPCID);
return;
}
StartQuestDialogue(QuestID, TargetNPCID);
}
};
// 任务UI绑定
void UQuestJournalWidget::BindToQuestSystem(UQuestSystem* QuestSystem)
{
QuestSystem->OnQuestTargetRejected.AddUObject(
this,
&UQuestJournalWidget::OnQuestTargetRejected
);
}
void UQuestJournalWidget::OnQuestTargetRejected(int32 TargetNPCID)
{
// 更新任务UI状态
UpdateQuestObjectives();
// 显示提示信息
ShowHintMessage("You cannot interact with this NPC yet. Complete prerequisites first.");
}
6. 调试和数据分析
目标拒绝统计
cpp
// 数据分析组件
UCLASS()
class UAnalyticsComponent : public UActorComponent
{
GENERATED_BODY()
public:
void BindToTargetingSystems()
{
// 绑定到各种目标选择系统
SkillComponent->OnTargetRejected.AddUObject(
this,
&UAnalyticsComponent::OnTargetRejected
);
QuestSystem->OnQuestTargetRejected.AddUObject(
this,
&UAnalyticsComponent::OnTargetRejected
);
}
private:
void OnTargetRejected(int32 TargetID)
{
// 记录分析数据
FTargetRejectionData RejectionData;
RejectionData.TargetID = TargetID;
RejectionData.Timestamp = FDateTime::Now();
RejectionData.PlayerID = GetPlayerID();
AnalyticsProvider->RecordTargetRejection(RejectionData);
UE_LOG(LogAnalytics, Verbose, TEXT("Target %d rejected by player"), TargetID);
}
};
实际项目中的最佳实践
-
清晰的错误分类:根据不同的拒绝原因使用不同的处理逻辑
-
用户体验优化:提供明确的视觉/音频反馈
-
性能考虑:避免在委托处理中进行昂贵的操作
-
内存管理:确保在对象销毁时正确解除绑定
-
网络同步:在多人游戏中确保客户端和服务器的状态同步
这种委托模式在实际项目中极大地提高了代码的模块化和可维护性,使得各个系统能够独立开发而又能高效协作。