虚幻引擎5 GAS开发俯视角RPG游戏 P06-06 次要属性

一.添加主要属性:

1.Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:

(1)定义主要属性

/*主要属性
	*1. Intelligence: 智力
	*2. Resilience: 穿透
	*3. Strength: 力量
	*4. Vigor: 体质
*/
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Intelligence)
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Intelligence);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Resilience)
	FGameplayAttributeData Resilience;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Resilience);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Strength)
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Strength);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Vigor)
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Vigor);
	

(2)复制的回调方法:

	
	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const;

	UFUNCTION()
	void OnRep_Resilience(const FGameplayAttributeData& OldResilience) const;
	
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;
		
	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldVigor) const;

void UCC_AttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Intelligence, OldIntelligence);
}

void UCC_AttributeSet::OnRep_Resilience(const FGameplayAttributeData& OldResilience) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Resilience, OldResilience);
}

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

void UCC_AttributeSet::OnRep_Vigor(const FGameplayAttributeData& OldVigor) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Vigor, OldVigor);
}

(3)将游戏玩法属性添加到属性集源文件中的GetLifetimeReplicatedProps函数中:

public:
	// 用于声明哪些变量需要在服务器和客户端之间自动复制‌
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
void UCC_AttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Intelligence, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Resilience, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Strength, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Vigor, COND_None, REPNOTIFY_Always);
	
}

2.在角色里添加GameplayEffect:

Source/CC_Aura/Public/Characters/CC_CharacterBase.h

(1)创建游戏效果子类

	/*属性效果*/
	UPROPERTY(BlueprintReadOnly,EditAnywhere,Category="Attributes|Primary")
	TSubclassOf<UGameplayEffect> DefualtPrimaryAttributes;
	

(2)创建函数,初始化角色的主要属性:

	/*初始化角色主要属性*/
	void InitCharacterPrimaryAttribute();
void ACC_CharacterBase::InitCharacterPrimaryAttribute()
{
	check(DefualtPrimaryAttributes);
	check(IsValid(GetAbilitySystemComponent()));
	const FGameplayEffectContextHandle ContextHandle = GetAbilitySystemComponent()->MakeEffectContext();
	const FGameplayEffectSpecHandle SpecHandle = GetAbilitySystemComponent()->MakeOutgoingSpec(DefualtPrimaryAttributes, 1.f, ContextHandle);
	GetAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), GetAbilitySystemComponent());
}

该代码实现了UE5 GAS系统中角色主要属性(Primary Attributes)的初始化逻辑,其核心是通过GameplayEffect动态配置属性值而非硬编码初始化。具体分析如下:

功能实现流程

  1. 前置校验
    通过check宏确保DefaultPrimaryAttributes数据资产和AbilitySystemComponent有效,避免空指针导致的运行时崩溃。

  2. 效果上下文创建
    调用MakeEffectContext生成效果上下文对象,用于传递施法者、目标等上下文信息至后续效果应用阶段。

  3. 效果规格生成
    使用MakeOutgoingSpec基于数据资产创建效果规格(GameplayEffectSpec),其中1.f表示效果等级,支持后续按比例调整属性值。

  4. 效果应用
    ApplyGameplayEffectSpecToTarget将生成的效果规格应用到自身ASC,实现属性值的动态初始化。此处目标ASC与源ASC相同,属于自应用效果(self-applied effect)。

设计优势

  • 灵活性‌:通过GameplayEffect数据资产配置属性值,支持策划人员在无需重新编译的情况下调整数值平衡。
  • 扩展性‌:该方法可兼容后续新增的主要属性(如力量、智力等),只需在数据资产中扩展配置而无需修改代码。
  • 网络同步‌:通过GAS内置的复制机制,属性变化会自动同步至客户端,确保多人游戏一致性。

典型应用场景

该模式常用于RPG游戏中角色创建时的基础属性分配,例如:

  • 根据职业模板初始化不同的力量/智力值
  • 加载存档时恢复角色成长后的属性
  • 装备系统临时修改主要属性

(3)在英雄角色初始化ASC时, 初始化主要角色:

