ActionRPG-3-RPGGameAbility

Posted ikun-proto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ActionRPG-3-RPGGameAbility相关的知识,希望对你有一定的参考价值。

#pragma once

#include "ActionRPG.h"
#include "Abilities/GameplayAbility.h"
#include "Abilities/RPGAbilityTypes.h"
#include "RPGGameplayAbility.generated.h"

/**
 * Subclass of ability blueprint type with game-specific data
 * This class uses GameplayEffectContainers to allow easier execution of gameplay effects based on a triggering tag
 * Most games will need to implement a subclass to support their game-specific code
 */
UCLASS()
class ACTIONRPG_API URPGGameplayAbility : public UGameplayAbility

	GENERATED_BODY()

public:
	// Constructor and overrides
	URPGGameplayAbility();

	/**
     * Map of gameplay tags to gameplay effect containers
     * 游戏标签到游戏效果容器的map
     */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = GameplayEffects)
	TMap<FGameplayTag, FRPGGameplayEffectContainer> EffectContainerMap;

	/**
     * @brief Make gameplay effect container spec to be applied later, using the passed in container
     *        根据给定的GE容器创建GE容器的规范
     * @param Container 给定的容器,包含一组GE
     * @param EventData 传递的游戏事件的数据
     */
	UFUNCTION(BlueprintCallable, Category = Ability, meta=(AutoCreateRefTerm = "EventData"))
	virtual FRPGGameplayEffectContainerSpec MakeEffectContainerSpecFromContainer(const FRPGGameplayEffectContainer& Container, const FGameplayEventData& EventData, int32 OverrideGameplayLevel = -1);

	/**
     * @brief Search for and make a gameplay effect container spec to be applied later, from the EffectContainerMap
     *        从EffectContainerMap中搜索并制作稍后应用的游戏效果容器规范
     */
	UFUNCTION(BlueprintCallable, Category = Ability, meta = (AutoCreateRefTerm = "EventData"))
	virtual FRPGGameplayEffectContainerSpec MakeEffectContainerSpec(FGameplayTag ContainerTag, const FGameplayEventData& EventData, int32 OverrideGameplayLevel = -1);

	/**
     * @brief Applies a gameplay effect container spec that was previously created
     *        应用先前创建的游戏效果容器规范
     */
	UFUNCTION(BlueprintCallable, Category = Ability)
	virtual TArray<FActiveGameplayEffectHandle> ApplyEffectContainerSpec(const FRPGGameplayEffectContainerSpec& ContainerSpec);

	/**
     * @brief Applies a gameplay effect container, by creating and then applying the spec
     *        通过创建并应用规范,应用游戏效果容器
     */
	UFUNCTION(BlueprintCallable, Category = Ability, meta = (AutoCreateRefTerm = "EventData"))
	virtual TArray<FActiveGameplayEffectHandle> ApplyEffectContainer(FGameplayTag ContainerTag, const FGameplayEventData& EventData, int32 OverrideGameplayLevel = -1);
;

 

#include "Abilities/RPGGameplayAbility.h"
#include "Abilities/RPGAbilitySystemComponent.h"
#include "Abilities/RPGTargetType.h"
#include "RPGCharacterBase.h"

URPGGameplayAbility::URPGGameplayAbility() 

