1.构建项目框架
角色类
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "BaseCharacter.generated.h"
class UMiNiAbilitySystemComponent;
class UDataAsset_StartUpDataBase;
class UMiNiAttributeSet;
UCLASS()
class MINIWORLD_API ABaseCharacter : public ACharacter
{
GENERATED_BODY()
public:
ABaseCharacter();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
virtual void PossessedBy(AController* NewController) override;
public:
UFUNCTION(BlueprintCallable)
void CallClientTravel(const FString& Address);
public:
/* 技能系统组件 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AbilitySystem")
UMiNiAbilitySystemComponent* AbilitySystemComponent;
/* 角色的属性配置 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "AbilitySystem")
UMiNiAttributeSet* MiNiAttributeSet;
/* 角色初始化资产 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "CharacterData")
TSoftObjectPtr<UDataAsset_StartUpDataBase> StartUpDataAsset;
public:
FORCEINLINE UMiNiAbilitySystemComponent* GetMiniAbilitySystemComponent() const { return AbilitySystemComponent; };
};
属性类
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "MiNiAttributeSet.generated.h"
/**
*
*/
UCLASS()
class MINIWORLD_API UMiNiAttributeSet : public UAttributeSet
{
GENERATED_BODY()
};
资产类
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "GameplayTagContainer.h"
#include "DataAsset_StartUpDataBase.generated.h"
class UMiNiAbilitySystemComponent;
class UBaseGameplayAbility;
/**
*
*/
UCLASS()
class MINIWORLD_API UDataAsset_StartUpDataBase : public UDataAsset
{
GENERATED_BODY()
public:
/* 赋予时立即激活的技能 */
UPROPERTY(EditDefaultsOnly,Category="StartUpData")
TArray<TSubclassOf<UBaseGameplayAbility>> ActiveOnGiveAbilities;
/* 响应特定事件的技能 */
UPROPERTY(EditDefaultsOnly,Category="StartUpData")
TArray<TSubclassOf<UBaseGameplayAbility>> ReactiveAbilites;
public:
/* 向能力系统组件添加技能 */
virtual void GiveToAbilitySystemComponent(UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level = 1);
void GrantAbilities(const TArray<TSubclassOf<UBaseGameplayAbility>>& Abilities, UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level = 1);
};
英雄资产类
#pragma once
#include "CoreMinimal.h"
#include "DataAssets/StartUpData/DataAsset_StartUpDataBase.h"
#include "MiniTypes/MiniStructTypes.h"
#include "DataAsset_HeroStartUpData.generated.h"
/**
*
*/
UCLASS()
class MINIWORLD_API UDataAsset_HeroStartUpData : public UDataAsset_StartUpDataBase
{
GENERATED_BODY()
public:
/* 英雄的技能信息,标签和对应的技能 */
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Hero StartUp Abilities")
TArray<FMiniHeroAbilitySet> HeroAbilitySets;
public:
virtual void GiveToAbilitySystemComponent(UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level = 1) override;
};
技能类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "BaseGameplayAbility.generated.h"
class UMiNiAbilitySystemComponent;
UENUM(BlueprintType)
enum class EMiniAbilityActivatePolicy : uint8
{
OnTrriger,
OnGive,
};
/**
*
*/
UCLASS()
class MINIWORLD_API UBaseGameplayAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, Category = "Mini | Ability")
EMiniAbilityActivatePolicy ActivatePolicy = EMiniAbilityActivatePolicy::OnTrriger;
protected:
virtual void OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) override;
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
public:
UFUNCTION(BlueprintPure, Category = "Warrior | Ability")
UMiNiAbilitySystemComponent* GetMiNiAbilitySystemComponent() const;
};
英雄技能类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Ability/BaseGameplayAbility.h"
#include "PlayerGameplayAbility.generated.h"
class APlayerCharacterBase;
class AMiniPlayerController;
/**
*
*/
UCLASS()
class MINIWORLD_API UPlayerGameplayAbility : public UBaseGameplayAbility
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Get Player Character")
APlayerCharacterBase* GetPlayerCharacter();
UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Get Player Controller")
AMiniPlayerController* GetPlayerController();
private:
TWeakObjectPtr<APlayerCharacterBase> CachedPlayerCharacter;
TWeakObjectPtr<AMiniPlayerController> CachedPlayerController;
};
技能系统组件类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "MiNiAbilitySystemComponent.generated.h"
/**
*
*/
UCLASS()
class MINIWORLD_API UMiNiAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
void OnAbilityInputPressed(const FGameplayTag& AbilityTag);
void OnAbilityInputReleased(const FGameplayTag& AbilityTag);
public:
/* 尝试通过标签激活指定的技能 */
UFUNCTION(BlueprintCallable, Category = "Ability")
void ActivateAbilityByTag(FGameplayTag AbilityTag);
};
武器类
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MiniTypes/MiniStructTypes.h"
#include "WeaponBase.generated.h"
UCLASS()
class MINIWORLD_API AWeaponBase : public AActor
{
GENERATED_BODY()
public:
AWeaponBase();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
};
英雄武器类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Items/Weapon/WeaponBase.h"
#include "HeroWeaponBase.generated.h"
/**
*
*/
UCLASS()
class MINIWORLD_API AHeroWeaponBase : public AWeaponBase
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "WeaponData")
FMiniHeroWeaponSet HeroWeaponData;
};
标签类
#pragma once
#include "NativeGameplayTags.h"
namespace MiNiGameplayTags
{
/* 玩家标签 */
MINIWORLD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Grab);
};
结构体信息类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "ScalableFloat.h"
#include "MiniStructTypes.generated.h"
class UPlayerGameplayAbility;
/**
*
*/
/* 技能配置信息 */
USTRUCT(BlueprintType)
struct FMiniHeroAbilitySet
{
GENERATED_BODY()
/* 输入标签 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "InputTag")
FGameplayTag InputTag;
/* 技能 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Ability")
TSubclassOf<UPlayerGameplayAbility> AbilityClass;
/* 行为 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Action")
class UInputAction* InputAction;
bool IsValid() const { return InputTag.IsValid() && AbilityClass!= nullptr && InputAction!= nullptr; }
};
/* 武器配置信息 */
USTRUCT(BlueprintType)
struct FMiniHeroWeaponSet
{
GENERATED_BODY()
public:
/* 武器伤害数据表 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FScalableFloat WeaponDamageBase;
/* 武器技能配置信息 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TArray<FMiniHeroAbilitySet> WeaponAbilitySets;
};
2.绑定技能和标签和输入之间的关系
核心观点:
1.首先将游戏开始时需要注册的技能通过数据资产注册到角色的技能系统组件中
在角色类被控制器控制时,加载技能系统的资产来注册技能到技能系统组件下
这种类型的技能不需要通过行为来触发,可能是在给予时触发亦或者是事件触发或者是当添加了某一个标签时触发
void ABaseCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (AbilitySystemComponent)
{
AbilitySystemComponent->InitAbilityActorInfo(this, this);
}
}
void APlayerCharacterBase::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (!HeroStartUpDataAsset.IsNull())
{
HeroStartUpData = HeroStartUpDataAsset.LoadSynchronous();
if (HeroStartUpData)
{
HeroStartUpData->GiveToAbilitySystemComponent(GetMiniAbilitySystemComponent());
}
}
}
void UDataAsset_StartUpDataBase::GiveToAbilitySystemComponent(
UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level)
{
if (!AbilitySystemComponent)
return;
GrantAbilities(ActiveOnGiveAbilities, AbilitySystemComponent, Level);
GrantAbilities(ReactiveAbilites, AbilitySystemComponent, Level);
}
void UDataAsset_StartUpDataBase::GrantAbilities(const TArray<TSubclassOf<UBaseGameplayAbility>>& Abilities, UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level)
{
if (Abilities.Num() > 0)
{
for (auto& Ability : Abilities)
{
if (Ability)
{
FGameplayAbilitySpec AbilitySpec(Ability);
AbilitySpec.SourceObject = AbilitySystemComponent->GetAvatarActor();
AbilitySpec.Level = Level;
AbilitySystemComponent->GiveAbility(AbilitySpec);
}
}
}
}
void UDataAsset_HeroStartUpData::GiveToAbilitySystemComponent(UMiNiAbilitySystemComponent* AbilitySystemComponent, int32 Level)
{
Super::GiveToAbilitySystemComponent(AbilitySystemComponent, Level);
for (auto& AbilitySet : HeroAbilitySets)
{
if (AbilitySet.IsValid())
{
FGameplayAbilitySpec AbilitySpec(AbilitySet.AbilityClass); // 技能
AbilitySpec.Level = Level; // 等级
AbilitySpec.SourceObject = AbilitySystemComponent->GetAvatarActor(); // 施法者
AbilitySpec.DynamicAbilityTags.AddTag(AbilitySet.InputTag);
/* 持续触发的技能 */
AbilitySystemComponent->GiveAbility(AbilitySpec); // 给组件添加技能
}
}
}
2.绑定增强输入系统,通过行为绑定技能,输入上下文来绑定行为和按键的关系,行为和行为之间可以互相管理,在行为触发时会调用对应的回调函数,在一开始就绑定了技能的标签作为回调函数的入参,在回调函数中通过技能系统组件来遍历注册到技能系统组件中的技能,最后来找到这个捆绑这个标签的技能最后触发该技能。
void APlayerCharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
/* 行为绑技能 */
BindActionToAbility(PlayerInputComponent);
}
void APlayerCharacterBase::BindActionToAbility(UInputComponent* PlayerInputComponent)
{
if (!HeroStartUpData)
{
HeroStartUpData = HeroStartUpDataAsset.LoadSynchronous();
}
// 增强输入组件
UEnhancedInputComponent* Input = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (Input)
{
for (auto& AbilitySet : HeroStartUpData->HeroAbilitySets)
{
Input->BindAction(AbilitySet.InputAction, ETriggerEvent::Started, this, &APlayerCharacterBase::OnAbilityInputPressed, AbilitySet.InputTag);
Input->BindAction(AbilitySet.InputAction, ETriggerEvent::Completed, this, &APlayerCharacterBase::OnAbilityInputReleased, AbilitySet.InputTag);
}
}
}
void APlayerCharacterBase::OnAbilityInputPressed(FGameplayTag AbilityTag)
{
AbilitySystemComponent->OnAbilityInputPressed(AbilityTag);
}
void APlayerCharacterBase::OnAbilityInputReleased(FGameplayTag AbilityTag)
{
AbilitySystemComponent->OnAbilityInputReleased(AbilityTag);
}
void UMiNiAbilitySystemComponent::OnAbilityInputPressed(const FGameplayTag& AbilityTag)
{
if (AbilityTag.IsValid())
{
for (auto& AbilitySpec : GetActivatableAbilities())
{
if (AbilitySpec.DynamicAbilityTags.HasTagExact(AbilityTag))
{
TryActivateAbility(AbilitySpec.Handle, true);
}
}
}
Print("Activate Ability By Tag = " + AbilityTag.ToString());
}
void UMiNiAbilitySystemComponent::OnAbilityInputReleased(const FGameplayTag& AbilityTag)
{
}
3.定义行为,并在输入映射上下文中绑定与按键的映射关系,在角色初始化时注册该上下文到增强输入系统中
至此GAS简易框架和增强输入系统已经构建完毕