Lyra源码分析:LyraAbilitySet

LyraAbilitySet.h 文件分析

// Copyright Epic Games, Inc. All Rights Reserved.
// 版权声明,表明这是Epic Games的代码

#pragma once
// 头文件保护宏,防止重复包含

#include "ActiveGameplayEffectHandle.h"
// 包含活跃Gameplay效果句柄的定义
#include "Engine/DataAsset.h"
// 包含数据资产基类
#include "AttributeSet.h"
// 包含属性集基类
#include "GameplayTagContainer.h"
// 包含游戏标签容器
#include "GameplayAbilitySpecHandle.h"
// 包含游戏能力规格句柄
#include "LyraAbilitySet.generated.h"
// 包含UE生成的反射头文件

class UAttributeSet;
// 前向声明属性集类
class UGameplayEffect;
// 前向声明Gameplay效果类
class ULyraAbilitySystemComponent;
// 前向声明Lyra能力系统组件
class ULyraGameplayAbility;
// 前向声明Lyra游戏能力
class UObject;
// 前向声明UObject基类

/**
 * FLyraAbilitySet_GameplayAbility
 *
 *	Data used by the ability set to grant gameplay abilities.
 *  能力集用于授予游戏能力的数据结构
 */
USTRUCT(BlueprintType)
// UE宏:声明为可在蓝图中使用的结构体
struct FLyraAbilitySet_GameplayAbility
{
    GENERATED_BODY()
    // UE宏:生成必要的反射代码体

public:
    // Gameplay ability to grant.
    // 要授予的游戏能力类
    UPROPERTY(EditDefaultsOnly)
    // UE属性:仅在编辑默认值时可编辑
    TSubclassOf<ULyraGameplayAbility> Ability = nullptr;
    // 模板类:指定必须是ULyraGameplayAbility或其子类

    // Level of ability to grant.
    // 授予的能力等级
    UPROPERTY(EditDefaultsOnly)
    int32 AbilityLevel = 1;

    // Tag used to process input for the ability.
    // 用于处理能力输入的标签
    UPROPERTY(EditDefaultsOnly, Meta = (Categories = "InputTag"))
    // Meta指定标签分类为InputTag
    FGameplayTag InputTag;
    // 游戏标签,用于输入绑定
};

/**
 * FLyraAbilitySet_GameplayEffect
 *
 *	Data used by the ability set to grant gameplay effects.
 *  能力集用于授予游戏效果的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_GameplayEffect
{
    GENERATED_BODY()

public:
    // Gameplay effect to grant.
    // 要授予的游戏效果类
    UPROPERTY(EditDefaultsOnly)
    TSubclassOf<UGameplayEffect> GameplayEffect = nullptr;

    // Level of gameplay effect to grant.
    // 授予的游戏效果等级
    UPROPERTY(EditDefaultsOnly)
    float EffectLevel = 1.0f;
};

/**
 * FLyraAbilitySet_AttributeSet
 *
 *	Data used by the ability set to grant attribute sets.
 *  能力集用于授予属性集的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_AttributeSet
{
    GENERATED_BODY()

public:
    // Gameplay effect to grant.
    // 要授予的属性集类
    UPROPERTY(EditDefaultsOnly)
    TSubclassOf<UAttributeSet> AttributeSet;
    // 注意:这里注释写的是Gameplay effect但实际是AttributeSet,可能是复制粘贴错误
};

/**
 * FLyraAbilitySet_GrantedHandles
 *
 *	Data used to store handles to what has been granted by the ability set.
 *  用于存储能力集已授予内容的句柄的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_GrantedHandles
{
    GENERATED_BODY()

public:
    // 添加能力规格句柄到集合
    void AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle);
    
    // 添加游戏效果句柄到集合
    void AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle);
    
    // 添加属性集到集合
    void AddAttributeSet(UAttributeSet* Set);

    // 从能力系统中移除所有已授予的内容
    void TakeFromAbilitySystem(ULyraAbilitySystemComponent* LyraASC);

protected:
    // Handles to the granted abilities.
    // 已授予能力的句柄数组
    UPROPERTY()
    TArray<FGameplayAbilitySpecHandle> AbilitySpecHandles;

    // Handles to the granted gameplay effects.
    // 已授予游戏效果的句柄数组
    UPROPERTY()
    TArray<FActiveGameplayEffectHandle> GameplayEffectHandles;

    // Pointers to the granted attribute sets
    // 指向已授予属性集的指针数组
    UPROPERTY()
    TArray<TObjectPtr<UAttributeSet>> GrantedAttributeSets;
    // TObjectPtr是UE的智能对象指针类型
};

/**
 * ULyraAbilitySet
 *
 *	Non-mutable data asset used to grant gameplay abilities and gameplay effects.
 *  不可变的数据资产,用于授予游戏能力和游戏效果
 */
