5. UE5 RPG使用GAS技能系统

之前也介绍过GAS的使用:
UE 5 GAS Gameplay Ability System
UE 5 GAS 在项目中处理AttributeSet相关
UE 5 GAS 在项目中通过数据初始化
基础的讲解这里不再诉说,有兴趣的可以翻我之前的博客。

接下来,在RPG游戏中实现GAS系统的使用。
GAS系统可以放到角色Pawn身上,也可以放到PlayerState里面,如果放到Pawn身上,GAS也会跟着销毁,这个比较方便与敌人身上,所以敌人的Ability System Component(ASC)和Attribute Set我们将直接放置到敌人的Pawn身上,而玩家控制的角色,牵扯到一个复活的问题,我们需要保存技能相关的数据,将放置到PlayerState身上,那样如果销毁掉角色Pawn,相关数据也会保存下来。

创建PlayerState

在这里插入图片描述
首先点击创建c++类
在这里插入图片描述
创建一个新的玩家状态类

// 版权归暮志未晚所有。


#include "Player/PlayerStateBase.h"

APlayerStateBase::APlayerStateBase()
{
	NetUpdateFrequency = 100.f; //每秒和服务器更新频率,使用GAS后可以设置的高一些
}

创建完成后再PlayerState.cpp中初始化时,修改NetUpdateFrequency 默认为2,使用了GAS可以设置的更高
在这里插入图片描述
打开ue,创建蓝图类
在这里插入图片描述
放置到蓝图文件夹内
在这里插入图片描述
将GameMode里面的玩家状态类修改成当前创建的蓝图。
GAS的载体就制作完成,接下来添加GAS系统。

添加GAS

在这里插入图片描述
打开插件,搜素gameplay,找到gameplay Abilities,添加,重新启动。
在这里插入图片描述
添加新的c++类,父类为AbilitySystemComponent
在这里插入图片描述
创建ASC基类
在这里插入图片描述
接下来创建数据集类,父类为AttributeSet

PrivateDependencyModuleNames.AddRange(new string[] { "GameplayAbilities", "GameplayTags", "GameplayTasks" });

在私有模块中添加相关模块

代码中添加

带有ASC的Actor也被称为ASC的OwnerActor。ASC实际作用的Actor叫作AvatarActor。OwnerActor和AvatarActor可以是同一个Actor,比如MOBA游戏中的野怪。它们也可以是不同的 Actors,比如MOBA游戏中玩家和AI控制的英雄角色,OwnerActor是PlayerState、AvatarActor是HeroCharacter。大部分情况下OwnerActor和AvatarActor可以是角色Actor。不过想像一下你控制的英雄角色死亡然后重生的过程,如果此时要保留死亡前的Attributes或者GameplayEffects,那么最理想的做法是将ASC交给PlayerState。

如果OwnerActor和AvatarActor是不同的Actors,那么两者都需要实现IAbilitySystemInterface。这个接口只有一个方法需要被重载UAbilitySystemComponent* GetAbilitySystemComponent() const,此方法将返回ASC。
在这里插入图片描述
首先在角色基础的类里面创建两个属性,分别用来定义技能组件和属性,记得声明它们的类。主角类和敌人基础的类都会继承角色基础类,那么,它们都会创建相关的属性。

AEnemyBase::AEnemyBase()
{
	GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block); //设置可视为阻挡

	AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponentBase>("AbilitySystemComponent");
	AbilitySystemComponent->SetIsReplicated(true); //设置组件用于在网络上复制

	AttributeSet = CreateDefaultSubobject<UAttributeSetBase>("AttributeSet");
}

敌人的基类里面,只需要在初始化时实例化相应的组件
在这里插入图片描述
主角的组件和数据,我们首先需要先在PlayerState身上设置,然后再characterBase身上去引用PlayerState身上的对应组件和数据,这样,即使character销毁掉,创建新的,我们一样可以获取到修改后的数据。

// 版权归暮志未晚所有。


#include "Player/PlayerStateBase.h"
#include "AbilitySystem/AbilitySystemComponentBase.h"
#include "AbilitySystem/AttributeSetBase.h"

