今年开始接触这个框架,最开始技术选型的时候是准备使用这个框架进行弱联网小游戏的开发,做一些休闲小游戏的开发。由于一些原因项目在demo阶段告一段落,算起来使用这个框架一共是4个月左右的时间。不知道下一个项目还会不会采用这个框架,利用缓冲时间来整理一下技术以及自己在项目中的收获。

一.框架介绍:

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

GameFramework的官方网站:https://gameframework.cn/

GameFramework的开源地址: https://github.com/EllanJiang/GameFramework/

具体的接入使用细节在官方网站都可以进行查阅,这里说一些常见的注意点:

1.在E神的github可以看到这个框架是分了一下层的,Framework是可以脱离unity单独使用的,在unity中的使用需要结合UnityGameFramework,Runtime中的代码是与Mono紧密结合的。在UnityGameFramework中prefabs文件夹中可以找到一个GameFramework的预制体,这个预制体可以看成一个基础组件,放在初始场景中贯穿整个游戏。

2.GF通过组件控制各个模块,GameEntry是整个游戏的入口,负责初始化框架的基础组件。

private static void InitBuiltinComponents(){Base = UnityGameFramework.Runtime.GameEntry.GetComponent<BaseComponent>();Config = UnityGameFramework.Runtime.GameEntry.GetComponent<ConfigComponent>();DataNode =  UnityGameFramework.Runtime.GameEntry.GetComponent<DataNodeComponent>();DataTable =  UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();Debugger =  UnityGameFramework.Runtime.GameEntry.GetComponent<DebuggerComponent>();Download =  UnityGameFramework.Runtime.GameEntry.GetComponent<DownloadComponent>();Entity = UnityGameFramework.Runtime.GameEntry.GetComponent<EntityComponent>();Event = UnityGameFramework.Runtime.GameEntry.GetComponent<EventComponent>();Fsm = UnityGameFramework.Runtime.GameEntry.GetComponent<FsmComponent>();Localization =  UnityGameFramework.Runtime.GameEntry.GetComponent<LocalizationComponent>();Network =  UnityGameFramework.Runtime.GameEntry.GetComponent<NetworkComponent>();ObjectPool =  UnityGameFramework.Runtime.GameEntry.GetComponent<ObjectPoolComponent>();Procedure =  UnityGameFramework.Runtime.GameEntry.GetComponent<ProcedureComponent>();Resource =  UnityGameFramework.Runtime.GameEntry.GetComponent<ResourceComponent>();Scene = UnityGameFramework.Runtime.GameEntry.GetComponent<SceneComponent>();Setting =  UnityGameFramework.Runtime.GameEntry.GetComponent<SettingComponent>();Sound = UnityGameFramework.Runtime.GameEntry.GetComponent<SoundComponent>();UI = UnityGameFramework.Runtime.GameEntry.GetComponent<UIComponent>();WebRequest =  UnityGameFramework.Runtime.GameEntry.GetComponent<WebRequestComponent>();CD = UnityGameFramework.Runtime.GameEntry.GetComponent<CDComponent>();Timer = UnityGameFramework.Runtime.GameEntry.GetComponent<TimerComponent>();SimpleEvent =  UnityGameFramework.Runtime.GameEntry.GetComponent<SimpleEventComponent>();}

下面CD Timer SimpleEvent 是根据项目需要添加的,其他组件的功能在官网的介绍中都可以了解到,基本上很多组件单独拎出来解释都可以作为一篇教程,后面也会介绍自己使用的比较多的组件。

3.这个框架是通过流程组件来设置游戏的当前的一个状态。

