注:1.这个分类是按照源码里的注释分类的
2.本篇是通读并给出一些注释形式的,并不涉及结构性的分析
3.看之前要对UE的GAS系统的定义有初步了解
4.因为都是接口函数,有些没细看的研究那一部分的时候会细看
15 GetGameplayEffectMagnitude
注释的大致翻译:原始访问器,用于查询游戏效果的强度,但结果并不总是准确的。外部代码(如UI等)如何询问类似 “这个游戏效果会将我的伤害修改多少” 这样的问题。我们最有可能在后端捕获这种情况——在伤害应用时,我们可以获取一个完整的转储/历史记录,了解数字是如何达到当前状态的。但即便如此,我们可能仍然需要像下面这样的轮询方法(我的伤害会是多少)。
这个注释说的还是挺清楚的,我们直接去看实现
/**
* Raw accessor to ask the magnitude of a gameplay effect, not necessarily always correct. How should outside code (UI, etc) ask things like 'how much is this gameplay effect modifying my damage by'
* (most likely we want to catch this on the backend - when damage is applied we can get a full dump/history of how the number got to where it is. But still we may need polling methods like below (how much would my damage be)
*/
UFUNCTION(BlueprintCallable, Category = GameplayEffects)
float GetGameplayEffectMagnitude(FActiveGameplayEffectHandle Handle, FGameplayAttribute Attribute) const;
调用下一级
ActiveGameplayEffects.GetGameplayEffectMagnitude(Handle, Attribute);
具体就是遍历容器找到指定Handle的指定Attribute,返回计算后的幅值
float FActiveGameplayEffectsContainer::GetGameplayEffectMagnitude(FActiveGameplayEffectHandle Handle, FGameplayAttribute Attribute) const
{
for (const FActiveGameplayEffect& Effect : this)
{
if (Effect.Handle == Handle)
{
for(int32 ModIdx = 0; ModIdx < Effect.Spec.Modifiers.Num(); ++ModIdx)
{
const FGameplayModifierInfo& ModDef = Effect.Spec.Def->Modifiers[ModIdx];
const FModifierSpec& ModSpec = Effect.Spec.Modifiers[ModIdx];
if (ModDef.Attribute == Attribute)
{
return ModSpec.GetEvaluatedMagnitude();
}
}
}
}
UE_LOG(LogGameplayEffects, Warning, TEXT("GetGameplayEffectMagnitude called with invalid Handle: %s"), *Handle.ToString());
return -1.f;
}
16 GetCurrentStackCount/FindActiveGameplayEffectHandle
返回指定Handle的已经应用的GE的堆叠数量
/** Returns current stack count of an already applied GE */
int32 GetCurrentStackCount(FActiveGameplayEffectHandle Handle) const;
调用了Spec的GetStacckCount,就是直接返回参数
ActiveGE->Spec.GetStackCount();
int32 FGameplayEffectSpec::GetStackCount() const
{
return StackCount;
}
传入GE赋予的GASpecHandle版本的:
/** Returns current stack count of an already applied GE, but given the ability spec handle that was granted by the GE */
int32 GetCurrentStackCount(FGameplayAbilitySpecHandle Handle) const;
多了一步找指定GE
FActiveGameplayEffectHandle GEHandle = FindActiveGameplayEffectHandle(Handle);
这个函数的声明:
/** Gets the GE Handle of the GE that granted the passed in Ability */
FActiveGameplayEffectHandle FindActiveGameplayEffectHandle(FGameplayAbilitySpecHandle Handle) const;
具体实现:
遍历ActiveGameplayEffects,在所有赋予的能力中匹配GASpecHandle,找到了就返回对应的GE的Handle
/** Gets the GE Handle of the GE that granted the passed in Ability */
FActiveGameplayEffectHandle UAbilitySystemComponent::FindActiveGameplayEffectHandle(FGameplayAbilitySpecHandle Handle) const
{
for (const FActiveGameplayEffect& ActiveGE : &ActiveGameplayEffects)
{
// Old, deprecated way of handling these (before AbilitiesGameplayEffectComponent):
PRAGMA_DISABLE_DEPRECATION_WARNINGS
for (const FGameplayAbilitySpecDef& AbilitySpecDef : ActiveGE.Spec.GrantedAbilitySpecs)
PRAGMA_ENABLE_DEPRECATION_WARNINGS
{
if (AbilitySpecDef.AssignedHandle == Handle)
{
return ActiveGE.Handle;
}
}
// Where AbilitiesGameplayEffectComponent stores its data
if (ActiveGE.GrantedAbilityHandles.Contains(Handle))
{
return ActiveGE.Handle;
}
}
return FActiveGameplayEffectHandle();
}
17 GetActiveGEDebugString
打印信息的函数,没啥好说的
FString UAbilitySystemComponent::GetActiveGEDebugString(FActiveGameplayEffectHandle Handle) const
{
FString Str;
if (const FActiveGameplayEffect* ActiveGE = ActiveGameplayEffects.GetActiveGameplayEffect(Handle))
{
Str = FString::Printf(TEXT("%s - (Level: %.2f. Stacks: %d)"), *ActiveGE->Spec.Def->GetName(), ActiveGE->Spec.GetLevel(), ActiveGE->Spec.GetStackCount());
}
return Str;
}
18 GetActiveGameplayEffect
根据FActiveGameplayEffectHandle找FActiveGameplayEffect
/** Returns const pointer to the actual active gameplay effect structure */
const FActiveGameplayEffect* GetActiveGameplayEffect(const FActiveGameplayEffectHandle Handle) const;
追溯到GE:
FActiveGameplayEffect* FActiveGameplayEffectsContainer::GetActiveGameplayEffect(const FActiveGameplayEffectHandle Handle)
{
for (FActiveGameplayEffect& Effect : this)
{
if (Effect.Handle == Handle)
{
return &Effect;
}
}
return nullptr;
}
19 GetActiveGameplayEffects
返回ASC上所有的active gameplay effects
/** Returns all active gameplay effects on this ASC */
const FActiveGameplayEffectsContainer& GetActiveGameplayEffects() const;
就一行,直接返回容器:
const FActiveGameplayEffectsContainer& UAbilitySystemComponent::GetActiveGameplayEffects() const
{
return ActiveGameplayEffects;
}
20 GetGameplayEffecctCDO
通过Handle返回对应的ClassDefaultObject
声明:
/** Returns a const pointer to the gameplay effect CDO associated with an active handle. */
const UGameplayEffect* GetGameplayEffectCDO(const FActiveGameplayEffectHandle Handle) const;
实现: 找到对应的ActiveGE返回Spec.Def
const UGameplayEffect* UAbilitySystemComponent::GetGameplayEffectCDO(const FActiveGameplayEffectHandle Handle) const
{
// get the active gameplay effect struct
const FActiveGameplayEffect* ActiveGE = GetActiveGameplayEffect(Handle);
if (ActiveGE)
{
// return the spec's CDO
return ActiveGE->Spec.Def;
}
// active effect not found
return nullptr;
}
21 GetGameplayEffectSourceTagsFromHandle/GetGameplayEffectTargetTagsFromHandle
通过接口追溯一下实现如下:
通过Handle获取Source/Target的标签
//还没考虑tag变化
const FGameplayTagContainer* FActiveGameplayEffectsContainer::GetGameplayEffectSourceTagsFromHandle(FActiveGameplayEffectHandle Handle) const
{
// @todo: Need to consider this with tag changes
for (const FActiveGameplayEffect& Effect : this)
{
if (Effect.Handle == Handle)
{
return Effect.Spec.CapturedSourceTags.GetAggregatedTags();
}
}
return nullptr;
}
22 CaptureAttributeForGameplayEffect
先确保实际有这个属性,再调用ActiveGameplayEffects的Capture函数
void UAbilitySystemComponent::CaptureAttributeForGameplayEffect(OUT FGameplayEffectAttributeCaptureSpec& OutCaptureSpec)
{
// Verify the capture is happening on an attribute the component actually has a set for; if not, can't capture the value
const FGameplayAttribute& AttributeToCapture = OutCaptureSpec.BackingDefinition.AttributeToCapture;
if (AttributeToCapture.IsValid() && (AttributeToCapture.IsSystemAttribute() || GetAttributeSubobject(AttributeToCapture.GetAttributeSetClass())))
{
ActiveGameplayEffects.CaptureAttributeForGameplayEffect(OutCaptureSpec);
}
}
GE中的实现:
要先获取对应的AttributeAggregator,管理属性用的
通过bSnapshot选择获取快照还是直接赋值
void FActiveGameplayEffectsContainer::CaptureAttributeForGameplayEffect(OUT FGameplayEffectAttributeCaptureSpec& OutCaptureSpec)
{
FAggregatorRef& AttributeAggregator = FindOrCreateAttributeAggregator(OutCaptureSpec.BackingDefinition.AttributeToCapture);
if (OutCaptureSpec.BackingDefinition.bSnapshot)
{
OutCaptureSpec.AttributeAggregator.TakeSnapshotOf(AttributeAggregator);
}
else
{
OutCaptureSpec.AttributeAggregator = AttributeAggregator;
}
}