APlayerStateBase::APlayerStateBase()
{
	NetUpdateFrequency = 100.f; //每秒和服务器更新频率,使用GAS后可以设置的高一些
	
	AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponentBase>("AbilitySystemComponent");
	AbilitySystemComponent->SetIsReplicated(true); //设置组件用于在网络上复制

	AttributeSet = CreateDefaultSubobject<UAttributeSetBase>("AttributeSet");
}

在PlayerStateBase.cpp里面实例化。

接下来比较重要的一步就是,如何在Character里面去获取PlayerState的技能组件,这里我们使用了GAS组件自带AbilitySystemInterface接口去实现。
在这里插入图片描述
需要在.h文件中使用技能组件,所以,我们将模块移入到Public列表中。

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemInterface.h"
#include "GameFramework/PlayerState.h"
#include "PlayerStateBase.generated.h"

class UAbilitySystemComponent;
class UAttributeSet;
/**
 * 
 */
UCLASS()
class AURA_API APlayerStateBase : public APlayerState, public IAbilitySystemInterface
{
	GENERATED_BODY()

public:
	APlayerStateBase();
	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override; //覆盖虚函数获取asc
	UAttributeSet* GetAttributeSet() const { return AttributeSet; } //获取as

protected:
	
	UPROPERTY()
	TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;

	UPROPERTY()
	TObjectPtr<UAttributeSet> AttributeSet;
};

在playerState里,继承接口,实现接口的虚函数,用于获取asc,并实现获取as的函数。

UAbilitySystemComponent* APlayerStateBase::GetAbilitySystemComponent() const
{
	return AbilitySystemComponent;
}

cpp里定义也只是返回asc组件。
在这里插入图片描述
character同样继承此接口,并实现对应的函数。
在这里插入图片描述
接下来我们要设置复制模式,以便来同步客户端和服务器端数据。

AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);

在角色的asc上面,我们使用Mixed模式同步。

AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);

而怪物的asc,则使用Minimal模式

初始化AbilitySysytemComponent

ASC需要有OwnerActor和AvatarActor进行初始化,而且必须在服务器和客户端都要完成初始化。

对于玩家控制的角色,ASC存在于Pawn中,我通常在Pawn的 PossessedBy()方法中完成ASC在服务器端的初始化,在PlayerController的AcknowledgePawn()方法中完成ASC在客户端的初始化。

对于玩家控制的角色,ASC存在于PlayerState中,我通常在Pawn 的PossessedBy() 方法中完成ASC在服务器端的初始化(这一点与上述相同),在 Pawn的 OnRep_PlayerState()方法中完成ASC在客户端的初始化(这将确保PlayerState在客户端已存在)。

对于AI控制的角色,ASC存在于Pawn中,通常在Pawn的 BeginPlay()方法中完成ASC在服务器端和客户端的初始化。

既然根据文档知道了如何初始化,那么,我们按照相应的方式初始化。首先初始化敌人身上的ASC,敌人作为ai怪物,只需要在BeginPlay里面初始化即可。
在这里插入图片描述
首先覆盖BeginPlay()的函数

void AEnemyBase::BeginPlay()
{
	Super::BeginPlay();

	AbilitySystemComponent->InitAbilityActorInfo(this, this);
}

然后在BeginPlay()里面调用InitAbilityActorInfo初始化即可完成。

接下来是玩家控制角色的ASC初始化,玩家控制角色按照文档说法,我们需要在AvatarActor里面进行初始化。
在这里插入图片描述
如果ASC存在于PlayerState中,则覆盖这两个函数,然后添加私有初始化函数(因为里面初始化代码一致)

void AHeroCharacter::InitAbilityActorInfo()
{
	APlayerStateBase* PlayerStateBase = GetPlayerState<APlayerStateBase>();
	check(PlayerStateBase);
	//从playerState获取ASC和AS
	AbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();
	AttributeSet = PlayerStateBase->GetAttributeSet();
	//初始化ASC
	AbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);
}

初始化代码就是获取到玩家控制角色的PlayerState,从PlayerState身上获取ASC和AS,OwnerActor就是PlayerState,而AvatarActor则就是自身。

void AHeroCharacter::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);

	//初始化ASC的OwnerActor和AvatarActor
	InitAbilityActorInfo();
}

