GameFramework解析:声音 (Sound)
前言
虽然现在稍微像样点的游戏项目都接上了像Wwise这类音频引擎,大概率用不上这类声音模块,不过GF的声音模块还是非常值得没有游戏音效管理经验的同学学习,声音模块也属于GF中较为轻量的一个模块,本文将简单讲解。
先抛出几个问题:
对于同一类型的音效,我希望在设置面板上做统一的音量大小调整,例如游戏设置中常有的BGM、UI、队友语音、场景音效等音量调节,但开发过程中不断有新的音效加入,如何做同一类型音效的音量的统一管理?
像RTS这类单位非常多,攻击频率也很高的游戏,如果每次攻击/受击都播放音效,那游戏整体声音将会十分混乱,如何在框架层面控制同个类型的声音的最大同时播放数量?
在问题2的基础上,如果我们只播放有限数量的音效,如何加入优先级控制,实现在已达到播放上限时,继续尝试播放音效,如果新播放的音效优先级比当前正在播放的音效要高,那么就顶替掉正在播放的音效?
结构
SoundAgent
SoundAgent是声音代理,在Unity中我们一般使用AudioSource来播放声音,在GF的声音管理下,我们不再自行创建AudioSource来播放声音,而是使用SoundAgent来播 ...
GameFramework解析:对象池 (Object Pool)
对象池的作用
前文引用池篇已经讲过对象池相关作用,这里就不再重复了,GF中对象池与引用池作用类似,引用池用于普通的C#对象,而对象池则一般用于储存UnityEngine下的对象(如Unity中的GameObject对象),具体区别见下文。
对象池的实现
结构
对象池的实现我们可以把他分成3部分,上图中从上到下每一行就是一部分,分别是物体信息部分(抽象类ObjectBase,泛型类Object,结构体ObjectInfo),对象池部分(抽象类ObjectPoolBase,接口IObjectPool,泛型类ObjectPool,委托ReleaseObjectFilterCallback),对象池管理器部分(接口IObjectPoolManager,类ObjectPoolManager)。其中Object和ObjectPool是ObjectPoolManager的内部私有类。
物体部分
ObjectBase
对象池并没有直接储存目标对象,追溯到代码最下层,发现储存的是ObjectBase对象,而ObjectBase类型有一个object类型的m_Target字段,这个字段引用的对象才是我们 ...
GameFramework解析:引用池 (ReferencePool)
引用池的作用
GF这里的引用池其实就是我们平常说的对象池,在程序中主要是起到防止对象被频繁创建和销毁、减少gc、预加载等作用,若对对象池作用和原理不太清楚的话,可以参考书籍《游戏编程模式》中对象池模式一节。
GF中池子有两种,一种叫引用池,一种叫对象池,两者原理一样,但具体实现和针对的对象不同,引用池一般用来储存普通的C#类型对象,而对象池则一般用于储存UnityEngine下的对象(如Unity中的GameObject对象),两者区别将在下一篇对象池篇中详细分析。本文将详细说一下其中的引用池。
引用池的实现
结构
引用池部分主要由4个部分组成,静态类ReferencePool、ReferencePool的内部类ReferenceCollection、结构体ReferencePoolInfo和接口IReference。
IReference接口
IReference接口只包含一个Clear方法,此方法会在对象回收池被调用,每一个需要被引用池储存的类型都需要实现此接口,以能清空当前状态,恢复到初始状态,供下次使用。
ReferenceCollection池子类
游戏中对象池通常不止一个 ...
GameFramework解析:界面(UI)
UI模块结构
UIGroup
UIGroup是GF的UI模块的一大功能,它提供了游戏中常见的UI栈,当不同的UIFrom实例处于同一个UIGroup中时,会以栈的形式去维护他们的层级和生命周期,一个UIGroup中永远只有一个UIForm处于最上层,已存在的界面会被新打开的界面覆盖,而且会收到被覆盖事件。UIGroup内部并没有直接以栈结构去维护上述功能,而是用链表的方式,表头代表栈顶,表尾代表栈底,这样的好处是UIGroup可以提供接口可以激活任意界面到最上层,虽然这一操作不符合栈的结构,但无疑能为我们的业务带来更大的灵活性。另外我们还可以通过UIGroup去控制一组相关联的UI的整体层级以及暂停状态。
当我们有一系列相关联的UI,他们同一时刻只有一个处于最上层,且需要感知相互间的打开关闭状态时,我们就可以把他们归到同一个UIGroup中。
UIGroup直接受UIManager管理,各个UIGroup管理各自的UIForm。
对外提供属性Get
Name:UIGroup的名字
Depth:UIGroup的深度
Pause:UIGroup的暂停状态
UIFormCount:包含 ...
GameFramework解析:编写游戏启动流程
GameFramework解析:编写游戏启动流程
前言
本文主要说明基于GameFramework框架去设计一个通用的支持热更的启动流程。以下流程与官方Demo的流程一致。
启动流程图
ProcedureLaunch
进行一些游戏启动的必要的初始化,支撑后续的启动流程,如:
初始化构建信息:如版本检测和资源更新的URL信息,更新界面资源等
语言设置:若有上次设置记录则使用上次设置记录,若没有则使用默认或系统语言
初始化变体:根据当前语言设置,通知后续底层加载对应的资源变体
初始本地化文本资源:根据当前语言设置选择对应的文本
以上涉及到的资源,包括更新信息文件、更新界面资源、本地化文本等都是build-in资源,也就是发布时就在包内,不可更新的。试想我们发布的游戏是一个仅仅支撑启动的包,所有游戏资源都需要在启动后的热更流程中下载,但一些启动图片,以及热更时的界面本身也是需要资源的,需要给出基本的文本、确认框等,以提供给玩家确认是否下载、下载进度预览,还涉及到更新请求的URL。这部分资源就是我们需要放在包内的不可更新资源,主要用来支撑热更的启动,而ProcedureLaunch流程就 ...
GameFramework解析:流程 (Procedure)
流程模块的作用
流程在实现上其实是对有限状态机的一个封装,如果未读本系列文章中的有限状态机解析篇,建议可以先看完有限状态机的解析再看本文。
那么流程是解决什么问题呢?我们来看看GF官方文档的定义:
贯穿游戏运行时整个生命周期的有限状态机。通过流程,将不同的游戏状态进行解耦将是一个非常好的习惯。对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。如果想增加流程,只要派生自 ProcedureBase 类并实现自己的流程类即可使用。
实际上就是用有限状态机把游戏整体状态管理了起来,我们应该让游戏在生命周期中的任何一刻,都属于某个流程中,且同时只会处于一个流程状态中。虽然实现简单,但起到了很好的逻辑划分作用,也很方便后期调整各流程的顺序,甚至可以构建一颗流程树,根据不同环境走不同的流程分支。
笔者曾经经历过这样的情景:项目原本是进入游戏后先走更新流程,再登录的,后来渠道方要求要把登录步骤放在前面,登录后再走版本检测、更新流程,由于那个项目对启 ...
GameFramework解析:有限状态机(FSM)
什么是有限状态机
有限状态机的概念相信很多同学都清楚了,不清楚的可以参考一下书籍《游戏编程模式》中状态模式一节,里面讲得十分清楚。FSM在游戏中常用于玩家控制、怪物AI、UI状态、游戏流程控制等。
有限状态机的实现
结构
有限状态机的实现我们可以把他分成3部分,上图中从上到下每一行就是一部分,分别是状态部分(FsmState),状态机部分(FsmBase、IFsm、Fsm)以及状态机管理器部分(IFsmManager、FsmManager)。
状态类FsmState
FsmState为有限状态机状态基类,所有用于有限状态机的状态都需要继承自此类,泛型参数T需要传入状态持有者类型。
OnInit、OnEnter、OnUpdate、OnLeave、OnDestroy为状态的生命周期方法,其中OnInit和OnDestroy分别在状态创建和销毁时调用,只会调用一次,而OnEnter、OnLeave分别在进入状态和离开状态时调用,可能会调用多次,而OnUpdate则是在进入该状态后每帧调用。
ChangeState用于切换到下一状态。ChangeState实际是用该方法传入的FSM对象调用 ...
GameFramework解析:整体架构
整体架构
GF层
包含框架中各个模块的具体实现,不依赖于引擎
各个模块若有需要引擎传递的参数,可通过UGF层的Component在初始化时传入
若需要调用依赖于引擎实现的接口,可定义对应的IHelper接口,并在UGF层实现接口,GF层只调用,不关心具体实现
UGF层
实现框架中需要依赖Unity的逻辑,把框架与引擎解耦
作为Game层与GF层之间的桥梁
实例化并初始化框架各个模块
借助Unity的Editor扩展,实现各个模块参数的可视化配置
上图UGF与GF的关系其实简化了,实际上每个模块的XXXManager都会实现了对应的IXXXManager接口,UGF只会直接引用接口,不会直接引用Manager
Game层
游戏逻辑,只与UGF层直接接触
启动流程
Unity要启动游戏,至少要有一个自定义的Monobehaviour脚本挂在场景中的GameObject上,来作为我们游戏的逻辑入口,那么任何框架要在Unity中启动也不例外,需要依赖Monobehaviour的生命周期方法启动。
GF中每个模块都有一个对应的Component(继承自Monobehaviour), ...
GameFramework解析:塔防Demo
简介
这是一款基于开源框架GameFramework(以下简称GF)实现的塔防游戏Demo。Demo原型是Unity官方放在Assets Store上的Demo Tower Defense Template。此项目是对Demo原型使用GF进行再实现以及扩展,主要用于个人对GF的学习和实践,也给其他学习GF的同学一个参考。
Github链接
TowerDefense-GameFramework-Demo
版本信息
Unity 2019.4.1f1
GameFramework 2020.12.31
Tower Defense Template 1.4
游戏简介
游戏预览
游戏介绍
游戏是塔防类型,总共五个关卡,每个关卡的地形环境、产生的敌人、以及可使用的塔都不一样。玩家利用获得的能量根据具体情况选择合适的塔,并建造在适当的位置来阻止敌人攻击基地。
能量
玩家在关卡开始有少量初始能量,通过击杀敌人和建造能量塔均可以获得能量,能量用于建造和升级塔。
塔
加农炮塔:高射速、低伤害
火箭炮塔:高AOE伤害(仅攻击地面敌人)
激光炮塔:低射速、高伤害、远射程
能量塔:每隔一段时间产 ...
GameFramework解析:开篇
GameFramework解析:开篇
框架简介
官方博客:https://gameframework.cn
Github地址:https://github.com/EllanJiang/GameFramework/
下面是GameFramework官方简介的缩略版,更具体的可以去到上面GameFramework的GitHub地址README看~
GameFramework 是一个基于 Unity 引擎的游戏框架,主要对游戏开发过程中常用模块进行了封装,很大程度地规范开发过程、加快开发速度并保证产品质量。
在最新的 Game Framework 版本中,包含以下 19 个内置模块,后续我们还将开发更多的扩展模块供开发者使用。
1.全局配置 (Config)
2.数据结点 (Data Node)
3.数据表 (Data Table)
4.调试器 (Debugger)
5.下载 (Download)
6.实体 (Entity)
7.事件 (Event)
8.文件系统 (File System)
9.有限状态机 (FSM)
10.本地化 (Localization)
11.网络 (Netwo ...