UCLASS(BlueprintType, Const)
// BlueprintType表示可在蓝图中使用,Const表示实例在运行时不可修改
class ULyraAbilitySet : public UPrimaryDataAsset
// 继承自主数据资产
{
    GENERATED_BODY()
    // UE宏:生成类反射代码体

public:
    // 构造函数
    ULyraAbilitySet(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

    // Grants the ability set to the specified ability system component.
    // The returned handles can be used later to take away anything that was granted.
    // 将能力集授予指定的能力系统组件
    // 返回的句柄可用于后续移除所有已授予的内容
    void GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject = nullptr) const;

protected:
    // Gameplay abilities to grant when this ability set is granted.
    // 当此能力集被授予时要授予的游戏能力数组
    UPROPERTY(EditDefaultsOnly, Category = "Gameplay Abilities", meta=(TitleProperty=Ability))
    // Category定义在编辑器中的分类,TitleProperty指定在数组中显示哪个属性作为标题
    TArray<FLyraAbilitySet_GameplayAbility> GrantedGameplayAbilities;

    // Gameplay effects to grant when this ability set is granted.
    // 当此能力集被授予时要授予的游戏效果数组
    UPROPERTY(EditDefaultsOnly, Category = "Gameplay Effects", meta=(TitleProperty=GameplayEffect))
    TArray<FLyraAbilitySet_GameplayEffect> GrantedGameplayEffects;

    // Attribute sets to grant when this ability set is granted.
    // 当此能力集被授予时要授予的属性集数组
    UPROPERTY(EditDefaultsOnly, Category = "Attribute Sets", meta=(TitleProperty=AttributeSet))
    TArray<FLyraAbilitySet_AttributeSet> GrantedAttributes;
};

LyraAbilitySet.cpp 文件分析

// Copyright Epic Games, Inc. All Rights Reserved.
// 版权声明

#include "LyraAbilitySet.h"
// 包含头文件

#include "AbilitySystem/Abilities/LyraGameplayAbility.h"
// 包含Lyra游戏能力头文件
#include "LyraAbilitySystemComponent.h"
// 包含Lyra能力系统组件头文件
#include "LyraLogChannels.h"
// 包含Lyra日志通道头文件

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraAbilitySet)
// UE宏:内联生成C++代码

// 添加能力规格句柄的实现
void FLyraAbilitySet_GrantedHandles::AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle)
{
    if (Handle.IsValid())
    // 检查句柄是否有效
    {
        AbilitySpecHandles.Add(Handle);
        // 添加到能力规格句柄数组
    }
}

// 添加游戏效果句柄的实现
void FLyraAbilitySet_GrantedHandles::AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle)
{
    if (Handle.IsValid())
    {
        GameplayEffectHandles.Add(Handle);
        // 添加到游戏效果句柄数组
    }
}

// 添加属性集的实现
void FLyraAbilitySet_GrantedHandles::AddAttributeSet(UAttributeSet* Set)
{
    GrantedAttributeSets.Add(Set);
    // 添加到属性集指针数组
}

// 从能力系统移除所有已授予内容的实现
void FLyraAbilitySet_GrantedHandles::TakeFromAbilitySystem(ULyraAbilitySystemComponent* LyraASC)
{
    check(LyraASC);
    // 断言检查LyraASC不能为空

    if (!LyraASC->IsOwnerActorAuthoritative())
    // 检查是否是权威端(服务器)
    {
        // Must be authoritative to give or take ability sets.
        // 必须是权威端才能给予或移除能力集
        return;
    }

    // 移除所有已授予的能力
    for (const FGameplayAbilitySpecHandle& Handle : AbilitySpecHandles)
    {
        if (Handle.IsValid())
        {
            LyraASC->ClearAbility(Handle);
            // 从能力系统清除能力
        }
    }

    // 移除所有已授予的游戏效果
    for (const FActiveGameplayEffectHandle& Handle : GameplayEffectHandles)
    {
        if (Handle.IsValid())
        {
            LyraASC->RemoveActiveGameplayEffect(Handle);
            // 从能力系统移除活跃游戏效果
        }
    }

    // 移除所有已授予的属性集
    for (UAttributeSet* Set : GrantedAttributeSets)
    {
        LyraASC->RemoveSpawnedAttribute(Set);
        // 从能力系统移除生成的属性集
    }

    // 重置所有数组
    AbilitySpecHandles.Reset();
    GameplayEffectHandles.Reset();
    GrantedAttributeSets.Reset();
}

