UE学习日志#9 GAS--ASC源码简要分析7 GameplayEffects: Primary outward facing API for other systems P3

注: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;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值