想象一下一个完整游戏流程。
-
Loading界面。
-
进入场景。
-
弹出Menu菜单
-
加载角色。
-
角色动画系统-切换动画系统(默认-剑客-拳手)
-
角色皮肤切换
-
-
相机
-
角色可以接收到用户输入,然后进行前后左右移动。
-
角色可以接收到用户输入,释放技能,开枪。
-
物品交互,背包。
-
场景中还有其它的敌人,怪物AI。
游戏不断迭代,推出不同活动后。这时候需要一种插拔式的功能模块。
10. GameFeature
接下来讲解一下Lyra是如何实现以上的功能点的。
接下来讲解一下Lyra是如何实现以上的功能点的。
-
场景
- 通过AssetManager,获取到所有的FacingExperience资产,罗列出所有场景
GameMode(Eperience)的加载流程
- GameMode通过命令参数,WordSettingsd等方式来寻找 Experience
- 加载对应的GameMode下所有的重写类
- ULyraExperienceManagerComponent 来加载Experience中配置的所有参数。
- 执行Experiece中所有的Action
- 加载并且执行完所有的Acton。后调用加载完成的回调。
- 在完成必备的Experience后。加载GameFeature。
切换场景
- 根据FacingExperienceName创建场景Request。
- 创建Session。然后切换场景。
- 切换场景后加载GameMode的时候会通过第一步的Requeset中读取到对应的experience。来执行初始化流程。
UI
加载界面
采用CommonLoadingScreen插件完成。
- 在切換地图的时候注冊播放加载动画的事件。
[/Script/CommonLoadingScreen.CommonLoadingScreenSettings] LoadingScreenWidget=/Game/UI/Foundation/LoadingScreen/W_LoadingScreen_Host.W_LoadingScreen_Host_C |
UI框架
采用CommanGame插件+UIExtension插件一起实现。
UE5 Lyra项目UI框架拆解 - 知乎
- 配置文件中配置UIPolice。
[/Script/LyraGame.LyraUIManagerSubsystem]
DefaultUIPolicyClass=/Game/UI/B_LyraUIPolicy.B_LyraUIPolicy_C
- UIPolice指定对应的UI Layout 。主要用栈的结构来push或者pop layout。
- W_OverallUILayout - PrimaryGameLayout 设置所有UI Layout。
- 将ULyraActivatableWidget绑定到PrimaryGameLayout中。
- ULyraActivatableWidget 可以添加slot。后续可以动态将widget注册到对应的slot下面
角色
角色动画
UE5 白话Lyra动画系统 - 知乎
角色换装
Input
UE5 Lyra项目学习(四) 输入系统 - 知乎
- LyraSettingsLocal去注册输入的配置文件。
- Player Controller中调用SetupPlayerInputComponent
- 角色加载完成的时候调用加载HandleChangeInitState。在HandleChangeInitState调用InitializePlayerInput
- 注册InputMapping上下文。
- 绑定IA给对应的函数。
基础移动函数
技能函数
相机
TODO
GAS
[UnrealOpenDay2020]深入GAS架构设计 | EpicGames 大钊_哔哩哔哩_bilibili
https://gitee.com/gunsun/gas0
【Unreal】虚幻GAS系统快速入门 - 知乎
ASC
是整个GAS的基础组件。所有需要应用GAS的对象(Actor),都必须拥有GAS组件。也可以被赋予PlayerState(可以保存死亡角色的一些数据)一般只放在Character or PlayerState上
- 给角色注册能力ASC。通过ASC注册能力。
GA
角色的技能,包括攻击、疾跑、施法、翻滚、使用道具等,但不包括基础移动和UI
- 创建GA
- 接收输入激活能力GA。
GE
Ability对自己或他人产生影响的途径。 GE通常可以被理解为我们游戏中的buff。比如增益/减益效果(修改属性)。.用于修改属性,如增加50移动速度10s;还能配合GA实现更多玩法
GA能够绑定GE
AS
角色身上可以用float表示的属性,如生命值、体力值、魔力值等
GC
执行非游戏性相关的事情,比如音效,粒子特效,震屏等。
Ability Task
GA是在一帧内完成的,如果想要实现类似Wait的异步逻辑需要使用Task。
Gameplay task
Gameplay tag
完整的做一个GA
- 制作一个IA
- 绑定IA到IMC中。
- IMC注册到Input Subsystem中
- Input Subsystem来对IA逐个绑定对应的GA(通过GameTag来进行动态绑定)
- 制作一个GA。
- 将GA和IA绑定(通过Gametag进行动态绑定)
GameFeature
以Epic的自家游戏《堡垒之夜》为例,在其开发过程中随着每次赛季更新和活动内容迭代,也会很快就发现在玩家的Pawn类里开始充斥了几千行代码和上百个方法。逐渐就变得难以维护和难以查错。每次要做个活动加点新内容,就得在Pawn里添加特定的方法,开发过程逐渐就变成一种苦痛负担。
GameFeatures更进一步,允许在“游戏功能”这个颗粒度上进行解耦。
- 团队内新人更易上手,因为无需了解项目内其他内在工作机制,就能开发这些独立功能。他可以创建一个GameFeature然后独立的开发和测试。
- 更少漏洞,更易读代码。因为GameFeature本身是独立自包含的,因此代码天然更易于进行单元测试,可以自然地避免在构建时意外或偶然地依赖其他代码。
- 更轻松的在多个团队或项目中共享功能,可以更容易的迁移插件模块。在以往我们虽然也幻想一个游戏功能模块可以从一个项目复用到另一个项目,但这些一般都是偏向玩法无关的功能模块。因为游戏玩法模块一般来说都合作得很“紧密”,耦合得很深,一般也很难干净拆出来复用。而GameFeatues则至少为我们提供了一个解决方向,把一些独立玩法封装成GameFeatue,则至少大大增大了复用的可能。
- 更容易在大型或分布式开发环境中协作,模块化总是能促进团队协作,更少的担心自己的修改会干涉到别人的功能。
- 更容易在“快迭代更新”游戏中迭代功能,也能快速安全的删除出现问题的功能。当前游戏业是越来越多的网游了,因此这些长运营的游戏一般也都得不停的迭代更新功能,在开发过程中,把这些要更新出去的功能以GameFeature的方式一小包一小包的模块化分发出去,显然更容易开发和管理。万一哪个玩法包出错了,也可以及时动态的关闭它,而不影响游戏本体的功能。我知道有些小伙伴到这可能已经想到可以把GameFeature利用到热更新去了,但这就是另一个大话题了。提前来说,GameFeatues从机制上来说已经支持从网络上下载来加载,但目前来说实现还不够完善。当然把一个GameFeatue打包成pak,再下载加载也是可以的。
《InsideUE5》GameFeatures架构(二)基础用法
GeneralSetting
- UGameUserSettings
- Stores user settings for a game (for example graphics and sound settings), with the ability to save and load to and from a file.
- AssetManager:
- A singleton UObject that is responsible for loading and unloading PrimaryAssets, and maintaining game-specific asset references
- Games should override this class and change the class reference
- AWorldSettings
- The default world settings object, used primarily to set the default gameplay experience to use when playing on this map
- Game Viewport Client Class
- 修改客户端Viewport显示
- Local Player Class
- 在开发的时候玩家登陆服务器发送的默认数据可以通过复写LocalPlayer中的某些方法来实现(e.g GetGameLoginOptions),在继承LocalPlayer复写完成后在项目设置中修改LocalPlayerClass来进行替换默认的LocalPlayer类
实用技巧
- bool标识的一种表达方式
SQL |
- UPROPERTY(config)。配置默认参数。
- 继承父类,修改父类中的变量类型。
文章引用
- https://www.bilibili.com/video/BV14N4y1b7ym/?spm_id_from=333.788&vd_source=f91b86a9db5d272fcc792e207e0f6f89