当前位置: 首页 > news >正文

虚幻引擎5 GAS开发俯视角RPG游戏 P05-05 游戏效果委托

该技术文档详细介绍了如何在Unreal Engine中实现游戏效果委托绑定系统。核心实现包括:

  1. 在UCC_AbilitySystemComponent中声明并绑定多播委托EffectApplied()到OnGameplayEffectAppliedDelegateToSelf,用于监听游戏效果应用事件。

  2. 通过AbilityActorInfoSet()方法初始化委托绑定,在角色初始化时调用。

  3. 实现效果处理逻辑:当效果被应用时,从FGameplayEffectSpec获取所有AssetTag并打印到屏幕。

  4. 在英雄角色(CC_HeroCharacter)和敌人角色(CC_EnemyCharacter)中分别实现初始化逻辑,确保服务器和客户端都能正确初始化能力系统组件并绑定委托。

该方案实现了游戏效果系统的解耦通信机制,为后续效果处理和UI反馈奠定了基础。

目标:我们要实现的就是绑定委托,在给自身添加GE时,打印GE附加的Asset Tag

1.在效果中,添加此效果拥有的资产标签:

2.在Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/AbilitySystemComponent.h

中:有相应的委托代码

	/** Delegate for when an effect is applied */DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnGameplayEffectAppliedDelegate, UAbilitySystemComponent*, const FGameplayEffectSpec&, FActiveGameplayEffectHandle);

这段代码是Unreal Engine中的多播委托声明,用于游戏效果应用时的事件通知。以下是关键点解析:

  1. 委托类型:DECLARE_MULTICAST_DELEGATE_ThreeParams声明了一个可绑定多个回调函数的多播委托
  2. 参数结构:委托接收三个参数:
    • UAbilitySystemComponent*:指向能力系统组件的指针
    • const FGameplayEffectSpec&:游戏效果规格的常量引用
    • FActiveGameplayEffectHandle:活动游戏效果的句柄
  3. 典型用途:常用于游戏技能系统,当效果被施加到目标时触发相关事件
  4. 观察者模式:允许多个对象订阅此事件,实现解耦的事件通知机制

这种委托在UE的GameplayAbilitySystem中广泛使用,用于处理技能效果、状态变化等游戏逻辑的通信需求。

接着往下看,会发现基于这个委托宏,创建了多个委托属性,有添加GE给自身触发的,有添加给目标触发的,有持续时间的GE添加给自身触发的,还有周期性触发的GE的委托等等。

/** Called on server whenever a GE is applied to self. This includes instant and duration based GEs. */FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToSelf;/** Called on server whenever a GE is applied to someone else. This includes instant and duration based GEs. */FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToTarget;/** Called on both client and server whenever a duration based GE is added (E.g., instant GEs do not trigger this). */FOnGameplayEffectAppliedDelegate OnActiveGameplayEffectAddedDelegateToSelf;/** Called on server whenever a periodic GE executes on self */FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnSelf;/** Called on server whenever a periodic GE executes on target */FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnTarget;

Unreal Engine GameplayEffect 委托技术文档

委托用途与区别

1. OnGameplayEffectAppliedDelegateToSelf

用途‌:当任意GameplayEffect(GE)被应用到自身时触发(服务器端)
特点‌:

  • 包含瞬时效果和持续效果
  • 仅在服务器端触发
  • 适用于需要立即响应效果应用的逻辑

2. OnGameplayEffectAppliedDelegateToTarget

用途‌:当任意GameplayEffect被应用到其他目标时触发(服务器端)
特点‌:

  • 包含瞬时效果和持续效果
  • 仅在服务器端触发
  • 适用于技能施放者监听目标效果

3. OnActiveGameplayEffectAddedDelegateToSelf

用途‌:当持续型GE被添加到自身时触发(客户端和服务器)
特点‌:

  • 仅持续效果触发(瞬时效果不触发)
  • 双端触发(客户端和服务器)
  • 适用于需要同步显示的状态效果

4. OnPeriodicGameplayEffectExecuteDelegateOnSelf

用途‌:当周期性GE在自身执行时触发(服务器端)
特点‌:

  • 仅周期性效果触发(如每2秒造成伤害)
  • 仅在服务器端触发
  • 适用于处理周期性伤害/治疗逻辑

5. OnPeriodicGameplayEffectExecuteDelegateOnTarget

用途‌:当周期性GE在目标执行时触发(服务器端)
特点‌:

  • 仅周期性效果触发
  • 仅在服务器端触发
  • 适用于技能施放者监听目标的周期性效果

3.在Source/CC_Aura/Public/AbilitySystem/CC_AbilitySystemComponent.h