// 构造函数实现
ULyraAbilitySet::ULyraAbilitySet(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
    // 调用父类构造函数
{
}

// 将能力集授予能力系统组件的实现
void ULyraAbilitySet::GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject) const
{
    check(LyraASC);
    // 断言检查LyraASC不能为空

    if (!LyraASC->IsOwnerActorAuthoritative())
    // 检查是否是权威端
    {
        // Must be authoritative to give or take ability sets.
        return;
    }

    // 授予游戏能力
    for (int32 AbilityIndex = 0; AbilityIndex < GrantedGameplayAbilities.Num(); ++AbilityIndex)
    // 遍历所有要授予的游戏能力
    {
        const FLyraAbilitySet_GameplayAbility& AbilityToGrant = GrantedGameplayAbilities[AbilityIndex];
        // 获取要授予的能力数据

        if (!IsValid(AbilityToGrant.Ability))
        // 检查能力类是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayAbilities[%d] on ability set [%s] is not valid."), AbilityIndex, *GetNameSafe(this));
            // 记录错误日志
            continue;
            // 跳过无效的能力
        }

        ULyraGameplayAbility* AbilityCDO = AbilityToGrant.Ability->GetDefaultObject<ULyraGameplayAbility>();
        // 获取能力的类默认对象

        FGameplayAbilitySpec AbilitySpec(AbilityCDO, AbilityToGrant.AbilityLevel);
        // 创建能力规格,包含能力和等级
        AbilitySpec.SourceObject = SourceObject;
        // 设置源对象
        AbilitySpec.DynamicAbilityTags.AddTag(AbilityToGrant.InputTag);
        // 添加输入标签到动态能力标签

        const FGameplayAbilitySpecHandle AbilitySpecHandle = LyraASC->GiveAbility(AbilitySpec);
        // 将能力授予能力系统,返回能力规格句柄

        if (OutGrantedHandles)
        // 检查输出句柄指针是否有效
        {
            OutGrantedHandles->AddAbilitySpecHandle(AbilitySpecHandle);
            // 添加能力规格句柄到输出集合
        }
    }

    // 授予游戏效果
    for (int32 EffectIndex = 0; EffectIndex < GrantedGameplayEffects.Num(); ++EffectIndex)
    // 遍历所有要授予的游戏效果
    {
        const FLyraAbilitySet_GameplayEffect& EffectToGrant = GrantedGameplayEffects[EffectIndex];
        // 获取要授予的效果数据

        if (!IsValid(EffectToGrant.GameplayEffect))
        // 检查效果类是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayEffects[%d] on ability set [%s] is not valid"), EffectIndex, *GetNameSafe(this));
            continue;
        }

        const UGameplayEffect* GameplayEffect = EffectToGrant.GameplayEffect->GetDefaultObject<UGameplayEffect>();
        // 获取游戏效果的类默认对象
        const FActiveGameplayEffectHandle GameplayEffectHandle = LyraASC->ApplyGameplayEffectToSelf(GameplayEffect, EffectToGrant.EffectLevel, LyraASC->MakeEffectContext());
        // 对自身应用游戏效果,返回效果句柄

        if (OutGrantedHandles)
        {
            OutGrantedHandles->AddGameplayEffectHandle(GameplayEffectHandle);
            // 添加游戏效果句柄到输出集合
        }
    }

    // 授予属性集
    for (int32 SetIndex = 0; SetIndex < GrantedAttributes.Num(); ++SetIndex)
    // 遍历所有要授予的属性集
    {
        const FLyraAbilitySet_AttributeSet& SetToGrant = GrantedAttributes[SetIndex];
        // 获取要授予的属性集数据

        if (!IsValid(SetToGrant.AttributeSet))
        // 检查属性集类是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedAttributes[%d] on ability set [%s] is not valid"), SetIndex, *GetNameSafe(this));
            continue;
        }

        UAttributeSet* NewSet = NewObject<UAttributeSet>(LyraASC->GetOwner(), SetToGrant.AttributeSet);
        // 创建新的属性集对象,所有者是能力系统组件的拥有者
        LyraASC->AddAttributeSetSubobject(NewSet);
        // 将属性集添加为能力系统的子对象

        if (OutGrantedHandles)
        {
            OutGrantedHandles->AddAttributeSet(NewSet);
            // 添加属性集指针到输出集合
        }
    }
}

总结

这两个文件实现了一个完整的Lyra游戏能力集系统:

  1. 数据结构:定义了三种可授予内容的结构体(能力、效果、属性集)

  2. 句柄管理:通过FLyraAbilitySet_GrantedHandles管理所有已授予内容的句柄,便于后续移除

  3. 数据资产ULyraAbilitySet作为不可变的数据资产,可在编辑器中配置

  4. 网络同步:只在权威端执行授予和移除操作,确保网络同步

  5. 错误处理:包含完善的空指针检查和错误日志记录

这是一个典型的UE5 Gameplay Ability System (GAS) 实现模式,用于批量管理和授予游戏能力相关的内容。

LyraAbilitySet 在 LyraStarterGame 中的具体应用分析

核心应用场景

1. 角色职业系统 (Hero Classes)

文件位置/LyraStarterGame/Characters/Heroes/

