UE5 GAS RPG Character Classes

在正常的游戏中,我们应该考虑如何去初始化角色属性,并且要给角色分好类型。比如,在我们游戏中,我们如何去初始化小兵的属性,并且还要实现小兵随着等级的增长而增加属性。而且就是小兵也有类型的区分,比如我们将在后面设置小兵分为三种:战士,游侠,法师。而小兵的属性实现,一般需要策划进行配表实现,将小兵的属性统一性的存入到表格导入项目。

我们将使用枚举去定义敌人的类型并创建一个ECharacterClass,并创建一个DataAsset命名为UCharacterClassInfo用来设置每种类型使用的属性初始化的GE。对于随着等级变动的基础属性,我们将使用曲线表格去生成所有等级的数据。并且,在数据中,我们去设置敌人需要附带的技能。

所以,接下来,我们实现的步骤是:

  1. 创建DataAsset储存UCharacterClassInfo
cpp 复制代码
// YanWei.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CharacterClassInfo.generated.h"

class UGameplayEffect;
//角色职业类型的枚举
UENUM(BlueprintType)
enum class ECharacterClass : uint8
{
	Elementalist, //法师
	Warrior, //战士
	Ranger //游侠
};

USTRUCT()
struct FCharacterClassDefaultInfo
{
	GENERATED_BODY()
	
	UPROPERTY(EditDefaultsOnly, Category="Class Defaults")
	TSubclassOf<UGameplayEffect> PrimaryAttributes;
	
};

/**
 * 根据职业选择初始化角色的数据
 */
UCLASS()
class AURA_API UCharacterClassInfo : public UDataAsset
{
	GENERATED_BODY()
	
public:
	//用于根据不同的职业选择不同的结构体,
	UPROPERTY(EditDefaultsOnly, Category="Class Defaults")
	TMap<ECharacterClass, FCharacterClassDefaultInfo> CharacterClassInformation;
	
	UPROPERTY(EditDefaultsOnly, Category="Common Class Defaults")
	TSubclassOf<UGameplayEffect> SecondaryAttributes;
	
	UPROPERTY(EditDefaultsOnly, Category="Common Class Defaults")
	TSubclassOf<UGameplayEffect> VitalAttributes;

	//通过枚举获取对应的初始化类
	FCharacterClassDefaultInfo GetClassDefaultInfo(ECharacterClass CharacterClass);
};


// YanWei.


#include "AbilitySystem/Data/CharacterClassInfo.h"

FCharacterClassDefaultInfo UCharacterClassInfo::GetClassDefaultInfo(ECharacterClass CharacterClass)
{
	return CharacterClassInformation.FindChecked(CharacterClass);
}
  1. 创建GE去填充DA_CharacterInfo

3.创建GE使用的 CurveTable

依次是 常数 线性 立方体(平滑曲线)

操作流程 添加n个关键帧->三次插值自动切线

4.CurveTable 填入GE

还有另外两种方法 CSV 和 JSON

  • 现在通过设置好的通用GE去实例化Enemy

创建完成对应的GE,我们并使用数据表格填充了对应的数据,接下来,我们将通过代码实现对应的逻辑去初始化角色。

首先,我们考虑将创建数据放在哪里,这里我们将其放到GameMode上面,对于GameMode来说,在不同场景可以设置不同的GameMode,刚好合适,比如你创建了一个关卡,可以设置上对应的数据,关卡内的敌人初始化时,就使用这一套GE去初始化。

在我们的GameMode基类上增加一个变量,用于设置数据 蓝图中设置CharacterClassInofo(DataAsset)

在函数库增加一个函数,用于初始角色属性

