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

101 篇文章 35 订阅
本文介绍了在UnrealEngine的游戏开发中,如何设计和实现游戏中角色的主要属性(如力量、智力等)和次级属性(如血量上限、蓝量上限等),并详细解释了如何通过GameplayAttribute和GameplayEffect在角色升级时实时调整属性值。
摘要由CSDN通过智能技术生成

在游戏中,游戏的角色属性会根据游戏玩法也不同,当前制作的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查看会很麻烦,所以一般情况,都有一个属性面板查看角色的属性,后面,我们将制作一个属性面板进行属性查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值