首先选择初始流程,一般会在初始流程中初始化config的信息等,每个流程实质都是一个状态机,都有OnInit(),OnEnter(),OnUpdata(),OnLeave(),方法,在进入流程的时候做一些初始化方法。

 public override void OnEnter(ProcedureOwner procedureOwner){base.OnEnter(procedureOwner);// 构建信息:发布版本时,把一些数据以 Json 的格式写入  Assets/GameMain/Configs/BuildInfo.txt,供游戏逻辑读取。//GameEntry.BuiltinData.InitBuildInfo();// 语言配置:设置当前使用的语言,如果不设置,则默认使用操作系统语言。InitLanguageSettings();// 变体配置:根据使用的语言,通知底层加载对应的资源变体。InitCurrentVariant();// 画质配置:根据检测到的硬件信息 Assets/Main/Configs/DeviceModelConfig 和用户配置数据,设置即将使用的画质选项。InitQualitySettings();// 声音配置:根据用户配置数据,设置即将使用的声音选项。InitSoundSettings();// 默认字典:加载默认字典文件 Assets/GameMain/Configs/DefaultDictionary.xml。// 此字典文件记录了资源更新前使用的各种语言的字符串,会随 App 一起发布,故不可更新。//GameEntry.BuiltinData.InitDefaultDictionary();}

切换流程直接调用ChangeState()方法,我们项目在launch之后会进到一个热更流程,检查版本更新,进行资源热更,然后在进入到load流程开始正式的load资源,然后在进入到main流程和game流程等开始游戏。在load流程中有一个坑,在编辑器模式下直接调PreloadResources()方法就可以了,但是打出真机包这里要改为GameEntry.Resource.InitResources(OnInitResourcesComplete)然后在OnInitResourcesComplete的回调中去调PreloadResources().

4.这个框架很多数据是直接采用配表的方式,在load的DatatableNames中写入配好的表的名称,在编辑器有一个GenerateDataTables可以直接将表数据转化成vs的数据格式,可以自己定义好数据类接收这些数据,例如我们项目的部分角色数据按如下方式获取:

public RoleData(int entityId, int typeId) : base(entityId, typeId){IDataTable<DRRole> dtRole = GameEntry.DataTable.GetDataTable<DRRole>();DRRole dtRoleData = dtRole.GetDataRow(typeId);if (dtRoleData == null){return;}assetPath = dtRoleData.AssetPath;MaxHp = dtRoleData.MaxHP;currentHp = dtRoleData.MaxHP;Defence = dtRoleData.Defense;lockDistance = dtRoleData.LockDistane;MoveSpeed = dtRoleData.MoveSpeed;m_RotateSpeed = dtRoleData.RotateSpeed;}

二.框架组件

框架组件的调用比较方便,因为在GameEntry中已经初始化了组件,并且组件是一直存在项目中的,调用组件只需要GameEntry点出组件名称就可以调用组件的方法了。框架组件这里我就按在我们项目中的使用顺序介绍一些比较重要的吧。

1.UI组件:这里需要关注的一般就是UIGroups,根据自己的项目设置好UI分层。我们项目暂时是分的4层,最底层是放类似血条UI等,中间层放一些选择界面,顶层放摇杆界面,属性介绍界面等;最顶层算是弹出框之类的。指定好depth就ok了。然后在InstanceRoot中指定Canvas,配好表以后就可以使用了。打开面板调用的是OpenUIForm传入配好的id就可以打开面板了,关于如何读取表中数据,以及如何去进行显示可以查看

public static int? OpenUIForm(this UIComponent uiComponent, UIFormId uiFormId, object  userData = null){return uiComponent.OpenUIForm((int)uiFormId, userData);}public static int? OpenUIForm(this UIComponent uiComponent, int uiFormId, object  userData = null){IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);if (drUIForm == null){Log.Warning("Can not load UI form '{0}' from data table.",  uiFormId.ToString());return null;}string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);if (!drUIForm.AllowMultiInstance){if (uiComponent.IsLoadingUIForm(assetName)){return null;}if (uiComponent.HasUIForm(assetName)){return null;}}return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName,  Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, userData);}

最后跳进OpenUIForm中查看可以在UIManager中找到打开界面的具体操作:

/// <summary>/// 打开界面。/// </summary>/// <param name="uiFormAssetName">界面资源名称。</param>/// <param name="uiGroupName">界面组名称。</param>/// <param name="priority">加载界面资源的优先级。</param>/// <param name="pauseCoveredUIForm">是否暂停被覆盖的界面。</param>/// <param name="userData">用户自定义数据。</param>/// <returns>界面的序列编号。</returns>public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority,  bool pauseCoveredUIForm, object userData){if (m_ResourceManager == null){throw new GameFrameworkException("You must set resource manager first.");}if (m_UIFormHelper == null){throw new GameFrameworkException("You must set UI form helper first.");}if (string.IsNullOrEmpty(uiFormAssetName)){throw new GameFrameworkException("UI form asset name is invalid.");}if (string.IsNullOrEmpty(uiGroupName)){throw new GameFrameworkException("UI group name is invalid.");}UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName);if (uiGroup == null){throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' is  not exist.", uiGroupName));}int serialId = ++m_Serial;UIFormInstanceObject uiFormInstanceObject =  m_InstancePool.Spawn(uiFormAssetName);if (uiFormInstanceObject == null){m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName);m_ResourceManager.LoadAsset(uiFormAssetName, priority,  m_LoadAssetCallbacks, OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm,  userData));}else{InternalOpenUIForm(serialId, uiFormAssetName, uiGroup,  uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData);}return serialId;}

因为这个项目暂停的比较早,UI界面这一块其实基本是还没开始做的,可能还有很多可以学习的地方,以后涉及到再慢慢总结。

2.实体组件:Entity同样是先指定实体组,一般根据类型指定来设置实体组吧,相同类型放一个组,每一个组还可以设置对象池的个数等等,一般使用默认的就好。同样在EntityExtension中写对应的show方法,传入对应的数据类就行了。数据类中可以指定实体的出生位置。类似于这样调用:

/// <summary>/// 出场特效/// </summary>/// <param name="index">特效的序号</param>/// <param name="bornPos">特效的位置</param>/// <param name="ownerId">挂载的父实体的Id</param>protected void ApperanceEffect(int index,Vector3 bornPos,int ownerId){EffectData effectData = new EffectData(GameEntry.Entity.GenerateSerialId(),  Data.SkillModel.EffectIdArray[index], ownerId){Position = bornPos};GameEntry.Entity.ShowEffect(effectData);}

