热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档

马肤

温馨提示:这篇文章已超过470天没有更新,请注意相关的内容是否还可用!

摘要:这份文档是一份详细的GameFramework讲解笔记,内容涵盖了万字以上的篇幅,旨在帮助读者了解GameFramework的使用和相关知识。该文档注重实践性和操作性,通过讲解实例和案例,使读者更好地理解和掌握GameFramework的应用。这份笔记文档对于游戏开发者来说是一份宝贵的资源,能够帮助他们更高效地开发游戏。
往期文章分享
  • 点击跳转=>《导航贴》- Unity手册,系统实战学习
  • 点击跳转=>《导航贴》- Android手册,重温移动开发

    本文约15千字,新手阅读需要27分钟,复习需要12分钟 【收藏随时查阅不再迷路】

    👉关于作者

    众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!

    专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)

    有什么需要欢迎私我,交流群让学习不再孤单。

    热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第1张

    👉前提

    这是小空坚持写的Unity新手向系列,欢迎品尝。

    小空为了方便更多的人(新手)看明白,使用的汉字,真实项目尽量使用英文规则昂。

    新手(√√√)

    大佬(√)

    这段时间学习个Unity框架并且准备应用到实际项目中,但是因为作者神龙见首不见尾,没有什么比较详细的文档,学习困难,不过好在作者将框架所有内容开源了,再次记录下学习过程。

    👉实践过程

    😜Game Framework简介导读

    问:她到底是个什么玩意?

    答:Game Framework 是一个基于 Unity 引擎的游戏框架,主要对游戏开发过程中常用模块进行了封装,很大程度地规范开发过程、加快开发速度并保证产品质量。

    支持5.3以上到现在所有的Unity版本。

    问:那她到底有什么功能呢?

    答:相当多哦,包含全局配置,日志等工具集,数据表维护,提示器,下载,事件,文件系统,有限状态机,本地化,网络,对象池,流程,资源管理,场景管理,游戏配置,声音,界面,Web请求。-详情参见文末功能备注(链接)

    问:她能帮助我什么?

    答:帮你快速开发项目以及搭建良好的产品框架,顺便提高自己的业务能力。

    问:那应该怎么找到她,学习她呢?

    答:Github地址- https://github.com/EllanJiang/GameFramework/

    API手册- https://gameframework.cn/api/

    😜初识Game Framework

    完整的 Game Framework 内容包含三部分:

    • GameFramework – 封装基础游戏逻辑,如数据管理、资源管理、文件系统、对象池、有限状态机、本地化、事件、实体、网络、界面、声音等,此部分逻辑实现不依赖于 Unity 引擎,以程序集的形式提供。

    • UnityGameFramework.Runtime – 依赖 UnityEngine.dll 进行对 GameFramework.dll 的补充实现。为了方便兼容 Unity 的各个版本,此部分已经以代码的形式包含在 Unity 插件中。

    • UnityGameFramework.Editor – 依赖 UnityEditor.dll 进行对工具、Inspector 的实现。为了方便兼容 Unity 的各个版本,此部分已经以代码的形式包含在 Unity 插件中。

      我们直接从官网下载unitypackage插件包,我的是2020.7.30版本。导入后如下图:

      热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第2张

      热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第3张

      😜如何使用?

      工程目录及作用如下:

      热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第4张

      • Libraries 存放 GameFramework.dll 核心框架和一些框架必需的第三方库(当前只有一个开源 zip 压缩算法库)
      • Prefabs 存放 GameFramework.prefab 预制体,用于快速创建一个游戏框架启动场景
      • Scripts 存放 UnityGameFramework 的全部 Runtime 和 Editor 代码
      • Example.unity 是一个含有 GameFramework.prefab 预制体的空场景,作为游戏启动的场景
      • ProcedureExample.cs 是一个示例流程代码文件,示例将以这个流程作为启动流程。

        运行项目后发现Game场景有个浮动小窗口,这是框架提供的调试器窗口

        热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第5张

        • Console 选项卡在运行时(当然可以在移动设备上)默认按不同日志类型,以不同的日志颜色回显最近的日志。点击某条日志可以查看详细的日志和堆栈详请
        • Information 选项卡显示设备硬件信息、游戏版本和资源信息,输入信息,传感器等
        • Profiler 选项卡显示性能调试相关的信息,内存,对象池,网络等信息
        • Other 选项卡可以用来配置调试框窗口的大小缩放(一般不用修改)、执行内存回收操作或者执行重启游戏操作等

          作者英语不是很好,为了用起来快捷将里面部分英文翻译成了中文,看起来确实顺畅多了,哈哈

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第6张

          😜场景

          我们先把从官方下载的.unitypackage包导入,然后新建一个场景对应新建一个脚本。

          然后打开GameFramework/Prefabs目录,将里面的GameFramework预制体拖到Hierarchy视图里(预制体里面包含了多种基本组件)

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第7张

          接着打开【ScriptSceneStart】脚本,让她继承自【ProcedureBase】,看过案例教程后我们知道框架是用流程来管理的,所以我们的场景第一步就要继承【ProcedureBase】,让她成为流程。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第8张

          之后我们将场景和框架中的流程绑定起来。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第9张

          然后打开框架日志,运行程序即可看到效果

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第10张

          注:Unity已经有打印日志的工具了,为什么我们还要用框架中的呢。

          因为我们不仅仅需要在编译器中查看,有时候发布出去后在其他平台或设备上查看日志就需要你自己写一套日志方案(这多不符合懒的思想啊)。既然框架提供了这些,为什么不用呢?现成的他不香吗?

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第11张

          难道我们游戏只有一个场景吗?不存在的,必然是多个场景存在,那多个场景在框架中又怎么切换呢?或者说怎么切换流程呢?

          我们再新建个场景【Scene_Set】,脚本为【ScriptSceneSet】

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第12张

          运行场景【Scene_Start】后直接切换场景到【Scene_Set】,但是你会发现场景【Scene_Start】没有卸载

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第13张

          原因在于基础场景里挂载着框架的组件【GameFramework】,你用人家的框架,还想干掉人家的框架,开玩笑呢?销毁了你还框什么架,所以这个场景在整个程序运行过程中不销毁的。

          除了这个普通的场景加载后或者切换场景后,发现也没销毁,原因是框架不会自动销毁,需要你主动销毁。

          使用Scene.GetLoadedSceneAssetNames();可以获得加载的场景数组

          Scene.UnloadScene(“场景资源名称”);来卸载,当然了框架会自动排除上面说的挂载着框架的场景

          有一点要记得,切换场景的时候Scene.LoadScene(“这需要完整的路径和后缀名”,this);

          思路接着往下走,场景切换后我们对应的控制和逻辑脚本也就应该切换到对应的了,所以我试了试:

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第14张

          就这张图的代码来看,切换场景后,下一个场景也有打印日志消息,但是实际的运行结果却没有,这令小空疑惑。而且去检查了流程组件的内容,都打对勾了。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第15张

          等等,流程!既然是流程,那是不是得自己控制流程的切换,框架将场景切换和流程切换分开,留给开发人员实现,岂不有更多的实现空间?然后小空去翻找官方案例,果然有个继承自【ProcedureBase】的【ProcedureChangeScene】类,往下翻找到了关键句【ChangeState(procedureOwner);】,关键字【ChangeState】这个必定是切换流程的,至于切换到哪个就需要在符号里写进去了。回去改小空的Demo:

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第16张

          运行后:(成功,果然Nice,框架方便之处渐渐浮出)

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第17张

          😜UI

          经过上一节搞定了场景,接着就要开搞UI了,UI也不是直接就在场景中全部展示出来了,有些需要我们动态从资源中加载。

          我直接上个步骤图,看的更形象一些。

          1. 代码中用UIComponent组件加载UI预制体,重点注意第二个参数,将UI进行了分组和层级管理
          2. 回到编辑器中找到GameFramework-UI物体,里面有个UI Groups属性要设置
          3. 预制体需要挂载脚本,脚本需要继承UIFormLogic脚本,这是UI控制脚本,这样才能交给框架进行管理

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第18张

          这一套下来,真的是如行云流水般顺畅,越来越方便了。继续学习看看框架到底还有多少惊喜。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第19张

          顺畅个屁啊,小空又跑回来更新了,学到后面发现怎么UI也出不来,哎,就是跟你玩,就是不出。不小心踩了个坑。

          UI,UI,都说了是UI,我竟然没搞Cnavas,糊涂啊。根据上图步骤,第三步预制体是你布局好UI控件然后将整个Canvas做成预制体。成功后是这样的(下图):

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第20张

          还有一点要留意,运行后你会发现在场景里并没有找到UI组件,其实不然,框架通过UIComponent 创建的的UI 统统都会跑到Framework 里面 UI下面。无论你打开几个场景UI始终都是在框架所在场景内的。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第21张

          如上图所示,全部在【UI-UI Form Instances】下

          😜日志管理工具

          在任何编程语言中,日志都是重中之重,是逻辑分析的首要工具,所以我们首要任务就是要学会使用框架的日志工具。

          首先是基础的Log日志(如图),和系统的一样输出到Unity编辑器的控制台

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第22张

          发布的产品,最好关闭所有日志或者仅开启错误及以上级别日志,自己开发调试的时候可以自定义开启日志级别。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第23张

          除了在控制台打印,我们使用框架更多的可能是将日志保存到文件的功能。

          自定义一个类继承DefaultLogHelper

          using GameFramework;
          using System;
          using System.Collections;
          using System.Collections.Generic;
          using System.IO;
          using System.Text;
          using UnityEngine;
          using UnityGameFramework.Runtime;
           
          internal class FileLogHelper : DefaultLogHelper
          {
          //设置日志文件保存路径-你可以自定义,也可以使用系统的
          private readonly string CurrentLogPath = Utility.Path.GetRegularPath(Path.Combine(Application.persistentDataPath, "current.log"));
          private readonly string PreviousLogPath = Utility.Path.GetRegularPath(Path.Combine(Application.persistentDataPath, "previous.log"));
          public FileLogHelper()
          {
              Application.logMessageReceived += OnLogMessageReceived;
              try
              {
                  //每次运行的时候将日志替换,就像队列一样
                  if (File.Exists(PreviousLogPath))
                  {
                      File.Delete(PreviousLogPath);
                  }
                  if (File.Exists(CurrentLogPath))
                  {
                      File.Move(CurrentLogPath, PreviousLogPath);
                  }
              }
              catch
              {
              }
          }
           
              private void OnLogMessageReceived(string logMessage, string stackTrace, LogType logType)
              {
                  string log = Utility.Text.Format("[{0}][{1}] {2}{4}{3}{4}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), logType.ToString(), logMessage ?? "", stackTrace ?? "", Environment.NewLine);
                  try
                  {
                      File.AppendAllText(CurrentLogPath, log, Encoding.UTF8);
                  }
                  catch
                  {
                  }
              }
          }
          

          然后在挂在了Base脚本的物体中选择使用即可,就这么简单!!!

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第24张

          运行的时候,也可以在调试器窗口中找到各个路径位置。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第25张

          😜事件订阅

          既然咱要用她就一定要先说说她的优点:

          她简化了组件间的通信,分离了事件的发送者和接收者,大大降低了耦合度。举个栗子:

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第26张

          前段时间的【黑悟空】实机演示,比如悟空的状态,经验值,怪物的血量等内容,会随时有着对应的变化,比如怪物死亡,人物获得经验以及结束判断等等,一次事件发生N多事件要对应变化,要是一个个主动修改你调我/我调你的,调来调去逻辑线不混乱才怪,又不玩捆绑S。所以我们要由主动变被动,我发个广播,谁想听我号令谁就注册下,不想听你不注册没影响,解耦效果显著。小空是Android出身,Android里的EventBus订阅用的贼爽,所以第一时间就学习了这个框架的订阅事件

          这就达到了,某件事件变化,执行了注册的地方会收到消息,自己处理自己的逻辑。被订阅者发,多个订阅者接收。

          来来来,我们看看到底怎么使用;

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第27张

          😜第一步

          需要先获得Event组件

          EventComponent eventComponent = UnityGameFramework.Runtime.GameEntry.GetComponent();

          😜第二步

          订阅事件

          eventComponent.Subscribe(OpenUIFormSuccessEventArgs.EventId, InitUISuccess);

          订阅事件第一个参数是内置的,【OpenUIFormSuccessEventArgs】是初始化打开界面成功事件,第二个参数是你自己声明的函数,界面完成后会触发这个函数。官方还有更多内置函数,详情看下方表格图。

          😜第三步

          加载UI

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第28张

          😜第四步

          在回调函数中打印下,看看有没有接收到消息。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第29张

          😜第五步

          记得在OnLeave方法解除注册昂。你都离开这个流程了,就不要再费心去监听别的事情了。否则会造成内存垃圾昂。

          运行结果:

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第30张

          成了。就这么简单?爱作妖的小空这时候又有想法了:实际开发不可能这么简单,可能有N多个UI,N多个时间,这要是多了又是什么样的?不急,接着试验

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第31张

          一运行发现哎都回调了方法啊。这个不错,如果再利用第四个参数传递自定义数据,返回后根据不同的数据做不同的处理岂不快哉。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第32张

          666,但是还有个疑问,仔细看上面【OpenUIForm】里面的第三个参数-优先级,我尝试输入不同的级别运行后发现并没有想象中的那样【这是一只猫】最先执行。小空就去赶紧看了官方案例,又有发现:官方案例区分的是资源优先级-字体、声音音乐/场景等这种大类别。应该不是用于小小的同级(比如都是UI)。这个留待后续再深入。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第33张

          小空学到这感觉基本使用可以了,这和Android的EventBus类似啊,在以后的实践学习中希望能发现框架也有EventBus的粘性事件和跨组件监听。补充一个框架内置组件图:

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第34张

          怎么样?使用起来是不是很简单?仿佛在那遥远的山村听到了有人说,

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第35张

          😜创建实体

          经历前面文章创建UI的过程,这一步操作起来就顺心多了,坑也少了。

          😜第一步

          同样需要创建预制体(物体模型)

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第36张

          😜第二步

          预制体上需要挂载继承了【EntityLogic】的脚本

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第37张

          😜第三步

          走走走,预制体出来我们就要开始创建了,代码先获取实体组件再创建实体

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第38张

          这和UI基本如出一辙昂,再回忆回忆和UI都是预制体,传递的参数都是预制体路径和分组。等等-分组,差点忘记了需要在框架的基础组件中添加分组

          小空在学习木头前辈的教程中留意到:这种带有路径的预制体加载方式,实际打包后会不会出现调用不到的问题。给出的答案是:不管是打不打包,框架都会处理好,无需操心。

          第四个参数需要注意下,她可以传递【this】,进而在控制中调用流程中的方法。

          官网案例也是这么做的:【ProcedureMenu】流程打开UI【GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this);】传递的是【this】,进而【MenuForm】中可以在【OnOpen】方法获取这个流程类【m_ProcedureMenu = (ProcedureMenu)userData;】,这样就可以调用流程中的方法,比如切换另一个流程,事实上官网也是这么做的。

          😜第四步

          分组机制管理器很多物体超级方便,不可缺少

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第39张

          组里面还有四个参数,小空暂时还没学到这些,保留知识。

          【instance auto release inerval】-实例自动释放间隔

          【instance auto release inerval】-实例容量

          【instance expire time】-实例过期/失效时间

          【instance priority】-实例优先级

          😜第五步

          运行成功

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第40张

          在这强调下,时刻要记得创建的东西都是在【GameFramework】框架组件下。

          😜第六步

          操作起来怎么这么顺利,就没遇到个让人劈叉的问题?

          小空还真疏忽了,在UI中就说过创建后一定要在框架下写上分组,在这小空又忘了,报错如下:不过小空现在已经记住了,时刻保持组名和代码中的参数保持一致。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第41张

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第42张

          在这进了一个坑(不承认我学艺不精),找搞C++的姐请教后实践,详情请看文章:

          快速代码补全-不同关键字权限,不同程序集自动生成的有微差别

          补充:当一个物体有灯光信息的话,不适合做成预制体,这会导致从预制体初始化出来的物体效果不对。

          原因是:在一个物体或者光源从场景中变成一个prefab的时候,那些和烘焙相关的信息被重置,是一个稳妥的做法,因为你做成一个prefab,意味着它可能被使用于不同场景,那残留的之前的烘焙信息也就没有意义了。反过来说,如果保留,你在别的场景中apply了这些信息,那其他场景的效果就错了。无法通用的信息,保留在prefab中,是危险的。

          烘焙信息是跟着场景走的,如果一个物体或者光源和场景没有关联了,那它身上存储的烘焙信息也就没有意义了。

          所以推荐布置在场景中,用切换流程切换场景来实现,普通的物体可以设置成预制体。官方案例也是这么搞的。

          👉其他

          📢作者:小空和小芝中的小空

          📢转载说明-务必注明来源:https://zhima.blog.csdn.net/

          📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

          温馨提示:点击下方卡片获取更多意想不到的资源。

          热乎的过万字GameFramework讲解笔记文档,热万字的GameFramework深度讲解笔记文档 第43张


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码