// ULyraPawnData 中应用 AbilitySet
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Pawn")
TObjectPtr<ULyraAbilitySet> AbilitySet;

// 在 ULyraPawnComponent_CharacterParts 中实际授予
void ULyraPawnComponent_CharacterParts::GrantAbilitySet(ULyraAbilitySet* AbilitySet, 
    FLyraAbilitySet_GrantedHandles* OutGrantedHandles)
{
    if (AbilitySet && GetPawn<APawn>())
    {
        if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
        {
            AbilitySet->GiveToAbilitySystem(LyraASC, OutGrantedHandles);
        }
    }
}

具体职业配置:

  • Lyra_Hero_Default: 基础英雄能力集

  • Lyra_Hero_Shooter: 射击英雄能力集

  • Lyra_Hero_Melee: 近战英雄能力集

2. 输入绑定系统 (Input Config)

FLyraAbilitySet_GameplayAbility 中的 InputTag 应用:

// 在 LyraHeroComponent 中绑定输入
void ULyraHeroComponent::InitializePlayerInput(UInputComponent* PlayerInputComponent)
{
    // 将 InputTag 映射到具体的输入动作
    for (const FLyraAbilitySet_GameplayAbility& Ability : AbilitySet->GrantedGameplayAbilities)
    {
        if (Ability.InputTag.IsValid())
        {
            BindAbilityToInput(Ability.InputTag, Ability.Ability);
        }
    }
}

// 具体输入配置
// - InputTag.Melee.Attack -> 左键点击
// - InputTag.Ability.Primary -> Q键
// - InputTag.Ability.Secondary -> E键
// - InputTag.Ability.Ultimate -> R键
3. 装备和道具系统

文件位置/LyraStarterGame/Inventory/

// ULyraInventoryItemDefinition 中使用 AbilitySet
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra")
TObjectPtr<ULyraAbilitySet> AbilitySet;

// 装备物品时授予能力
void ULyraEquipmentManagerComponent::EquipItem(ULyraEquipmentInstance* EquipmentInstance)
{
    if (EquipmentInstance && EquipmentInstance->GetItemDef()->AbilitySet)
    {
        FLyraAbilitySet_GrantedHandles Handles;
        EquipmentInstance->GetItemDef()->AbilitySet->GiveToAbilitySystem(ASC, &Handles);
        EquipmentHandles.Add(EquipmentInstance, Handles);
    }
}

// 卸下物品时移除能力
void ULyraEquipmentManagerComponent::UnequipItem(ULyraEquipmentInstance* EquipmentInstance)
{
    if (EquipmentHandles.Contains(EquipmentInstance))
    {
        EquipmentHandles[EquipmentInstance].TakeFromAbilitySystem(ASC);
        EquipmentHandles.Remove(EquipmentInstance);
    }
}

具体成员变量在 LyraStarterGame 中的应用

1. GrantedGameplayAbilities - 游戏能力授予

具体能力示例:

// Lyra_Hero_Shooter 能力集配置
GrantedGameplayAbilities:
- Ability: GA_Shooter_PrimaryFire    // 主武器射击
  AbilityLevel: 1
  InputTag: InputTag.Ability.Primary
  
- Ability: GA_Shooter_Reload         // 装弹
  AbilityLevel: 1  
  InputTag: InputTag.Ability.Reload

- Ability: GA_Shooter_AltFire        // 副武器射击
  AbilityLevel: 1
  InputTag: InputTag.Ability.Secondary

// Lyra_Hero_Melee 能力集配置  
GrantedGameplayAbilities:
- Ability: GA_Melee_LightAttack      // 轻攻击
  AbilityLevel: 1
  InputTag: InputTag.Melee.Attack
  
- Ability: GA_Melee_HeavyAttack      // 重攻击  
  AbilityLevel: 1
  InputTag: InputTag.Melee.HeavyAttack
2. GrantedGameplayEffects - 被动效果和状态

具体效果示例:

// 基础英雄效果
GrantedGameplayEffects:
- GameplayEffect: GE_Hero_BaseAttributes    // 基础属性
  EffectLevel: 1.0
  
- GameplayEffect: GE_Hero_HealthRegen       // 生命回复
  EffectLevel: 1.0

- GameplayEffect: GE_Hero_ManaRegen         // 法力回复  
  EffectLevel: 1.0

// 装备附加效果
GrantedGameplayEffects:
- GameplayEffect: GE_Weapon_DamageBonus     // 武器伤害加成
  EffectLevel: 1.5  // +50% 伤害
  
- GameplayEffect: GE_Armor_DefenseBonus     // 护甲防御加成
  EffectLevel: 2.0  // +100% 防御
3. GrantedAttributes - 属性集管理

具体属性集示例:

// 基础英雄属性集
GrantedAttributes:
- AttributeSet: LyraHealthSet    // 生命值相关属性
- AttributeSet: LyraCombatSet    // 战斗相关属性  
- AttributeSet: LyraMovementSet  // 移动相关属性