cpp 复制代码
//函数的实现
void UMyASBlueprintFunctionLibrary::InitializeDefaultAttributes(const UObject* WorldContextObject,
	ECharacterClass CharacterClass, float Level, UAbilitySystemComponent* ASC)
{
	//这里需要用到ASC去索引到AvatarActor 才能应用GE属性 
	AActor* AvatarActor = ASC->GetAvatarActor();
	
	//获取到当前关卡的GameMode实例
	const AAuraGameModeBase* GameMode = Cast<AAuraGameModeBase>(UGameplayStatics::GetGameMode(WorldContextObject));
	if(GameMode == nullptr) return;

	//从实例获取到关卡角色的配置
	UCharacterClassInfo* ClassInfo = GameMode->CharacterClassInfo;

	//获取到默认的基础角色数据
	const FCharacterClassDefaultInfo ClassDefaultInfo = ClassInfo->GetClassDefaultInfo(CharacterClass);

	//应用基础属性
	FGameplayEffectContextHandle PrimaryContextHandle = ASC->MakeEffectContext();
	PrimaryContextHandle.AddSourceObject(AvatarActor);
	const FGameplayEffectSpecHandle PrimarySpecHandle = ASC->MakeOutgoingSpec(ClassDefaultInfo.PrimaryAttributes, Level, PrimaryContextHandle);
	ASC->ApplyGameplayEffectSpecToSelf(*PrimarySpecHandle.Data.Get());

	//设置次级属性
	FGameplayEffectContextHandle SecondaryContextHandle = ASC->MakeEffectContext();
	SecondaryContextHandle.AddSourceObject(AvatarActor);
	const FGameplayEffectSpecHandle SecondarySpecHandle = ASC->MakeOutgoingSpec(ClassInfo->SecondaryAttributes, Level, SecondaryContextHandle);
	ASC->ApplyGameplayEffectSpecToSelf(*SecondarySpecHandle.Data.Get());

	//填充血量和蓝量
	FGameplayEffectContextHandle VitalContextHandle = ASC->MakeEffectContext();
	VitalContextHandle.AddSourceObject(AvatarActor);
	const FGameplayEffectSpecHandle VitalSpecHandle = ASC->MakeOutgoingSpec(ClassInfo->VitalAttributes, Level, VitalContextHandle);
	ASC->ApplyGameplayEffectSpecToSelf(*VitalSpecHandle.Data.Get());
	
}

然后需要在Enemy.h中设置 职业变量并 InitInfo使用上面实现的函数nitializeDefaultAttributes()

cpp 复制代码
	//TODO:: 用于给不同敌人划分不同职业
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character Class Defaults" )
	ECharacterClass CharacterClass = ECharacterClass::Warrior;
    //重写父类初始化函数
    virtual void InitializeDefaultAttributes() const override;

//--Enemt.cpp

void AAuraEnemy::InitAbilityActorInfo()
{
	//初始化ActorInfo
	AbilitySystemComponent->InitAbilityActorInfo(this,this);
	//单向了解
	Cast<UAuraAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
	//通过GE初始角色的属性
	InitializeDefaultAttributes();
}

void AAuraEnemy::InitializeDefaultAttributes() const
{
	//重写覆盖父类初始化函数,但删去Super
	UMyASBlueprintFunctionLibrary::InitializeDefaultAttributes(this,CharacterClass,Level,AbilitySystemComponent);
}

调试验证

打断点处

相关推荐
啊阿狸不会拉杆35 分钟前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路1 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
曙曙学编程2 小时前
stm32——GPIO
c语言·c++·stm32·单片机·嵌入式硬件
△曉風殘月〆2 小时前
Visual Studio中的常用调试功能(下)
c++·ide·visual studio·调试
武当豆豆2 小时前
C++编程学习(第25天)
开发语言·c++·学习
minji...6 小时前
C++ string类(STL简介 , string类 , 访问修改字符)
开发语言·c++
Forward♞6 小时前
Qt——文件操作
开发语言·c++·qt
十五年专注C++开发6 小时前
CMake进阶: CMake Modules---简化CMake配置的利器
linux·c++·windows·cmake·自动化构建
winds~7 小时前
【git】 撤销revert一次commit中的某几个文件
linux·c++
carver w7 小时前
MFC,C++,海康SDK,回调,轮询
开发语言·c++·mfc