FRPGGameplayEffectContainerSpec URPGGameplayAbility::MakeEffectContainerSpecFromContainer(const FRPGGameplayEffectContainer& Container,
                                                                                          const FGameplayEventData& EventData,
                                                                                          int32 OverrideGameplayLevel) 
	// First figure out our actor info
	FRPGGameplayEffectContainerSpec ReturnSpec;
	AActor* OwningActor = GetOwningActorFromActorInfo();
	ARPGCharacterBase* OwningCharacter = Cast<ARPGCharacterBase>(OwningActor);
	URPGAbilitySystemComponent* OwningASC = URPGAbilitySystemComponent::GetAbilitySystemComponentFromActor(OwningActor);

	if (OwningASC) 
		// If we have a target type, run the targeting logic. This is optional, targets can be added later
        // // 如果我们有一个目标类型,那么运行目标逻辑。这是可选的,以后可以添加目标
		if (Container.TargetType.Get()) 
			TArray<FHitResult> HitResults;
			TArray<AActor*> TargetActors;
			const URPGTargetType* TargetTypeCDO = Container.TargetType.GetDefaultObject();
			AActor* AvatarActor = GetAvatarActorFromActorInfo();
			TargetTypeCDO->GetTargets(OwningCharacter, AvatarActor, EventData, HitResults, TargetActors);
			ReturnSpec.AddTargets(HitResults, TargetActors);
		
		// If we don\'t have an override level, use the default on the ability itself
        // 如果我们没有覆盖级别,请对功能本身使用默认级别
		if (OverrideGameplayLevel == INDEX_NONE) 
			OverrideGameplayLevel = OverrideGameplayLevel = this->GetAbilityLevel(); //OwningASC->GetDefaultAbilityLevel();
		
		// Build GameplayEffectSpecs for each applied effect
        // 为每个应用的效果构建GESpecs
		for (const TSubclassOf<UGameplayEffect>& EffectClass : Container.TargetGameplayEffectClasses)
		
			ReturnSpec.TargetGameplayEffectSpecs.Add(MakeOutgoingGameplayEffectSpec(EffectClass, OverrideGameplayLevel));
		
	
	return ReturnSpec;


FRPGGameplayEffectContainerSpec URPGGameplayAbility::MakeEffectContainerSpec(FGameplayTag ContainerTag,
                                                                             const FGameplayEventData& EventData,
                                                                             int32 OverrideGameplayLevel) 
	FRPGGameplayEffectContainer* FoundContainer = EffectContainerMap.Find(ContainerTag);

	if (FoundContainer)
	
		return MakeEffectContainerSpecFromContainer(*FoundContainer, EventData, OverrideGameplayLevel);
	
	return FRPGGameplayEffectContainerSpec();


TArray<FActiveGameplayEffectHandle> URPGGameplayAbility::ApplyEffectContainerSpec(const FRPGGameplayEffectContainerSpec& ContainerSpec) 
	TArray<FActiveGameplayEffectHandle> AllEffects;
	// Iterate list of effect specs and apply them to their target data
    // 迭代效果规格列表,并将其应用于目标数据
	for (const FGameplayEffectSpecHandle& SpecHandle : ContainerSpec.TargetGameplayEffectSpecs) 
		AllEffects.Append(K2_ApplyGameplayEffectSpecToTarget(SpecHandle, ContainerSpec.TargetData));
	
	return AllEffects;


TArray<FActiveGameplayEffectHandle> URPGGameplayAbility::ApplyEffectContainer(FGameplayTag ContainerTag,
                                                                              const FGameplayEventData& EventData,
                                                                              int32 OverrideGameplayLevel) 
	FRPGGameplayEffectContainerSpec Spec = MakeEffectContainerSpec(ContainerTag, EventData, OverrideGameplayLevel);
	return ApplyEffectContainerSpec(Spec);

 

NLP-Word Embedding-Attention机制

参考技术A

attention机制是个坑。
要明白attention机制,首先要明白seq2seq
要明白seq2sql,首先要明白RNN
要明白RNN,首先要明白MLP和BP算法
这是attention机制的前坑

明白attention机制后,要明白self-attention,以及attention在诸多领域的应用
明白self-attention后,要明白Transformer
明白transformer后,要明白Bert
这是attention机制的后坑

即一个序列生成另一个序列。最直观的就是机器翻译,一句英文翻译成一句中文。或者应答,问一句答一句。
模型结构:输入数据连接一个 encoder(编码器) 得到编码输出又称中间状态 C 然后连接到一个 decoder(解码器) 最后解码器的输出作为模型输出

也可以发现,RNN星球的外星人,执着于吃自己的隐层状态h(x),同时,其隐层状态可以继续计算得到输出y。当然,他们也会去吃y,当手头没有输入时他们会把前一个y当输入吃掉,就像小D。当手头有输入时,他们可以不吃y而吃输入。就像小E。至于为什么这样,可能是他们当地人的习惯吧,总得有点下shit菜不是。

