其他分享
首页 > 其他分享> > UE的GAS学习过程

UE的GAS学习过程

作者:互联网

参考文档:https://github.com/BillEliot/GASDocumentation_Chinese

GAS即GameplayAbilitySystem,其核心为AbilitySystemComponent组件。

其实现由技能系统组件(AbilitySystemComponent),调用技能(Ability),技能中实现具体逻辑,由效果(Effect)对其属性(Attribute)进行修改。

开始

UCLASS()
class ABILTYDEMO_API AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AMyCharacter();
	UPROPERTY()
	UAbilitySystemComponent* AbilitySystemComponent;
	UPROPERTY()
	UMyAttributeSet* AbilitySet;
	UPROPERTY(BlueprintReadWrite,EditAnywhere,Category="Ability")
	TSubclassOf<UGameplayAbility> Ability;
	
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;
};

IAbilitySystemInterface需要去继承这个借口,并实现virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override;方法

同时需要申明UAbilitySystemComponent* AbilitySystemComponent;GetAbilitySystemComponent()返回的对象便是该组件。

对于技能属性UMyAttributeSet* AbilitySet;会自动加载进AbilitySystemaComponent中。

技能属性集需要继承UAttributeSet

一下为UMyAttributeSet类的具体

 #define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
 	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
 	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
 	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
 	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

UCLASS()
class ABILTYDEMO_API UMyAttributeSet : public UAttributeSet
{
	GENERATED_BODY()

public:
	UMyAttributeSet();
	UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health)
	FGameplayAttributeData Health;
	UFUNCTION()
	virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
	ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
	virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
	virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};

对于上面的宏,在Attribute.h的源码中有解释,其作用是生成对应的GetValue、SetValue、InitValue、GetAttribute方法


/**
 * This defines a set of helper functions for accessing and initializing attributes, to avoid having to manually write these functions.
 * It would creates the following functions, for attribute Health
 *
 *	static FGameplayAttribute UMyHealthSet::GetHealthAttribute();
 *	FORCEINLINE float UMyHealthSet::GetHealth() const;
 *	FORCEINLINE void UMyHealthSet::SetHealth(float NewVal);
 *	FORCEINLINE void UMyHealthSet::InitHealth(float NewVal);
 *
 * To use this in your game you can define something like this, and then add game-specific functions as necessary:
 * 
 *	#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
 *	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
 *	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
 *	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
 *	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
 * 
 *	ATTRIBUTE_ACCESSORS(UMyHealthSet, Health)
 */

#define GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	static FGameplayAttribute Get##PropertyName##Attribute() \
	{ \
		static FProperty* Prop = FindFieldChecked<FProperty>(ClassName::StaticClass(), GET_MEMBER_NAME_CHECKED(ClassName, PropertyName)); \
		return Prop; \
	}

#define GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	FORCEINLINE float Get##PropertyName() const \
	{ \
		return PropertyName.GetCurrentValue(); \
	}

#define GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	FORCEINLINE void Set##PropertyName(float NewVal) \
	{ \
		UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent(); \
		if (ensure(AbilityComp)) \
		{ \
			AbilityComp->SetNumericAttributeBase(Get##PropertyName##Attribute(), NewVal); \
		}; \
	}

#define GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName) \
	FORCEINLINE void Init##PropertyName(float NewVal) \
	{ \
		PropertyName.SetBaseValue(NewVal); \
		PropertyName.SetCurrentValue(NewVal); \
	}

现在已经有了技能组件和技能属性,接下来尝试让他去执行技能。

UCLASS()
class ABILTYDEMO_API UMyGameplayAbility : public UGameplayAbility
{
	GENERATED_BODY()

public:

	UMyGameplayAbility();
	UPROPERTY(EditAnywhere,BlueprintReadWrite)
	TSubclassOf<UGameplayEffect> Effect;
	
	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
protected:
	virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
		const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
};

技能需要继承UGameplayAbility对其ActivateAbility进行重写,在里面实现具体的逻辑

void UMyGameplayAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
                                         const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo,
                                         const FGameplayEventData* TriggerEventData)
{
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
	UE_LOG(LogTemp, Log, TEXT("play Ability In Ability"));
	ApplyGameplayEffectSpecToOwner(Handle, ActorInfo, ActivationInfo, MakeOutgoingGameplayEffectSpec(Effect));//激活技能
}

如何调用技能

GameplayAbilitySpecHandle =  AbilitySystemComponent->GiveAbility(Ability.GetDefaultObject());//对技能组件授予技能
AbilitySystemComponent->TryActivateAbility(GameplayAbilitySpecHandle);//激活系统技能

系统激活技能是会自动调用ActivateAbility以及EndAbility

Effect为技能效果,基于配置,由蓝图来写,继承GamePlayEffect,这东西下次再讲。

image-20220327171553846

将该类引用传入C++进行调用,主要是修改系统组件具备的属性。

标签:const,GAMEPLAYATTRIBUTE,PropertyName,GAS,virtual,学习,UE,void,技能
来源: https://www.cnblogs.com/ldnanchao/p/16063553.html