之前,只是简单的实现了一些特定的功能,这几天一直在学习官方的案例,学习了Lyra初学者项目和Action RPG的项目,也从中学习到了很多功能的使用,并对基础的架构设计有了初步的认识。
接下来,将对基础的一些设置做一下介绍,方便和我一样初学ue的小伙伴一起学习。
GameInstace 游戏实例
GameInstace是一个正在运行的游戏的高级别的管理对象,在游戏创建时生成,游戏实例关闭时自动销毁,一个游戏可以有多个GameInstace。
切换关卡不会销毁GameInstance,所以切换关卡需要传递的信息可以通过GameInstance去传递。
在游戏中,GameInstace可以作为一个全局的类使用,存储在全局位置使用,在蓝图中可以通过获取GameInstace来获取。
摘自:https://blog.csdn.net/Highning0007/article/details/123042719
设置项目的GameInstace,我们可以在项目设置GameInstance,在地图和模式里,找到游戏实例类,设置你自己的项目的游戏实例类
创建自己的游戏实例,你可以通过添加蓝图类,在所有类里面搜索GameInstance来找到游戏实例的父类,基于它创建一个自己的GameInstance类
在蓝图中获取游戏实例,你可以通过获取游戏实例节点,来获取到游戏实例对象,从里面获取数据或者设置数据
又或者直接在蓝图函数库里面创建一个全局获取函数,获取你自己设置的类型的类的实例,这样,你不用每次获取到游戏实例以后,还需要将其转换为相应的类型
在官方案例动作RPG项目中,GameInstance主要保存一些数据资产,给角色以及ui使用,获取全局的设置,并提供设置全局的接口
在事件图表中,有关卡切换逻辑,游戏暂停的逻辑
还有就是在游戏开始时,默认设置一份本地存储,并预先加载游戏中使用的数据结构,链接服务器功能好像未实现。
GameMode 游戏模式
GameMode定义了游戏的玩法和规则,比如你可以在游戏模式里面设置怪物的生成,以及游戏获胜的规则等等。在项目设置中,你可以设置游戏的默认模式。
你可以使用单一的GameMode来应用到多个不同的关卡,比如多个游戏副本可以适应一套GameMode。
而在关卡中,你可以通过游戏模式重载,在世界场景设置中定义当前关卡的游戏模式
在选中的游戏模式中,默认的pawn类是默认生成的玩家控制类,一般不会直接在这里设置,会在玩家控制器中去生成。
默认HUD类,HUD是指"抬头显视"或二维屏幕显示,在许多游戏中较为常用。例如显示血条、弹药指示器、枪准星等。每个玩家控制器通常都配有其中一种显示。这个一般也不会直接设置,因为正常的项目使用的HUD千变万化,需要实时创建。
玩家控制类,这个看名称就知道,主要是协助控制玩家的,后面会重点讲解。
游戏状态类 GameState包含游戏的状态,其中可以包括联网玩家列表、得分、棋类游戏中棋子的位置,或者在开放世界场景中完成的任务列表。游戏状态存在于服务器和所有客户端上,可以自由复制以保持所有机器处于最新状态。
玩家状态类 玩家状态 是游戏玩家的状态,例如人类玩家或模拟玩家的机器人。作为游戏的一部分而存在的非玩家AI将不会拥有玩家状态。在玩家状态中适当的示例数据包括玩家姓名或得分、比赛中MOBA等的等级,或玩家当前是否在CTF游戏中携带旗帜。所有玩家的玩家状态存在于所有机器上(与玩家控制器不同),并且可以自由复制以保持同步。
旁观者类 其实就是作为第三者,在观察场景内的数据调试时使用,作为一个额外的相机控制器使用,如果在运行时选择模拟,会使用旁观者类进入场景来操控相机
下图为官方的框架关系结构图
接下来,我们看一下官方的demo 动作RPG中,在游戏模式中实现了什么,
在主菜单场景中,游戏模式只是简单的实现了添加ui到视口,和初始化了全局的设置,并保存到本地
而在战斗场景中,事件图表中,播放开场动画,显示剩余游玩事件,开始游戏的处理,游戏结束处理以及重新开始游戏处理
在GameMode里面还有一个图表,用于处理敌人的生成逻辑
PlayerController 玩家控制器
玩家控制器是我们和游戏中的角色沟通的媒介,我们需要通过玩家控制器实现对游戏中的角色的控制,所以,很多操作都是需要通过玩家控制器实现。
比如,操作的输入,需要通过玩家控制器输入,如果你在游戏中,打开ui界面,此时,将无法再控制游戏中的角色攻击,移动等操作,都需要通过玩家控制器实现。
比如,你需要操作玩家,其实需要设置玩家输入模式游戏
你也可以通过玩家控制器设置不接受任何输入,比如进入自动模式
游戏是否暂停,你也需要通过玩家控制器实现
如果你只允许UI相应用户输入
你也可以设置鼠标光标是否显示
你可以在玩家控制器中获取到控制的角色对象
你甚至可以将角色的移动和朝向直接写在角色控制器里面
在官方案例动作RPG项目中,将玩家查看的HUD界面放到了角色控制器中
还有暂停游戏,打开角色属性栏,设置角色自动战斗
还有过场动画的播放和停止事件(播放停止以后,将创建HUD,战斗模式开始新的游戏,让GameMode生成怪物)
还有打开背包事件的逻辑
以及背包更新,或者修改了装备的更新,都会去更新HUD(On Screen Controls 变量),还调用了角色身上的创建所有持有武器事件,创建所有持有武器事件放到控制角色身上的原因是删除的时候,可以直接根据角色去删除,不需要通过PlayerController去实现。
PlayerCameraManager 相机管理器
PlayerCameraManager 用于为一个特定的玩家管理摄像机。它定义最终查看属性,供渲染器这类的其它系统使用。PlayerCameraManager的功能类似于一个用来查看世界的 “虚拟眼球”。 它可以直接计算最终摄像机属性,也能够在其它物体或者影响摄像机的Actor之间混合(从一个CameraActor混合到另外一个)。
摘自官网 https://docs.unrealengine.com/5.2/zh-CN/cameras-in-unreal-engine/
可以通过节点获取到当前相机管理器
可以通过相机管理器获取到当前相机的位置和旋转
AssetManager 资产管理器
资产管理器是一个独特的全局对象,可以根据不同的项目进行覆盖和自定义。它提供了一个管理资产的框架,可将内容划分为数据块,对应项目的上下文,而同时保证虚幻引擎 4 松散打包架构 的优势。unreal会自动处理资产的加载与卸载,在某些情况下需要更精确的控制资产,则需要使用到资产管理器。
资产管理器对象是一个单例,有且唯一,负责主资产的发现与加载。
摘自:https://docs.unrealengine.com/4.27/zh-CN/ProductionPipelines/AssetManagement/
主资产和次要资产
说到资产管理器,不得不提的就是主资产和次要资产。资产管理器通过主资产ID可直接对其进行操作。默认的主资产只有关卡资产,其它资产均为次要资产(有办法设置次要资产为主资产)。
主资产在编辑器中最明显的表现就是鼠标悬停在资产上面,查看其有没有主资产相关的信息
主资产类型和主资产命名一起组成了主资产ID(PrimaryAssetID)
创建自定义的资源管理器
创建自定义的资源管理器需要书写代码,类继承至UAssetManager
然后在项目设置中,找到一般设置默认类,设置资产管理类
获取主资产
既然资产管理器可以对主资产进行操作,那么,资产管理器如何实现获取操作
最简单的就是在项目设置里面,资产管理器中,添加要扫描的主资产类型,并设置相应的目录
主资产类型我们可以自定义名称的,然后在蓝图中,可以通过类型去获取相应的资源列表
在官方项目动作RPG中,它在动画实例中加载了三种类型的资产,可以看到,键就是使用主资产类型设置的
资源管理器先关操作
像之前的动作RPG中的,通过主资产类型获取主资产ID列表
异步加载可以有效的防止卡顿,最主要的,如果主资产不需要使用,我们还可以卸载掉,减少内存使用率。
主资产ID中包含两项内容,它们共同组成了主资产ID,分别是主资产类型,和主资产名称
主资产类型就是在资产管理器中设置的类型,名称则是当前的文件名称
创建自定义主资产
要实现自定义主资产的创建,你需要通过c++代码创建,我们可以实现创建一个基于UPrimaryDataAsset创建一个自定义类,而且必须要实现GetPrimaryAssetId方法的覆盖
首先创建一个基于PrimaryDataAsset的c++类
我第一次编译直接给我整了一个大的,因为我自己装了一个插件,导致编译一直无法通过,最后,将project用记事本打开,将那个插件删除了以后才能够打开。
然后它会自动打开vs,给你编译代码,编译完成后,会有两个文件,一个.h结尾的是头文件,一个.cpp的是资源文件,我们需要在数据资产里面覆盖GetPrimaryAssetId,我这里将主资产类型设置成了一个变量,
首先创建一个蓝图,类继承c++类
在蓝图中,我创建了三个变量,而且还可以修改默认的主资产类型,如果这个类型设置为None,这个资产将不再是主资产。
创建数据资产
创建数据资产需要你选择数据资产类,数据资产也相当于是一个实例,但是创建的蓝图是无法从资源管理器获取到的
然后在数据资产里面定义相关的数据
然后在资产管理器中设置好主资产类型,资产基础类和目录
在蓝图中,获取主资产ID列表中,会多出你自定义的Weapon项
然后获取第一项,通过异步进行加载
加载完成后,将类型转换为定义的资产类型,并打印目标的类
然后运行此逻辑,只要把类名打印出来,就实现了。