一.添加主要属性:
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动态配置属性值而非硬编码初始化。具体分析如下:
功能实现流程
-
前置校验
通过check宏确保DefaultPrimaryAttributes数据资产和AbilitySystemComponent有效,避免空指针导致的运行时崩溃。 -
效果上下文创建
调用MakeEffectContext生成效果上下文对象,用于传递施法者、目标等上下文信息至后续效果应用阶段。 -
效果规格生成
使用MakeOutgoingSpec基于数据资产创建效果规格(GameplayEffectSpec),其中1.f表示效果等级,支持后续按比例调整属性值。 -
效果应用
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);
运行游戏:

165

被折叠的 条评论
为什么被折叠?