实体都要继承EntityBase,所以每个实体都是有OnInit,update,OnHide方法的,可以很好地执行实体的逻辑。实体这里有一个比较好用的方法OnAttachTo可以实现把当前实体绑定到其他实体的某个节点上,然后当前实体会跟着父实体移动和旋转。

在加载多个实体的时候出现加载非常慢的问题,这个是对框架的资源加载方式不熟练导致的,后面会专门写一篇记录自己对这个框架的资源加载的理解。

3.FSM有限状态机组件

我们项目使用了框架的有限状态机去做主角的状态切换,并跟动画状态机结合进行角色的动画播放。首先是写了一个状态基类继承FsmState需要指定有限状态机持有者类型,我这边给的是角色实体基类。然后就是根据需求创建角色的其他状态,Idle,Attack,Die,Run,Skill状态。在角色实体基类里面需要初始化状态机。

public GameFramework.Fsm.IFsm<IRoleEntityLogic> RoleFsm;           //当前角色的状态机
private void InitRoleFsm(){FsmState<IRoleEntityLogic>[] roleStates = new FsmState<IRoleEntityLogic>[]{new RoleIdleState(),new RoleRunState(),new RoleAttackState(),new RoleDieState(),new RoleSkillState(),};//创建状态机RoleFsm = GameEntry.Fsm.CreateFsm(this, roleStates);//启动状态机RoleFsm.Start<RoleIdleState>();}

把状态注册进状态机然后指定初始状态启动状态机,就可以正常执行逻辑了,非常方便。

基本上掌握了框架流程组件,配表读表,UI组件,实体组件,可以正常开发了,但是框架很多东西还是要自己深入去看去了解,自己其实到现在也没有深入理解这个框架,很多复杂的东西东西框架已经帮我们做好了,但是自己不去理解的话还是很容易掉坑里。

暂时写到这吧,后面会在补充框架的使用和项目完成其他的功能,框架的资源加载,声音控制器,Easytouch人物移动控制,简单事件系统,技能系统,buff系统,背包系统,血条显示,渲染合批,常用工具类,性能分析工具等,这些都会分篇来回顾总结。

GameFramework使用教程相关推荐

  1. 简易版GameFramework游戏框架搭建教程(一)前言

    GameFramework(以下简称GF),是由Ellan开发的一款开源Unity游戏框架,以下是来自官网的简介: Game Framework 是一个基于 Unity 5.3+ 引擎的游戏框架,主要 ...

  2. GameFramework教程✨十一、使用 AssetBundle 编辑工具

    目录

  3. GameFramework教程✨三、流程

    目录

  4. GameFramework教程✨十七、数据表

    目录

  5. GameFramework教程✨二十三、Web请求

    目录

  6. GameFramework教程✨二、GameEntry,游戏入口

    目录

  7. GameFramework教程✨一、本专栏概述及注意事项

    目录

  8. GameFramework教程✨五、界面,即UI

    目录

  9. GameFramework教程✨十四、AB包资源初始化(单机模式),与资源预加载

    目录

最新文章

  1. pandas读取字典(dict)数据
  2. MySQL隐式转化整理
  3. PowerDesigner基本使用 - 创建业务处理模型BPM
  4. final cut pro的vlog模版的需要region of interests和导出视频注意事项
  5. MariaDB备份和恢复
  6. 【视频】谷歌大佬30分钟让你入门机器学习(2019谷歌I/O资源分享)
  7. iis php 内存溢出,iis-7.5 - HTTP错误405.0-不允许方法IIS 7.5模块staticfilemodule - 堆栈内存溢出...
  8. jave-1.0.2.jar
  9. 美图录爬虫(requests模块,re模块)
  10. sumif计算机怎么学,SUMIF 带给Excel不一样的条件求和
  11. 华为路由器 linux 口,华为路由器以太网口配置命令
  12. 每日一生信--blast2go本地化(终极版)
  13. 安装webpack powershell出现 Set-ExecutionPolicy : 对注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell
  14. 设计模式C++描述----01.单例(Singleton)模式
  15. 什么是主动式计算机用户,电脑电源主动PFC是什么意思
  16. 第8章 中医证型关联规则挖掘代码调整
  17. Harmonious
  18. 狼的故事11:以牙还牙
  19. Unity实用功能之读写Excel表格
  20. 管理学总论之管理者的角色和技能

热门文章

  1. 温升对母线槽的隐患问题
  2. Detours学习之十四:Detour 4.0 的编译
  3. 宋宝华:论程序员的时代焦虑与焦虑的缓解
  4. 《编程之美》读书笔记(四): 卖书折扣问题的贪心解法
  5. vb.net 教程 20-4 库存管理系统3.9 入库管理(FormStorageIn)
  6. 奥比中光Orbbec Astra Pro RGBD 3D视觉传感器在ROS(indigo和kinetic)使用说明 rgb depth同时显示
  7. 喜欢你,也喜欢你的雀斑
  8. Java 打怪升级路线图,大佬是这样炼成的!一定要收藏
  9. https和http有什么区别(内附详细分析)
  10. 安慰剂检验(stata)