20. UE5 GAS RPG创建次级属性并实现设置

本文介绍了在UnrealEngine的游戏开发中,如何设计和实现游戏中角色的主要属性(如力量、智力等)和次级属性(如血量上限、蓝量上限等),并详细解释了如何通过GameplayAttribute和GameplayEffect在角色升级时实时调整属性值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在游戏中,游戏的角色属性会根据游戏玩法也不同,当前制作的RPG中,主要分为两种属性,一种是主要属性另一种次级属性。这两种类型属性的区分主要数值的计算是否需要依托于其它数值
举个例子,你的体力值主要在于角色的个人成长增加以及装备等的增加,它不依托于其它属性,所以是主要属性。而你的血量上限需要依托于体力数值,根据体力进行一定的比例设置血量上线,它需要依托于体力属性,所以是次级属性。
接下来,我们首先将属性设置完整,这个属性一般需要策划进行设计,然后程序进行实现,如果自己学习,那么你就是策划,也是程序,所以,接下来我们自己设计一下属性。

经过了长达几分钟的思考,主要属性为一下几项:

  1. Strength 力量
  2. Intelligence 智力
  3. Resilience 韧性
  4. Vigor 体力

而次要属性里面我们设计了多项数值,依托于上面的主要属性,主要用于战斗中

  1. MaxHealth 血量上限,基于Vigor 体力属性计算
  2. MaxMana 蓝量上限,基于Intelligence 智力属性
  3. Armor 防御,基于Resilience 韧性属性计算, 降低所受伤害
  4. ArmorPenetration 护甲穿透,基于Resilience 韧性属性计算,降低敌人的防御,增加暴击率
  5. BlockChance 格挡率 ,基于Armor 防御属性计算,增加格挡伤害概率,触发时,降低一半所受伤害
  6. CriticalHitChance 暴击率,基于ArmorPenetration 护甲穿透属性计算,增加触发暴击伤害的概率
  7. CriticalHitDamage 暴击伤害,基于ArmorPenetration 护甲穿透属性计算,触发暴击时基于增加的伤害量
  8. CriticalHitResistance 暴击抵抗,基于Armor 防御属性计算,降低敌人的暴击概率
  9. HealthRegeneration 血量自动恢复,基于Vigor 体力属性计算,每秒自动恢复一定血量
  10. ManaRegeneration 蓝量自动恢复,基于Intelligence 智力属性,每秒自动恢复蓝量

在AS增加新的属性

我们需要将上面提到的所有属性添加到AS里面,虽然之前的文章说了很多遍如何添加了,这里再复习一遍加强记忆。
在AttributeSet类的上面,我们先定义了一个宏,在调用这个宏的时候,会给我们生成属性对应的定义:

// Uses macros from AttributeSet.h
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

这个宏定义生成四个调用的函数使用。

接下里就是定义一个属性的步骤:

  1. 首先创建一个属性,定义好蓝图可读,定义和服务器的同步函数,以及分类
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Strength, Category="Primary Attributes")
	FGameplayAttributeData Strength; //力量
  1. 设置宏,生成对属性的操作函数
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Strength, Category="Primary Attributes")
	FGameplayAttributeData Strength; //力量
	ATTRIBUTE_ACCESSORS(UAttributeSetBase, Strength);

ATTRIBUTE_ACCESSORS宏调用后,最终会生成四个函数,那Strength举例,会生成四个函数分别是:GetStrengthAttribute() 获取属性引用 GetStrength() 获取属性值 SetStrength(float NewValue) 设置属性值 InitStrength(float NewValue) 初始化属性值

  1. 定义OnRep_Strength,这个函数会在服务器上的属性值发生变化时,将服务器的数值同步到本地。
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;

在cpp中的实现

void UAttributeSetBase::OnRep_Strength(const FGameplayAttributeData& OldStrength) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UAttributeSetBase, Strength, OldStrength);
}

这个宏会生成对应的函数回调,在服务器值修改时,同步到本地。
https://docs.unrealengine.com/5.3/zh-CN/conditional-property-replication-in-unreal-engine/
4. 最后一步就是在GetLifetimeReplicatedProps回调函数中注册此属性提交服务器同步,在本地属性发生改变时,将此值提交给服务器。

void UAttributeSetBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	//主要属性
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Strength, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Intelligence, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Resilience, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Vigor, COND_None, REPNOTIFY_Always);
	//次级属性
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Health, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, MaxHealth, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Mana, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, MaxMana, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, Armor, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, ArmorPenetration, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, BlockChance, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, CriticalHitChance, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, CriticalHitDamage, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, CriticalHitResistance, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, HealthRegeneration, COND_None, REPNOTIFY_Always);
	DOREPLIFETIME_CONDITION_NOTIFY(UAttributeSetBase, ManaRegeneration, COND_None, REPNOTIFY_Always);
}

通过以上四个步骤,我们将所有的属性都注册一下。编译运行一下,showdebug abilitysystem 看一下属性
在这里插入图片描述

实现次级属性的设置

上面,我们把属性都创建了出来,而次级属性需要在主要属性变动的时候,实时变动,这里也不卖关子了,要实现这种效果,我们使用GE的Infinite,在主要属性变动,实时OverWrite覆写值即可。
接下来,我们将实现此功能,在上一章中,我们在角色的基础类中实现了一个方法,实现了主要属性数值的添加