CC_HeroCharacter.cpp:


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、AS
	if (AbilitySystemComponent == nullptr || AttributeSet == nullptr)
	{
		AbilitySystemComponent = CCPlayerState->GetAbilitySystemComponent();
		AttributeSet = CCPlayerState->GetAttributeSet();
	}
	//初始化ASC
	AbilitySystemComponent->InitAbilityActorInfo(CCPlayerState, this);
	Cast<UCC_AbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
	//获取玩家控制器
	ACC_PlayerController* CCPlayerController = Cast<ACC_PlayerController>(GetController());
	/*服务器中,拥有所有玩家控制器
	 * 客户端只拥有自己的玩家控制器,当控制器为空是,游戏不能崩溃
	 */
	if (CCPlayerController)
	{
		//获取HUD
		ACC_HUD* CCHUD = Cast<ACC_HUD>(CCPlayerController->GetHUD());
		if (CCHUD) //仅对本地控制的玩家有效
		{
			//初始化HUD
			CCHUD ->InitOverlay(CCPlayerController, CCPlayerState, AbilitySystemComponent, AttributeSet);
		}
	}

	InitCharacterPrimaryAttribute();		//初始化角色主要属性
}

(4)添加游戏效果蓝图:

(5)英雄角色蓝图上添加初始主要属性(DefualtPrimaryAttributes)游戏效果:

(6)效果:

二. 添加次要属性:


/*次要属性:
 * 1. Armor: 护甲	减少受到的伤害, 提高格挡几率.
 *		- 受Resilience影响
 *
 * 2. Armor Penetration: 护甲穿透	忽略敌人护甲的百分比, 增加暴击几率.
 *		- 受Resilience影响
 *
 * 3. Block Chance: 格挡几率		有机会将受到的伤害减半.
 *		- 受Armor影响
 *
 * 4. Critical Hit Chance: 暴击几率		有机会获得双倍伤害并获得暴击加成
 *		- 受Armor Penetration影响
 *
 * 5. Critical Hit Damage: 暴击伤害		暴击时增加的额外伤害
 *		- 受Armor Penetration影响
 *
 * 6. Critical Hit Resistance: 暴击抗性		减少敌人攻击时的暴击几率
 *		- 受Armor影响
 *
 * 7. Health Regeneration: 生命回复		每秒回复的生命值
 *		- 受Vigor影响
 *
 * 8. Mana Regeneration: 魔法回复		每秒回复的魔法值
 *		- 受Intelligence影响
 *
 * 9. Max Health: 最大生命值
 *		- 受Vigor影响
 *
 * 10. Max Mana: 最大法力值
 *		- 受Intelligence影响
 */
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_Armor)
	FGameplayAttributeData Armor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Armor);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ArmorPenetration)
	FGameplayAttributeData ArmorPenetration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ArmorPenetration);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_BlockChance)
	FGameplayAttributeData BlockChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, BlockChance);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitChance)
	FGameplayAttributeData CriticalHitChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitChance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitDamage)
	FGameplayAttributeData CriticalHitDamage;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitDamage);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitResistance)
	FGameplayAttributeData CriticalHitResistance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitResistance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_HealthRegeneration)
	FGameplayAttributeData HealthRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, HealthRegeneration);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ManaRegeneration)
	FGameplayAttributeData ManaRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ManaRegeneration);

	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxHealth)
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxHealth);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxMana)
	FGameplayAttributeData MaxMana;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxMana);

	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldValue) const;
	

void UCC_AttributeSet::OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ManaRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, HealthRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitResistance, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitDamage, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitChance, OldValue);
}

void UCC_AttributeSet::OnRep_BlockChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, BlockChance, OldValue);
}

void UCC_AttributeSet::OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ArmorPenetration, OldValue);
}

void UCC_AttributeSet::OnRep_Armor(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Armor, OldValue);
}

	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Armor, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ArmorPenetration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, BlockChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitDamage, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitResistance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, HealthRegeneration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ManaRegeneration, COND_None, REPNOTIFY_Always);
	

运行游戏:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值