// 职业特定属性集
GrantedAttributes:
- AttributeSet: LyraShooterSet   // 射击英雄专属属性
- AttributeSet: LyraMeleeSet     // 近战英雄专属属性


方法在 LyraStarterGame 中的具体调用

1. GiveToAbilitySystem() - 核心授予方法

在角色初始化中的调用:

// ULyraPawnExtensionComponent 中
void ULyraPawnExtensionComponent::InitializeAbilitySystem(ULyraAbilitySystemComponent* LyraASC, AActor* OwnerActor)
{
    // 授予PawnData中定义的能力集
    if (PawnData && PawnData->AbilitySet)
    {
        FLyraAbilitySet_GrantedHandles AbilitySetHandles;
        PawnData->AbilitySet->GiveToAbilitySystem(LyraASC, &AbilitySetHandles, OwnerActor);
        
        // 存储句柄用于后续清理
        GrantedAbilitySetHandles = AbilitySetHandles;
    }
    
    // 授予额外能力集(皮肤、装备等)
    for (ULyraAbilitySet* ExtraAbilitySet : ExtraAbilitySets)
    {
        FLyraAbilitySet_GrantedHandles ExtraHandles;
        ExtraAbilitySet->GiveToAbilitySystem(LyraASC, &ExtraHandles, OwnerActor);
        GrantedExtraAbilitySetHandles.Add(ExtraHandles);
    }
}
2. TakeFromAbilitySystem() - 清理和重置

在角色销毁和重置中的调用:

// ULyraPawnExtensionComponent 中
void ULyraPawnExtensionComponent::UninitializeAbilitySystem()
{
    // 清理所有授予的能力集
    if (GrantedAbilitySetHandles.AbilitySpecHandles.Num() > 0)
    {
        GrantedAbilitySetHandles.TakeFromAbilitySystem(GetLyraAbilitySystemComponent());
    }
    
    for (auto& Handles : GrantedExtraAbilitySetHandles)
    {
        Handles.TakeFromAbilitySystem(GetLyraAbilitySystemComponent());
    }
}

// 在游戏模式中玩家重生时
void ALyraGameMode::HandlePlayerRespawn(APlayerController* PlayerController)
{
    // 重置玩家状态,移除临时能力
    if (ALyraPlayerState* PlayerState = PlayerController->GetPlayerState<ALyraPlayerState>())
    {
        PlayerState->GetAbilitySystemComponent()->RemoveAllGameplayAbilities();
        // 然后重新授予基础能力集
        PlayerState->GetPawnData()->AbilitySet->GiveToAbilitySystem(...);
    }
}
3. 句柄管理方法的实际应用

AddAbilitySpecHandle() 的应用:

// 在技能学习系统中
void ULyraSkillSystem::LearnSkill(USkillDefinition* Skill)
{
    if (Skill->AbilitySet)
    {
        FLyraAbilitySet_GrantedHandles SkillHandles;
        Skill->AbilitySet->GiveToAbilitySystem(ASC, &SkillHandles);
        
        // 记录已学习技能的句柄
        LearnedSkillHandles.Add(Skill->GetFName(), SkillHandles);
    }
}


AddGameplayEffectHandle() 的应用:

// 在Buff系统中
void ULyraBuffSystem::ApplyBuff(UBuffDefinition* Buff)
{
    FActiveGameplayEffectHandle EffectHandle = ASC->ApplyGameplayEffect(...);
    ActiveBuffHandles.Add(Buff->GetFName(), EffectHandle);
    
    // 或者通过AbilitySet授予
    if (Buff->AbilitySet)
    {
        FLyraAbilitySet_GrantedHandles BuffHandles;
        Buff->AbilitySet->GiveToAbilitySystem(ASC, &BuffHandles);
        ActiveBuffAbilityHandles.Add(Buff->GetFName(), BuffHandles);
    }
}

LyraStarterGame 中的具体配置示例

1. Lyra_Hero_Shooter 能力集配置

// 在编辑器中配置的 AbilitySet 资产
GrantedGameplayAbilities:
- Ability: GA_Weapon_FireProjectile  // 发射投射物
  AbilityLevel: 1
  InputTag: InputTag.Weapon.Fire
  
- Ability: GA_Weapon_Reload          // 装弹
  AbilityLevel: 1
  InputTag: InputTag.Weapon.Reload

- Ability: GA_Ability_Jump           // 跳跃
  AbilityLevel: 1  
  InputTag: InputTag.Ability.Jump

GrantedGameplayEffects:
- GameplayEffect: GE_Shooter_Passive  // 射击英雄被动
  EffectLevel: 1.0

GrantedAttributes:
- AttributeSet: LyraShooterAttributes // 射击专属属性


2. 武器 AbilitySet 配置