void AHeroCharacter::OnRep_PlayerState()
{
	Super::OnRep_PlayerState();

	//初始化ASC的OwnerActor和AvatarActor
	InitAbilityActorInfo();
}

接下来就是在PossessedBy()和OnRep_PlayerState()调用,完成服务端和客户端的初始化。

	//初始化ASC的OwnerActor和AvatarActor
	InitAbilityActorInfo();

	//设置OwnerActor的Controller
	SetOwner(NewController);

注意: Mixed 复制模式要求OwnerActor的 Owner必须是Controller。 PlayerState的 Owner默认是Controller,但是Character不是。如果使用Mixed复制模式的OwnerActor不是PlayerState那么你需要在OwnerActor上调用SetOwner()并传递一个有效的Controller。(不过从4.24开始, PossessedBy() 会为Pawn设置一个新的Controller。)

参考:虚幻引擎游戏技能系统文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/331553.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

笔记本电脑如何连接显示屏?

目录 1.按下快捷键 winP,选择扩展 2.连接显示器&#xff0c;连好接线 3.笔记本驱动有问题&#xff0c;显示错误如下&#xff1a; 4.驱动已经下载完成&#xff0c; 按下快捷键&#xff0c;还是显示第3步中的错误 5.驱动已经下载完成&#xff0c; 按下快捷键&#xff0c;参照…

Redis:原理速成+项目实战——Redis实战13(GEO实现附近商铺、滚动分页查询)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis实战12&#xff08;好友关注、Feed流&#xff08;关注推送&#xff09;、滚动分页查…

拼多多无货源中转仓项目真的靠谱吗?发展前景如何?

阿阳最近一直在关注无货源电商这一块&#xff0c;尤其是拼多多无货源中转仓&#xff0c; 现如今也有了自己的运营团队和交付团队&#xff0c;整体来看这个项目还算不错&#xff01; 说实话&#xff0c;在考察这个项目的时候&#xff0c;看到市面上很多人在做&#xff0c;包括我…

JAVA基础-----认识异常

文章目录 1. 异常的概念与体系结构1.1 异常的概念1.2 异常的体系结构1.3 异常的分类 2. 异常的处理2.1 防御式编程2.2 异常的抛出2.3 异常的捕获2.3.1 异常声明throws2.3.2 try-catch捕获并处理2.3.3 finally 2.4 异常的处理流程 3. 自定义异常类 1. 异常的概念与体系结构 1.1…

C/C++ 基本数据类型的范围

一、常见的数据类型及其范围 数据类型Size(64位)范围int4Byteunsigned int4Bytelong4Byteunsigned long4Bytelong long8Byteunsigned long long8Byte 查询Size代码&#xff1a;sizeof(类型) 查询范围代码&#xff1a;numeric_limits<类型>::max和numeric_limits<类…

使用 mybatis-plus 的mybaits的一对多时, total和record的不匹配问题

应该是框架的问题&#xff0c;去官方仓库提了个issues&#xff0c;等回复 https://github.com/baomidou/mybatis-plus/issues/5923 回复来了&#xff1a; 背景 发现 record是两条&#xff0c;但是total显示3 使用resultMap一对多时&#xff0c;三条数据会变成两条&#xff0…

redis原理(四)redis命令

目录 一、字符串命令&#xff1a; 二、列表命令&#xff1a; 三、集合命令&#xff1a; 四、散列命令&#xff1a; 五、有序集合命令&#xff1a; 六、redis发布与订阅命令&#xff1a; 七、事务命令 八、其他命令 1、排序&#xff1a;SORT 2、键的过期时间&#xff…

代码随想录算法训练营Day23 | 455.分发饼干、376.摆动子序列、53.最大子数组和

LeetCode 455 分发饼干 本题思路&#xff1a;分发饼干的时候&#xff0c;外层循环是胃口&#xff0c;内层是饼干&#xff0c;按照大饼干满足大胃口的思维来投递饼干。 需要将 两个数组&#xff0c;一开始就进行排序处理。 class Solution {public int findContentChildren(int…

java转义字符

//转义字符的使用 public class ChangeChar{//编写一个main方法public static void main(String[] args){// \t :一个制表位&#xff0c;实现对齐的功能System.out.println("北京\t天津\t上海");// \n :换行符&#xff0c;实现换行System.out.println("jack\nsm…