里面,添加一个多播委托:EffectApplied()

protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveEffectHandle);

(2)将EffectApplied()绑定到

	/** Called on server whenever a GE is applied to self. This includes instant and duration based GEs. */FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToSelf;

(3)创建一个函数,当我们初始化了能力信息时,绑定它:

public:void AbilityActorInfoSet();

(4)在演员能力信息初始化时,调用:

private://初始化能力演员信息void InitCharacterAbilityInfo();

在Source/CC_Aura/Public/Characters/CC_CharacterBase.h

protected://初始化能力演员信息virtual void InitCharacterASC();

Source/CC_Aura/Public/Characters/CC_HeroCharacter.h:

protected://初始化能力演员信息virtual void InitCharacterASC() override;

Source/CC_Aura/Public/Characters/CC_EnemyCharacter.h:

protected://初始化能力演员信息virtual void InitCharacterASC() override;

void ACC_EnemyCharacter::BeginPlay()
{Super::BeginPlay();InitCharacterASC();
}void ACC_EnemyCharacter::InitCharacterASC()
{	// 为敌人类初始化演员能力信息AbilitySystemComponent->InitAbilityActorInfo(this,this);Cast<UCC_AbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
}

(5)Source/CC_Aura/Private/AbilitySystem/CC_AbilitySystemComponent.cpp

效果:

源码:

Source/CC_Aura/Public/AbilitySystem/CC_AbilitySystemComponent.h

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "CC_AbilitySystemComponent.generated.h"/*** */
UCLASS()
class CC_AURA_API UCC_AbilitySystemComponent : public UAbilitySystemComponent
{GENERATED_BODY()
public:void AbilityActorInfoSet();protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveEffectHandle);};

Source/CC_Aura/Private/AbilitySystem/CC_AbilitySystemComponent.cpp;

// 版权归陈超所有#include "AbilitySystem/CC_AbilitySystemComponent.h"void UCC_AbilitySystemComponent::AbilityActorInfoSet()
{//多播委托,绑定回调函数OnGameplayEffectAppliedDelegateToSelf.AddUObject(this, &UCC_AbilitySystemComponent::EffectApplied);
}void UCC_AbilitySystemComponent::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveEffectHandle)
{// GEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Blue, FString("Effect Applied!"));FGameplayTagContainer TagContainer;EffectSpec.GetAllAssetTags(TagContainer);for(const FGameplayTag& Tag : TagContainer){//TODO: 将tag广播给Widget Controllerconst FString Msg = FString::Printf(TEXT("GE Tag: %s"), *Tag.ToString()); //获取Asset TagGEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖}
}

Source/CC_Aura/Public/Characters/CC_CharacterBase.h:

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "AbilitySystemInterface.h"
#include "GameFramework/Character.h"
#include "CC_CharacterBase.generated.h"class UAbilitySystemComponent;
class UAttributeSet;
class USkeletalMeshComponent;UCLASS(Abstract)
class CC_AURA_API ACC_CharacterBase : public ACharacter,public IAbilitySystemInterface
{GENERATED_BODY()public:// 设置此角色属性的默认值ACC_CharacterBase();//重写接口函数,获取能力系统组件virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;//获取属性集virtual UAttributeSet* GetAttributeSet() const {return AttributeSet;};protected:// 在游戏开始或生成时调用virtual void BeginPlay() override;UPROPERTY(EditAnywhere,Category="Combat")TObjectPtr<USkeletalMeshComponent> Weapon;UPROPERTY()TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;UPROPERTY()TObjectPtr<UAttributeSet> AttributeSet;protected://初始化能力演员信息virtual void InitCharacterASC();
};

Source/CC_Aura/Private/Characters/CC_CharacterBase.cpp:

// 版权归陈超所有#include "Characters/CC_CharacterBase.h"#include "AbilitySystem/CC_AbilitySystemComponent.h"// #include "AttributeSet.h"// 设置默认值
ACC_CharacterBase::ACC_CharacterBase()
{// 将此字符设置为每帧调用Tick()。如果你不需要它,你可以关闭它来提高性能。PrimaryActorTick.bCanEverTick = false;//将武器添加到角色身上,并且武器跟随某个骨骼节点移动,形成手握武器效果。Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Weapon"));	//创建默认子对象Weapon->SetupAttachment(GetMesh(), FName("WeaponHandSocket"));		//添加到父节点Weapon->SetCollisionEnabled(ECollisionEnabled::NoCollision);		//关闭骨骼网格体碰撞}//重写接口函数,获取能力系统组件
UAbilitySystemComponent* ACC_CharacterBase::GetAbilitySystemComponent() const
{return AbilitySystemComponent;
}// 在游戏开始或生成时调用
void ACC_CharacterBase::BeginPlay()
{Super::BeginPlay();}void ACC_CharacterBase::InitCharacterASC()
{
}

Source/CC_Aura/Public/Characters/CC_HeroCharacter.h:

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "Characters/CC_CharacterBase.h"
#include "CC_HeroCharacter.generated.h"class UCameraComponent;
class USpringArmComponent;
/*** */
UCLASS()
class CC_AURA_API ACC_HeroCharacter : public ACC_CharacterBase
{GENERATED_BODY()public://构造函数ACC_HeroCharacter();//服务器端初始化ASCvirtual void PossessedBy(AController* NewController) override;;//客户端初始化ASCvirtual void OnRep_PlayerState() override;protected://初始化能力演员信息virtual void InitCharacterASC() override;#pragma region Components//弹簧臂组件UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera", meta = (AllowPrivateAccess = "true"))TObjectPtr<USpringArmComponent> SpringArm;//跟随摄像机组件UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera", meta = (AllowPrivateAccess = "true"))TObjectPtr<UCameraComponent> FollowCamera;#pragma endregion};

Source/CC_Aura/Private/Characters/CC_HeroCharacter.cpp:

// 版权归陈超所有#include "Characters/CC_HeroCharacter.h"// #include "AbilitySystemComponent.h"
#include "AbilitySystem/CC_AbilitySystemComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Player/CC_PlayerController.h"
#include "Player/CC_PlayerState.h"
#include "UI/HUD/CC_HUD.h"ACC_HeroCharacter::ACC_HeroCharacter()
{//角色本身的设置(俯视角游戏)GetCharacterMovement()->bOrientRotationToMovement = true; //设置为true,角色将朝移动的方向旋转GetCharacterMovement()->RotationRate = FRotator(0.f, 400.f, 0.f); //旋转速率GetCharacterMovement()->bConstrainToPlane = true; //约束到平面GetCharacterMovement()->bSnapToPlaneAtStart = true; //设置了上面一项为true,且此项设置为true,则在开始时与地面对齐bUseControllerRotationPitch = false;	//同时需要确保角色本身不跟随控制器旋转:bUseControllerRotationYaw = false;bUseControllerRotationRoll = false;//弹簧臂组件SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));SpringArm->SetupAttachment(RootComponent);	//设置附着点(跟组件)SpringArm->TargetArmLength = 900;SpringArm->SetRelativeRotation(FRotator(-45.f, 0, 0));	//设置相对旋转 设置俯视角度(Pitch负值)SpringArm->bUsePawnControlRotation = false;	//确保不随角色转向而转动SpringArm->bInheritPitch = false;	//取消继承俯仰SpringArm->bInheritRoll = false;	//取消继承翻滚SpringArm->bInheritYaw = false;		//取消继承摇摆SpringArm->bEnableCameraLag = true;	//相机延迟效果//跟随摄像机组件FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));FollowCamera->SetupAttachment(SpringArm, USpringArmComponent::SocketName); //设置附着点(弹簧臂组件接口名称)FollowCamera->bUsePawnControlRotation = false;}void ACC_HeroCharacter::PossessedBy(AController* NewController)
{Super::PossessedBy(NewController);//服务器端初始化ASCInitCharacterASC();
}void ACC_HeroCharacter::OnRep_PlayerState()
{Super::OnRep_PlayerState();//客户端初始化ASCInitCharacterASC();
}void ACC_HeroCharacter::InitCharacterASC()
{ACC_PlayerState* CCPlayerState = GetPlayerState<ACC_PlayerState>();	//获取玩家状态// check(CCPlayerState);if (CCPlayerState == nullptr){UE_LOG(LogTemp, Warning, TEXT("CCPlayerState: %s - CCPlayerState is nullptl"), *GetName());return;}//获取玩家角色的ASC、ASif (AbilitySystemComponent == nullptr || AttributeSet == nullptr){AbilitySystemComponent = CCPlayerState->GetAbilitySystemComponent();AttributeSet = CCPlayerState->GetAttributeSet();}//初始化ASCAbilitySystemComponent->InitAbilityActorInfo(CCPlayerState, this);Cast<UCC_AbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();//获取玩家控制器ACC_PlayerController* CCPlayerController = Cast<ACC_PlayerController>(GetController());/*服务器中,拥有所有玩家控制器* 客户端只拥有自己的玩家控制器,当控制器为空是,游戏不能崩溃*/if (CCPlayerController){//获取HUDACC_HUD* CCHUD = Cast<ACC_HUD>(CCPlayerController->GetHUD());if (CCHUD) //仅对本地控制的玩家有效{//初始化HUDCCHUD ->InitOverlay(CCPlayerController, CCPlayerState, AbilitySystemComponent, AttributeSet);}}
}

Source/CC_Aura/Public/Characters/CC_EnemyCharacter.h:

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "Characters/CC_CharacterBase.h"
#include "Interations/CC_EnemyInterface.h"
#include "CC_EnemyCharacter.generated.h"/*** */
UCLASS()
class CC_AURA_API ACC_EnemyCharacter : public ACC_CharacterBase ,public ICC_EnemyInterface
{GENERATED_BODY()public:ACC_EnemyCharacter();// ~Begin IEnemyInterface重写函数virtual void HighlightActor() override;virtual void UnHighlightActor() override;// ~End IEnemyInterface重写函数protected:virtual void BeginPlay() override;protected://初始化能力演员信息virtual void InitCharacterASC() override;
};

Source/CC_Aura/Private/Characters/CC_EnemyCharacter.cpp:

// 版权归陈超所有#include "Characters/CC_EnemyCharacter.h"#include "AbilitySystem/CC_AbilitySystemComponent.h"
#include "AbilitySystem/CC_AttributeSet.h"
#include "CC_Aura/CC_Aura.h"//构造函数
ACC_EnemyCharacter::ACC_EnemyCharacter()
{//为网格设置碰撞响应GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);	//自定义碰撞,块碰撞//添加能力系统组件AbilitySystemComponent = CreateDefaultSubobject<UCC_AbilitySystemComponent>("AbilitySystemComponent");AbilitySystemComponent->SetIsReplicated(true); //设置组件用于在网络上复制AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);	//复制模式//添加属性集AttributeSet = CreateDefaultSubobject<UCC_AttributeSet>("AttributeSet");
}void ACC_EnemyCharacter::BeginPlay()
{Super::BeginPlay();InitCharacterASC();
}void ACC_EnemyCharacter::InitCharacterASC()
{	// 为敌人类初始化演员能力信息AbilitySystemComponent->InitAbilityActorInfo(this,this);Cast<UCC_AbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
}//高亮显示角色
void ACC_EnemyCharacter::HighlightActor()
{GetMesh()->SetRenderCustomDepth(true);	//是否渲染自定义深度GetMesh()->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);		//自定义深度模板值Weapon->SetRenderCustomDepth(true);Weapon->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);
}//取消高亮显示角色
void ACC_EnemyCharacter::UnHighlightActor()
{GetMesh()->SetRenderCustomDepth(false);Weapon->SetRenderCustomDepth(false);
}

http://www.dtcms.com/a/457020.html

相关文章:

  • 音频audio播放两种方式:MediaPlayer和AudioTrack对比
  • K8s学习笔记(十五) pause容器与init容器
  • DVWA靶场之十六:未验证的重定向漏洞(Open HTTP Redirect)
  • 上海网站建设免费推做网站的软件 简单易学
  • 面部情绪识别数据集的介绍和下载
  • Golang中的HTTP请求凝聚器
  • 网站建设多少钱一平米中铁建设集团门户网登陆
  • Linux shell学习(更新中....)
  • 自动生成API文档与故障排查决策树的NLP应用
  • 手机怎么制作钓鱼网站建设文明网 联盟网站的
  • Rust 的类型自动解引用:隐藏在人体工学设计中的魔法
  • AVX-512深度实现分析:从原理到LLaMA.cpp的性能优化艺术
  • 前端玩转大模型,DeepSeek-R1 蒸馏 Llama 模型的 Bedrock 部署
  • 计算机网络-运输层
  • OSPF协议详解5:实验 - 计时器、度量值与其他高级配置
  • OpenCV(五):鼠标控制
  • Linux中权限系统
  • 网站域名到期后果四川人力资源考试官网二建
  • python爬虫(五) ---- Pyinstaller打包Python程序为exe文件及遇到的问题
  • 沈阳做网站价格自己做网站要学什么
  • 深入浅出ArkTS:HarmonyOS应用开发的现代化语法解析
  • UVa 204 Robot Crash
  • 2025 完整指南:Gemini 2.5 Computer Use 模型 - AI Agent 界面控制的革命性突破
  • 云南网站建设专业品牌网站域名怎么转
  • Vue项目中如何实现表格选中数据的 Excel 导出
  • 【多模态学习】QA7: GRPO算法?KL散度指的是什么?什么叫做长思维连冷启动?模型退火是什么意思?
  • 无人机_鲁棒性
  • 用自己的计算机做服务器建网站海外模板网站有哪些
  • 检测MODBUS通讯连接 (MODBUS POLL)
  • 数据结构(陈越,何钦铭)期末考试