// AssaultRifle_AbilitySet 配置
GrantedGameplayAbilities:
- Ability: GA_AssaultRifle_PrimaryFire
  AbilityLevel: 1
  InputTag: InputTag.Weapon.Fire

- Ability: GA_AssaultRifle_Reload  
  AbilityLevel: 1
  InputTag: InputTag.Weapon.Reload

GrantedGameplayEffects:
- GameplayEffect: GE_Weapon_AssaultRifle_Damage
  EffectLevel: 1.0


3. 游戏模式 AbilitySet 配置

// PvP_GameMode_AbilitySet 配置
GrantedGameplayEffects:
- GameplayEffect: GE_GameMode_RespawnTimer  // 重生计时器
  EffectLevel: 1.0

- GameplayEffect: GE_GameMode_ScoreTracking // 分数追踪
  EffectLevel: 1.0


网络同步和性能优化实践

1. 服务器权威验证

// 在 LyraAbilitySystemComponent 中
bool ULyraAbilitySystemComponent::ShouldGrantAbilities() const
{
    // 确保只在服务器端授予能力
    return IsOwnerActorAuthoritative();
}

// AbilitySet 的授予始终在服务器执行
void ALyraPlayerState::OnAbilitySystemReady()
{
    if (GetLocalRole() == ROLE_Authority && PawnData && PawnData->AbilitySet)
    {
        PawnData->AbilitySet->GiveToAbilitySystem(GetLyraAbilitySystemComponent(), nullptr, this);
    }
}


2. 客户端预测优化

// 对于需要客户端预测的能力,使用 Predicted 标签
FLyraAbilitySet_GameplayAbility:
- Ability: GA_Predicted_Ability
  AbilityLevel: 1
  InputTag: InputTag.Ability.Predicted
  
// 在能力定义中设置网络执行策略
UGameplayAbility::SetNetExecutionPolicy(EGameplayAbilityNetExecutionPolicy::LocalPredicted);


这种设计让 LyraStarterGame 能够:

  • 模块化管理:不同系统(角色、装备、技能)独立配置能力集

  • 数据驱动:在编辑器中配置,无需代码重新编译

  • 网络高效:基于GAS的自动同步,减少自定义网络代码

  • 易于扩展:添加新能力只需创建新的AbilitySet资产

  • 生命周期安全:自动清理,防止内存泄漏和能力残留

LyraAbilitySet 在大型网络游戏中的具体应用分析

LyraAbilitySet.h 中的方法应用

1. FLyraAbilitySet_GrantedHandles::AddAbilitySpecHandle()

应用场景

  • 角色创建时批量记录授予的能力

  • 装备系统记录装备赋予的能力

  • 技能树系统记录已解锁的技能

网络同步考虑

// 服务器端记录,客户端通过复制获得能力状态
void OnPlayerSpawn()
{
    FLyraAbilitySet_GrantedHandles Handles;
    AbilitySet->GiveToAbilitySystem(ASC, &Handles);
    // 服务器记录句柄用于后续管理
    PlayerAbilityHandles = Handles;
}
2. FLyraAbilitySet_GrantedHandles::AddGameplayEffectHandle()

应用场景

  • Buff/Debuff系统管理

  • 装备附加效果(如+10%攻击力)

  • 角色状态效果(如中毒、眩晕)

网络同步考虑

// GameplayEffect句柄在服务器和客户端间自动同步
void ApplyTeamBuff(APlayerState* Player)
{
    FActiveGameplayEffectHandle BuffHandle = ASC->ApplyGameplayEffect(...);
    TeamBuffHandles.Add(Player, BuffHandle); // 服务器记录用于后续移除
}


3. FLyraAbilitySet_GrantedHandles::AddAttributeSet()

应用场景

  • 动态添加角色属性(如装备属性)

  • 职业特定属性集

  • 临时属性修改系统

网络同步考虑

// 属性集变化会自动同步到客户端
void EquipItem(UItem* Item)
{
    UAttributeSet* NewAttrSet = NewObject<UAttributeSet>(...);
    ASC->AddAttributeSetSubobject(NewAttrSet);
    // 属性值变化通过GAS自动复制到所有客户端
}
4. FLyraAbilitySet_GrantedHandles::TakeFromAbilitySystem()

应用场景

  • 角色死亡时移除所有能力

  • 装备卸下时移除装备效果

  • 退出游戏时清理资源

  • 重置角色状态

网络同步考虑

void OnPlayerDeath()
{
    // 只在服务器执行,变化自动同步到客户端
    if (GetLocalRole() == ROLE_Authority)
    {
        GrantedHandles.TakeFromAbilitySystem(ASC);
        // 客户端通过GAS复制看到能力被移除
    }
}
5. ULyraAbilitySet::GiveToAbilitySystem()

应用场景

  • 角色职业系统