小E和小D是RNN星球的外星小伙伴,这个大家都知道了
小E吃了一筐水果小D来了发现没了很不开心,这个大家都知道了
当小D骄傲的说出小E具体吃了什么时,他们发现,小D说的没有那么准。
两人对视一会,发现问题:小D只吃了小E最后的h(an),那最后的h(an)携带的前面的信息就很少了。要改变!要把小E所有的h(ai)都用上!而且,要尽量找到对应关系,例如预测第一个时,要尽量用到第一个h(a)的信息。

具体是怎么做的呢?
小D是这么想的,首先,让小E把他拉的所有h(a)都给他。即[h(a1),h(a2),h(a3)...h(an)],每个h(ai)都是一个向量,所以这些组成了一个矩阵K
然后,小D每拉出一个h(b)就去这个矩阵分别计算该h(b)和每个h(a)的相关度,得到一系列分数,按照分数大小来组合这些h(a)从而得到一个专属于该h(b)的C。下图中的a即是表示对应的分数

还有一个问题,怎么计算相关度?cos相关度,点乘,皮尔森相关等都可以
最后一个问题,初始的隐藏状态是什么,因为没有用到非attention机制的h(h(an))。老规矩,随机初始化。

所以,attention机制,像是一种配方,根据当前不同位置来调配encoder一系列隐藏状态h(ai)的组合比重,这显然是很有道理的,因为就拿翻译来说,词的顺序往往是对应的。

简言之,encoder获取状态矩阵K,decoder根据每一轮隐藏状态h计算注意力分数获得注意力向量C,拼接h和C获得输出y,y和h进入下一轮decode获得新的h。。。

上一步有个矩阵K,来自encoder。而来自decoder的h类似于一个查询(query)。这个查询分别与K中的不同向量h(a)(key)计算相关度得到分数(score),然后利用分数做权重与对应的h(a)(value)加权求和得到自己想要的结果C。
这里我为什么要写query,key,value呢?是为了讲解self-attention。注意这里key和value都是指h(a)即encoder的状态矩阵。
那如果这个query不来自decoder而来自encoder本身呢?即自己查自己?
有了query,key,value概念之后,就比较好理解self-attention了。
首先,输入的词汇(小E吃的水果也好,翻译中一句话分成的一组词也好)都是要embedding成一个固定长度的向量x才输入模型的。即对于一句话的所有词,组成了一个输入矩阵X。
然后,我们随机生成3个矩阵Q,K,V对应query,key,value
对于一个输入x,
用x点乘Q得到query
用x点乘K得到key
用x点乘V得到value
这样,对于一句话中的所有x,都可以得到对应的query,key,value

有了这些就好办了
每个x,都可以用自己的query去和其他key计算score,然后用该score和对应的其他value来计算自己的注意力向量C。经过这样的计算,x变成了C。

上图中的z即为C。而score到softmax之间的步骤是一些tricks,不用管。

同样,可以多叠加几层self-attention,用同样的操作不同的QKV矩阵由c变成cc,变成ccc
这就是self-attention。

self-attention像是一种向量转换。x变为c,维度没变,值变了。而同时,这种转变又蕴含了x与上下文x之间的关系。rnn也可以实现由x变为另一个向量,同时也考虑了上下文关系,但是,他存在循环神经网络的弊端,无法并行。而self-attention组成的transformer则可以实现并行运算。即,他不需要等待下一个状态h计算出来再计算C,而是直接通过QKV矩阵和当前x计算所得。
那QKV怎么得到?随机初始,训练所得。

https://caicai.science/2018/10/06/attention%E6%80%BB%E8%A7%88/
https://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/
https://zhuanlan.zhihu.com/p/37601161
https://jalammar.github.io/illustrated-transformer/

以上是关于ActionRPG-3-RPGGameAbility的主要内容,如果未能解决你的问题,请参考以下文章