SSH隧道技术

SSH隧道 简介 SSH隧道是一种通过SSH协议在两个网络节点之间建立安全通信的技术。它可以用于多种用途&#xff0c;包括加密和保护敏感数据传输、绕过防火墙限制、远程访问内部服务等。 应用&#xff1a; 端口转发&#xff1a;SSH隧道可以将本地端口转发到远程主机上&#xf…

Python学习从0到1 day5 python基础语法3 数据类型及数据类型转换

一切都会好的&#xff0c;我一直相信 ——24.1.17 一、数据类型 1.数据是有类型的 目前主要接触如下三类数据类型&#xff1a; 2.type()语句 我们可以通过type()语句来得到数据的类型 语法&#xff1a;type(被查看类型的数据) a 10 type(a) print(type(a)) print(type(11…

分子动力学模拟—LAMMPS 模拟(固体和液体)数据后处理软件(六)

记录一下检索到一篇分子动力学模拟数据后处理的软件。 感谢论文的原作者&#xff01; 主要功能&#xff1a; Structure Analysis Ackland Jones Analysis CentroSymmetry Parameter Common Neighbor Analysis Common Neighbor Parameter Atomic Structure Entropy Stein…

IOS-高德地图连续定位-Swift

使用定位功能需要需要接入高德地图定位Api&#xff1a; pod AMapLocation配置Info 在info中新建一个名为Privacy - Location Temporary Usage Description Dictionary的字典&#xff0c;然后在这个字典下新建Privacy - Location When In Use Usage Description、Privacy - Lo…

【​电力电子在电力系统中的应用​】6 滞环电流控制的PWM整流器 + STATCOM整流器 + APF仿真

【仅供参考】 【2023.06西南交大电力电子在电力系统中的应用】 目录 步骤一&#xff1a;基于滞环电流控制的PWM整流器仿真 1.1 仿真要求 1.2 仿真电路原理及设计 1.2.1 主电路的搭建 1.2.2 控制电路的搭建 1.3 波形分析 步骤二&#xff1a;从PWM整流器到STATCOM仿真 2…

使用ProxySql实现Mysql的读写分离 详细安装步骤 亲测可行

主机ip说明192.168.168.109ProxySql192.168.168.77mysql master(主&#xff09;192.168.168.78mysql slave&#xff08;从&#xff09; 1.下载ProxySql安装包 在192.168.168.109机器上操作 https://github.com/sysown/proxysql/releases/download/v2.5.5/proxysql-2.5.5-1-ce…

阿里云ack集群管理及故障处理

一、集群管理维护 二、常见故障处理 存储&#xff1a; 网络 弹性伸缩 service

Microsoft Word 设置底纹

Microsoft Word 设置底纹 References 打开文档页面&#xff0c;选中特定段落或全部文档 在“段落”中单击“边框”下三角按钮 在列表中选择“边框和底纹”选项 在“边框和底纹”对话框中单击“底纹”选项卡 在图案样式和图案颜色列表中设置合适颜色的底纹&#xff0c;单击“确…

利用蓝图直接提升客户服务体验的方法

简单地说&#xff0c;流程就是按顺序执行的一系列操作过程。每项行动都有一个结果&#xff0c;而这个结果又会成为该序列中下一项行动的输入。客户服务流程的建立目的是为了保持一致性、提高效率并帮助组织管理规模。不过&#xff0c;在实际操作的过程中&#xff0c;他们会遇到…

C#判断输入的数字是否符合货币格式

目录 一、用正则表达式判断输入是否符合货币格式 二、用double.TryParse()判断输入是否符合货币格式 一、用正则表达式判断输入是否符合货币格式 // 判断输入是否货币合格 using System.Text.RegularExpressions; namespace IsCurrency_Format {partial class Program{stati…

直播间的秒杀狂热背后,猫眼电影如何接住10w+并发运营活动?

“倒数&#xff0c;5、4、3、2、1” “10万张&#xff01;” “20秒没了” 上周末&#xff0c;张家辉和导演马浴柯带着新电影《怒潮》上了疯狂小杨哥的直播间&#xff0c;人数一度冲破80万人。 这次直播&#xff0c;是猫眼电影为新电影《怒潮》准备的一次宣传活动。 随着小…