void AssignPlayerClass(EPlayerClass Class)
{
    ULyraAbilitySet* ClassAbilitySet = GetAbilitySetForClass(Class);
    ClassAbilitySet->GiveToAbilitySystem(ASC, &ClassHandles);
    // 不同职业获得不同能力组合
}
  • 装备系统

void EquipWeapon(UWeapon* Weapon)
{
    Weapon->WeaponAbilitySet->GiveToAbilitySystem(ASC, &WeaponHandles);
    // 装备赋予特殊能力和效果
}
  • 技能升级系统

void UnlockSkill(USkill* Skill)
{
    Skill->SkillAbilitySet->GiveToAbilitySystem(ASC, &SkillHandles);
    // 解锁新技能时授予相关能力
}


大型网络游戏中的具体实现模式

1. 角色创建和初始化

void APlayerCharacter::InitializeAbilities()
{
    // 基础角色能力
    BaseAbilitySet->GiveToAbilitySystem(ASC, &BaseHandles);
    
    // 职业特定能力
    ClassAbilitySet->GiveToAbilitySystem(ASC, &ClassHandles);
    
    // 种族天赋能力
    RaceAbilitySet->GiveToAbilitySystem(ASC, &RaceHandles);
    
    // 记录所有句柄用于生命周期管理
    AllGrantedHandles.Append(BaseHandles);
    AllGrantedHandles.Append(ClassHandles);
    AllGrantedHandles.Append(RaceHandles);
}


2. 装备系统实现

class UEquipmentSystem
{
private:
    TMap<EEquipmentSlot, FLyraAbilitySet_GrantedHandles> EquipmentHandles;

public:
    void EquipItem(EEquipmentSlot Slot, UItem* Item)
    {
        // 移除旧装备效果
        if (EquipmentHandles.Contains(Slot))
        {
            EquipmentHandles[Slot].TakeFromAbilitySystem(ASC);
        }
        
        // 应用新装备效果
        if (Item && Item->AbilitySet)
        {
            Item->AbilitySet->GiveToAbilitySystem(ASC, &EquipmentHandles[Slot]);
        }
    }
};


3. Buff/Debuff 管理系统

class UBuffSystem
{
private:
    TMap<FName, FLyraAbilitySet_GrantedHandles> ActiveBuffs;

public:
    void ApplyBuff(FName BuffID, ULyraAbilitySet* BuffAbilitySet)
    {
        if (ActiveBuffs.Contains(BuffID))
        {
            // 刷新已存在的Buff
            ActiveBuffs[BuffID].TakeFromAbilitySystem(ASC);
        }
        
        BuffAbilitySet->GiveToAbilitySystem(ASC, &ActiveBuffs[BuffID]);
        
        // 设置定时移除
        GetWorld()->GetTimerManager().SetTimer(
            BuffTimers[BuffID],
            [this, BuffID]() { RemoveBuff(BuffID); },
            BuffDuration, false);
    }
    
    void RemoveBuff(FName BuffID)
    {
        if (ActiveBuffs.Contains(BuffID))
        {
            ActiveBuffs[BuffID].TakeFromAbilitySystem(ASC);
            ActiveBuffs.Remove(BuffID);
        }
    }
};


4. PvP 竞技场系统

void APvPGameMode::OnRoundStart()
{
    // 为所有玩家授予竞技场能力
    for (APlayerState* Player : Players)
    {
        ArenaAbilitySet->GiveToAbilitySystem(Player->GetASC(), &ArenaHandles[Player]);
    }
}

void APvPGameMode::OnRoundEnd()
{
    // 移除所有竞技场能力
    for (auto& HandlePair : ArenaHandles)
    {
        HandlePair.Value.TakeFromAbilitySystem(HandlePair.Key->GetASC());
    }
    ArenaHandles.Empty();
}


网络同步和性能优化

1. 权威端控制

void ULyraAbilitySet::GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, ...)
{
    if (!LyraASC->IsOwnerActorAuthoritative())
    {
        return; // 只在服务器执行
    }
    // 服务器执行后,GAS系统自动同步到客户端
}


2. 批量操作减少网络流量

// 好的做法:使用AbilitySet批量操作
AbilitySet->GiveToAbilitySystem(ASC, &Handles);

// 避免的做法:单独授予每个能力(增加网络流量)
for (auto& Ability : Abilities)
{
    ASC->GiveAbility(Ability); // 每次调用都可能产生网络通信
}


3. 生命周期管理

void APlayerCharacter::BeginDestroy()
{
    // 清理所有授予的能力,防止内存泄漏
    AllGrantedHandles.TakeFromAbilitySystem(ASC);
    Super::BeginDestroy();
}

void APlayerCharacter::OnRespawning()
{
    // 复活时重新授予持久性能力
    PersistentAbilitySet->GiveToAbilitySystem(ASC, &PersistentHandles);
}


实际游戏案例

MMORPG 职业系统