void ACharacterBase::InitializePrimaryAttributes() const
{
	check(IsValid(GetAbilitySystemComponent()));
	check(DefaultPrimaryAttributes);
	
	const FGameplayEffectContextHandle ContextHandle = GetAbilitySystemComponent()->MakeEffectContext();
	const FGameplayEffectSpecHandle SpecHandle = GetAbilitySystemComponent()->MakeOutgoingSpec(DefaultPrimaryAttributes, 1.0f, ContextHandle);
	GetAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), GetAbilitySystemComponent());
}

接下来,我们要修改这个函数可以复用,因为我们将需要添加主要属性和次要属性,这两个属性需要分开添加,我们将这个函数增加两个参数,一个是类作为参数传入,另一个则是玩家等级(后续可以根据等级设置不同的属性)

void ACharacterBase::ApplyEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level) const
{
	check(IsValid(GetAbilitySystemComponent()));
	check(GameplayEffectClass);
	
	const FGameplayEffectContextHandle ContextHandle = GetAbilitySystemComponent()->MakeEffectContext();
	const FGameplayEffectSpecHandle SpecHandle = GetAbilitySystemComponent()->MakeOutgoingSpec(GameplayEffectClass, Level, ContextHandle);
	GetAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), GetAbilitySystemComponent());
}

增加一个GE属性,用于在角色身上设置次级属性的GE

	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Attributes")
	TSubclassOf<UGameplayEffect> DefaultSecondaryAttributes;

增加一个函数,用于初始化两个GE,调用ApplyEffectToSelf函数

void ACharacterBase::InitializeDefaultAttributes() const
{
	ApplyEffectToSelf(DefaultPrimaryAttributes, 1.f);
	ApplyEffectToSelf(DefaultSecondaryAttributes, 1.f);
}

最后,在英雄角色初始化数据的地方,修改为调用InitializeDefaultAttributes()即可
编译打开UE,在角色属性查看是否可以设置两个类
在这里插入图片描述
后面,我们只需要实现次级属性的GE应用即可

实现次级属性的GE

前面提到了,我们要实现次级属性的设置,需要使用GameplayEffect去实现,所以,我们创建一个专门设置次级属性的GE
在这里插入图片描述
设置应用给角色
在这里插入图片描述
设置持续时间为无限
在这里插入图片描述
先增加一个属性进行测试,这里我们使用对Maxhealth进行修改,比例和体力一比一,就是多少体力就有多少最大血量,运算模式记得修改为覆盖(覆写)
在这里插入图片描述
运行查看,发现体力和最大血量是相同的
在这里插入图片描述
接下来我们修改碰撞盒子,在碰撞事件中,增加体力十点,查看最大血量是否跟着改变
在这里插入图片描述
结果显而易见,通过利用GE我们简简单单就实现了对属性的实时修改。

接下来就是对大批量的属性进行修改,这个工作主要是策划进行设计,作为独立游戏,没有策划,你就是策划,我们就随意写一套用作测试所有属性好了。
这里,我将所有的次级属性都进行了设置
在这里插入图片描述
下面对每个属性设置的参数一一截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行项目,showdebug abilitysystem 发现属性都正常设置
在这里插入图片描述
如果属性过多,后面使用debug查看会很麻烦,所以一般情况,都有一个属性面板查看角色的属性,后面,我们将制作一个属性面板进行属性查看

### UE5 中基于 GAS 架构的 RPG 游戏开发 #### 创建角色属性系统 在 Unreal Engine 5 (UE5) 的游戏中,Gameplay Ability System (GAS) 提供了一种强大的方式来管理游戏角色的能力和属性。为了创建一个基本的角色属性系统,在项目设置中启用插件 `GameplayAbilities` 和 `GameplayTags` 是必要的[^1]。 定义自定义属性集类继承于 `UAttributeSet` 类,用于表示玩家的生命值、法力值和其他统计信息: ```cpp // MyCharacterAttributes.h #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "AbilitySystemComponent.h" #include "MyCharacterAttributes.generated.h" /** * */ UCLASS() class MYGAME_API UMyCharacterAttributes : public UAttributeSet { GENERATED_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") FGameplayAttributeData Health; ATTRIBUTE_ACCESSORS(UMyCharacterAttributes, Health) // Other attributes like Mana, Stamina can be added here similarly. }; ``` #### 实现能力框架 接着实现具体的游戏玩法功能——即“能力”。这涉及到编写新的 C++ 或蓝图脚本文件以扩展 `UGameplayAbility` 基础类。这些对象封装了执行特定动作所需的数据逻辑,比如攻击敌人或施放魔法技能等操作。 对于每个想要赋予给角色的新能力,都需要单独创建对应的子类实例配置其行为参数。例如,可以构建名为 `AGrenadeThrowAbility` 的投掷手雷能力类,通过编辑器界面指定冷却时间、消耗资源量以及效果范围等相关设定。 #### 设计任务与奖励机制 当考虑如何在游戏中引入任务系统时,可以通过 GAS 来追踪目标进度向完成挑战的用户提供反馈。利用 `FGameplayTagContainer` 结合标签查询表达式匹配条件触发事件,从而动态调整难度等级或是解锁新区域等内容更新。 此外,还可以借助该系统的灵活性为不同类型的成就设立专属奖赏池,允许开发者轻松定制各种形式的经验加成、道具掉落概率提升等奖励措施。 #### 集成用户界面显示 为了让玩家能够直观了解当前状态变化情况,应该同步修改 HUD 组件以便实时反映最新数值变动。通常做法是在屏幕角落固定位置绘制小型图标条形图等形式展示生命槽、能量棒之类的关键指标;同时也可以采用弹窗提示框的方式告知重要消息通知。 最后值得注意的是,由于 GAS 自身不直接处理 UI 层面的工作,因此这部分工作往往需要额外投入一定精力去精心打磨用户体验细节部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值