5. UE5 RPG使用GAS技能系统

news2024/9/24 18:00:01

之前也介绍过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。)

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一次缓存失效引发的惨案!

分享是最有效的学习方式。 故事 对于小猫来讲&#xff0c;最近的一段日子是不好过的&#xff0c;纵使听着再有节拍的音乐&#xff0c;也换不起他对生活的热情。由于上一次“幂等事件”躺枪&#xff0c;他已经有几天没有休息好了。他感觉人生到了低谷。 当接手这个商城项目之后…

Linux 为何不把图形用户界面写入内核?

Linux 为何不把图形用户界面写入内核&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#…

禅道:从安装到使用,一篇文章带你全面了解

博客前言&#xff1a; 在这个充满竞争和快节奏的世界里&#xff0c;项目管理已经成为了许多行业的关键环节。禅道作为一种功能强大、易用的项目管理工具&#xff0c;正在被越来越多的企业和团队所采用。它不仅能帮助我们高效地管理项目&#xff0c;还能提升团队协作和沟通的效…

DC-1靶机刷题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1GX7qOamdNx01622EYUBSow?pwd9nyo 提取码&#xff1a;9nyo 参考答案&#xff1a; https://c3ting.com/archives/kai-qi-vulnhnbshua-tiDC-1.pdf【【基础向】超详解vulnhub靶场DC-1】 https://www.bilibi…

【数据结构二】链表和LinkedList详解

目录 链表和LinkedList 1.链表的实现 2.LinkedList的使用 3.ArrayList和LinkedList的区别 4.链表OJ题训练 链表和LinkedList 当 在 ArrayList 任意位置插入或者删除元素时&#xff0c;就需要将后序元素整体往前或者往后 搬移&#xff0c;时间复杂度为 O(n) &#xff0c;效率…

ChatGLM-6B部署和微调实例

文章目录 前言一、ChatGLM-6B安装1.1 下载1.2 环境安装 二、ChatGLM-6B推理三、P-tuning 微调3.1微调数据集3.2微调训练3.3微调评估3.4 调用新的模型进行推理 总结 前言 ChatGLM-6B ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Mo…

unity-shader笔记OLD

shader shader在面板中的位置相关代码代码切换shader shader在面板中的位置 选中物体属性面板中 相关代码 代码切换shader 挂载到怪物上的shader名字统一叫body&#xff0c;然后获取上面的SkinnedMeshRender SkinnedMeshRender smr&#xff1b; //恢复到原来的shader …

JavaScript DOM可以做什么?

1、通过id获取标签元素 DOM是文档对象模型&#xff0c;它提供了一些属性和方法来方便我们操作document对象&#xff0c;比如getElementById()方法可以通过某个标签元素的id来获取这个标签元素 // 用法 window.document.getElementById(id); // 例子 <!DOCTYPE html> &l…

LeetCode、374. 猜数字大小【简单,二分】

文章目录 前言LeetCode、374. 猜数字大小【简单&#xff0c;二分】题目及类型思路及代码实现 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技…

移动云助力智慧交通数智化升级

智慧交通是在整个交通运输领域充分利用物联网、空间感知、云计算、移动互联网等新一代信息技术&#xff0c;综合运用交通科学、系统方法、人工智能、知识挖掘等理论与工具&#xff0c;以全面感知、深度融合、主动服务、科学决策为目标&#xff0c;推动交通运输更安全、更高效、…

联想拯救者冠名2024第二届OPENAIGC开发者大赛,开启AI落地新纪元

2024年1月17日&#xff0c;在联想拯救者及消费生态新品发布会上&#xff0c;AIGC开放社区携手联想拯救者&#xff0c;宣布将共同举办“AI生成未来第二届拯救者杯OPENAIGC开发者大赛”。此次大赛旨在集结所有开发者的智慧和创造力&#xff0c;推动人工智能技术的创新和应用实践。…

Promise的几道基础题

event loop它的执行顺序&#xff1a; 一开始整个脚本作为一个宏任务执行执行过程中同步代码直接执行&#xff0c;宏任务进入宏任务队列&#xff0c;微任务进入微任务队列当前宏任务执行完出队&#xff0c;检查微任务列表&#xff0c;有则依次执行&#xff0c;直到全部执行完执…

服务器自动拉取git代码运行脚本

# 1.场景分析 工作中常常会遇到本地编辑shell脚本或者python脚本完成后需要在服务器上运行的情况&#xff0c;每次进行拷贝费时费力。下面介绍下通过git管理器&#xff0c;实现本地与服务器代码同步的方式。选择公司搭建的gitlab为例&#xff1a; 2.gitlab配置服务器ssh密钥 …

免费的爬虫软件【2024最新】

在国际市场竞争日益激烈的背景下&#xff0c;国外网站的SEO排名直接关系到网站在搜索引擎中的曝光度和用户点击量。良好的SEO排名能够带来更多的有针对性的流量&#xff0c;提升网站的知名度和竞争力。 二、国外网站SEO排名的三种方法 关键词优化&#xff1a; 关键词优化是SEO…

【IAP】核心开发流程

最近做了IAP U盘升级模块开发&#xff0c;总结下IAP基本开发流程&#xff0c;不深入讨论原理。 详细原理参考 首先需要知道我们需要把之前的APP区域拆一块出来做BOOT升级程序区域。 以STM32F103为例&#xff0c;0x08000000到0x0807FFFF为FLASH空间&#xff0c;即上图代码区域…

Java基础面试题-2day

面向对象 创建一个对象用什么运算符&#xff0c;对象实体和对象引用有什么不同&#xff1f; 创建对象使用new String A new String(); A即为对象引用&#xff0c;通过new运算符&#xff0c;创建String()类型的对象实体。 对象引用的存储位置在栈内存 对象实体的存储位置在堆…

2024玩儿转TikTok之环境介绍及搭建

郑重申明&#xff1a;本文章只对合法合理做tiktok视频运营的用户做学习交流使用&#xff0c;有其他使用不当的违规违法行为后果自负&#xff01; 一、网络环境图介绍&#xff1a;我们只需要保证红色的环境通畅即可(手机阿里tiktok运营专用服务器) 二、服务器部分环境搭建 1、…

STM32F103标准外设库——SysTick系统定时器(八)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

软件测试|sqlalchemy一对一关系详解

简介 SQLAlchemy 是一个强大的 Python ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它允许我们将数据库表映射到 Python 对象&#xff0c;并提供了丰富的关系模型来处理不同类型的关系&#xff0c;包括一对一关系。在本文中&#xff0c;我们将深入探讨 SQLAlchemy …

大数据工作岗位需求分析

前言&#xff1a;随着大数据需求的增多&#xff0c;许多中小公司和团队也新增或扩展了大数据工作岗位&#xff1b;但是却对大数据要做什么和能做什么&#xff0c;没有深入的认识&#xff1b;往往是招了大数据岗位&#xff0c;搭建起基础能力后&#xff0c;就一直处于重复开发和…