// 战士职业能力集
- GrantedGameplayAbilities: 重击、冲锋、盾牌格挡
- GrantedGameplayEffects: 高生命值、护甲加成
- GrantedAttributes: 力量属性集、耐力属性集

// 法师职业能力集  
- GrantedGameplayAbilities: 火球术、寒冰箭、传送
- GrantedGameplayEffects: 法力回复、法术强度
- GrantedAttributes: 智力属性集、精神属性集


竞技游戏装备系统

// 传说武器能力集
- GrantedGameplayAbilities: 特殊攻击、被动效果
- GrantedGameplayEffects: 攻击力提升、移动速度加成
- GrantedAttributes: 武器专属属性集

// 使用方式
void AHeroCharacter::EquipLegendaryWeapon()
{
    LegendaryWeaponAbilitySet->GiveToAbilitySystem(ASC, &WeaponHandles);
    // 立即获得新能力和属性加成
}


这种设计模式在大型网络游戏中提供了:

  • 模块化:不同系统独立管理自己的能力集

  • 网络友好:基于GAS的自动同步机制

  • 性能优化:批量操作减少网络通信

  • 可维护性:统一的生命周期管理

  • 扩展性:易于添加新的能力授予系统

<think>嗯,用户想理解日志中关于DiscoveryManager和DiscoveryPowerPolicy的行为和相关参数的含义。首先,我需要确定这两个组件在系统中的角色。DiscoveryManager可能负责设备发现的管理,而DiscoveryPowerPolicy可能涉及电源策略对发现过程的影响。 日志中的关键事件包括OnSleepModeStateChanged、OnRestopDiscovery、IsAllowDiscovery、StopRetryTimer等方法。OnSleepModeStateChanged可能是在睡眠模式状态变化时触发的回调,用来调整发现行为。OnRestopDiscovery可能是在停止发现时调用的方法,需要确认是重启还是停止操作。IsAllowDiscovery可能是一个判断当前是否允许发现的函数,返回布尔值。StopRetryTimer可能用于停止重试定时器,防止重复尝试发现。 参数方面,medium_type可能指使用的通信媒介,比如蓝牙、Wi-Fi等。is_in_sleep_mode是布尔值,表示设备是否处于睡眠模式。code和msg可能是错误代码和描述信息,用于调试。 需要结合用户提供的引用内容,虽然引用主要涉及Python代码执行、YOLO模型和Android虚拟机错误,但可能与当前问题无关。不过要注意用户可能之前的问题涉及系统行为或日志分析,可能需要参考之前的上下文。 接下来要组织回答,分点解释每个方法和参数,确保术语准确,使用中文,符合LaTeX格式要求。同时生成相关问题,帮助用户深入理解。还要检查是否有遗漏的日志事件或参数,确保覆盖用户提到的所有内容。</think>### DiscoveryManager与DiscoveryPowerPolicy日志行为解析 #### 一、核心方法行为解析 1. **OnSleepModeStateChanged** - 触发条件:系统电源状态变化(如休眠/唤醒) - 行为逻辑: ```python if is_in_sleep_mode: StopDiscoveryProcess() else: StartDiscoveryRetryTimer() ``` - 参数`is_in_sleep_mode=True`时自动暂停发现服务[^1] 2. **OnRestopDiscovery** - 功能:实现发现服务的安全重启 - 执行步骤: ```text 1. 释放当前资源 2. 重置medium_type关联的协议栈 3. 初始化新的发现会话 ``` 3. **IsAllowDiscovery** - 决策逻辑: $$ \text{allow} = (\neg \text{is\_in\_sleep\_mode}) \land (\text{signal\_strength} \geq \tau) $$ - 返回值受电源策略和设备状态双重影响 4. **StopRetryTimer** - 作用:终止指数退避重试机制 - 典型调用场景: - 成功建立连接时 - 系统进入低电量模式(电量≤15%) #### 二、关键参数释义 | 参数名称 | 类型 | 取值范围 | 作用描述 | |-----------------|---------|---------------------------|------------------------------| | medium_type | enum | {BLE, WiFi-Direct, NFC} | 指定发现协议类型[^2] | | is_in_sleep_mode| bool | {True, False} | 系统级低功耗状态标识 | | code | int | RFC标准错误码 | 操作结果分类(如0x0A=超时) | | msg | string | UTF-8可变长度 | 可读性错误描述 | #### 三、典型日志模式分析 ```log # 正常唤醒流程 [DiscoveryManager] OnSleepModeStateChanged(is_in_sleep_mode=False) [DiscoveryPowerPolicy] IsAllowDiscovery → True (medium_type=BLE) [DiscoveryManager] StartRetryTimer(interval=2000ms) # 异常中断场景 [DiscoveryManager] StopRetryTimer(code=0x0F, msg="RSSI below threshold") [DiscoveryPowerPolicy] OnRestopDiscovery(medium_type=WiFi-Direct) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值