版权申明:

  • 本文原创首发于以下网站:
  1. 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123
  2. 优梦创客的官方博客:https://91make.top
  3. 优梦创客的游戏讲堂:https://91make.ke.qq.com
  4. 『优梦创客』的微信公众号:umaketop
  • 您可以自由转载,但必须加入完整的版权声明!

概要

  • 在init.cs中:

    • 首先,await到DownloadBundle完毕(即使是异步的)
    • 然后,Game.Hotfix.GotoHotfix()负责启动Hotfix层,进而启动UILogin画面
    • 本节就主要分析UILogin的启动流程,以及其事件处理

先上Hotfix入口代码:

public void LoadHotfixAssembly()
{
Game.Scene.GetComponent<ResourcesComponent>().LoadBundle($"code.unity3d");
GameObject code = (GameObject)Game.Scene.GetComponent<ResourcesComponent>().GetAsset("code.unity3d", "Code"); byte[] assBytes = code.Get<TextAsset>("Hotfix.dll").bytes;
byte[] pdbBytes = code.Get<TextAsset>("Hotfix.pdb").bytes; #if ILRuntime
Log.Debug($"当前使用的是ILRuntime模式");
// ...
#else
Log.Debug($"当前使用的是Mono模式"); this.assembly = Assembly.Load(assBytes, pdbBytes); Type hotfixInit = this.assembly.GetType("ETHotfix.Init");
this.start = new MonoStaticMethod(hotfixInit, "Start"); this.hotfixTypes = this.assembly.GetTypes().ToList();
#endif Game.Scene.GetComponent<ResourcesComponent>().UnloadBundle($"code.unity3d");
} public void GotoHotfix()
{
#if ILRuntime
ILHelper.InitILRuntime(this.appDomain);
#endif
this.start.Run();
}
  • 由于ILRT模式无法调试,所以开发阶段选择Mono模式,下面的分析也是以Mono方式为例的,这也是ET作者建议的工作流程(开发用Mono,发布用ILRT)
  • LoadHotfixAssembly:得到start方法
    • start方法实际就是ETHotfix命名空间下的Init类的Start方法
  • GotoHotfix:执行start方法

ETHotfix.Init.Start():

namespace ETHotfix
{
public static class Init
{
public static void Start()
{
#if ILRuntime
if (!Define.IsILRuntime)
{
Log.Error("Model层是mono模式, 但是Hotfix层是ILRuntime模式");
}
#else
if (Define.IsILRuntime)
{
Log.Error("Model层是ILRuntime模式, Hotfix层是mono模式");
}
#endif try
{
// 注册热更层回调
ETModel.Game.Hotfix.Update = () => { Update(); };
ETModel.Game.Hotfix.LateUpdate = () => { LateUpdate(); };
ETModel.Game.Hotfix.OnApplicationQuit = () => { OnApplicationQuit(); }; Game.Scene.AddComponent<UIComponent>();
Game.Scene.AddComponent<OpcodeTypeComponent>();
Game.Scene.AddComponent<MessageDispatcherComponent>(); // 加载热更配置
ETModel.Game.Scene.GetComponent<ResourcesComponent>().LoadBundle("config.unity3d");
Game.Scene.AddComponent<ConfigComponent>();
ETModel.Game.Scene.GetComponent<ResourcesComponent>().UnloadBundle("config.unity3d"); UnitConfig unitConfig = (UnitConfig)Game.Scene.GetComponent<ConfigComponent>().Get(typeof(UnitConfig), 1001);
Log.Debug($"config {JsonHelper.ToJson(unitConfig)}"); Game.EventSystem.Run(EventIdType.InitSceneStart);
}
catch (Exception e)
{
Log.Error(e);
}
}
}
}
  • 注意:第86行,和上一课的分析类似,也是在初始化阶段通过引发事件来创建UI界面,只不过这次的事件是InitSceneStart

InitSceneStart_CreateLoginUI.Run():

namespace ETHotfix
{
[Event(EventIdType.InitSceneStart)]
public class InitSceneStart_CreateLoginUI: AEvent
{
public override void Run()
{
UI ui = UILoginFactory.Create(); // 注意:这次是调用Hotfix层的UILoginFactory的Create工厂方法来创建UI实体,下面会重点分析
Game.Scene.GetComponent<UIComponent>().Add(ui); // 注意:这次是添加Hotfix层的UIComponent组件,其代码与模型层类似,不再赘述
}
}
}

UILoginFactory.Create():

namespace ETHotfix
{
public static class UILoginFactory
{
public static UI Create()
{
try
{
ResourcesComponent resourcesComponent = ETModel.Game.Scene.GetComponent<ResourcesComponent>();
resourcesComponent.LoadBundle(UIType.UILogin.StringToAB());
GameObject bundleGameObject = (GameObject)resourcesComponent.GetAsset(UIType.UILogin.StringToAB(), UIType.UILogin);
GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject); UI ui = ComponentFactory.Create<UI, string, GameObject>(UIType.UILogin, gameObject, false); ui.AddComponent<UILoginComponent>();
return ui;
}
catch (Exception e)
{
Log.Error(e);
return null;
}
}
}
}```
- 注意:
- 这次加载的是从AB包加载UILogin预制体资源,而上节课是从Resources文件夹加载UILoading资源,不一样!
- 虽然通过ComponentFactory.Create创建的Entity还是UI Entity,但该Entity添加的组件和上节课不一样,是“UILoginComponent”! # UILoginComponent事件处理:
```csharp
namespace ETHotfix
{
[ObjectSystem]
public class UiLoginComponentSystem : AwakeSystem<UILoginComponent>
{
public override void Awake(UILoginComponent self)
{
self.Awake();
}
} public class UILoginComponent: Component
{
private GameObject account;
private GameObject loginBtn; public void Awake()
{
ReferenceCollector rc = this.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>();
loginBtn = rc.Get<GameObject>("LoginBtn");
loginBtn.GetComponent<Button>().onClick.Add(OnLogin);
this.account = rc.Get<GameObject>("Account");
} public void OnLogin()
{
LoginHelper.OnLoginAsync(this.account.GetComponent<InputField>().text).Coroutine();
}
}
}
  • 事件处理在UILoginComponent.Awake方法中被注册
  • 在Entity.AddComponent时,AwakeSystem.Awake()->UILoginComponent.Awake方法链会被调用

Unity进阶之ET网络游戏开发框架 03-Hotfix层启动的更多相关文章

  1. Unity进阶之ET网络游戏开发框架 02-ET的客户端启动流程分析

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  2. Unity进阶之ET网络游戏开发框架 01-下载、运行

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  3. Unity进阶之ET网络游戏开发框架 04-资源打包

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  4. Unity进阶之ET网络游戏开发框架 05-搭建自己的第一个Scene

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  5. Unity进阶之ET网络游戏开发框架 08-深入登录成功消息

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  6. Unity进阶之ET网络游戏开发框架 06-游客登录

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  7. Unity进阶之ET网络游戏开发框架 07-修正游客登录的异步BUG

    版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...

  8. Unity进阶技巧 - 动态创建UGUI

    前言 项目中有功能需要在代码中动态创建UGUI对象,但是在网上搜索了很久都没有找到类似的教程,最后终于在官方文档中找到了方法,趁着记忆犹新,写下动态创建UGUI的方法,供需要的朋友参考 你将学到什么? ...

  9. Unity进阶----Lua语言知识点(2018/11/08)

    国内开发: 敏捷开发: 集中精力加班堆出来第一个版本 基本没啥大的bug 国外开发: 1).需求分析: 2).讨论 3).分模块 4).框架 5).画UML图(类图class function)(e- ...

随机推荐

  1. Android开发-实现第三方APP跳转

    自己创建一个按钮: <Button android:id="@+id/btn_button" android:layout_width="fill_parent&q ...

  2. dockerfile 制作镜像

    # Set the base image to UbuntuFROM ubuntu # File Author chenghanMAINTAINER chenghan ################ ...

  3. 洛谷:P2952 [USACO09OPEN]牛线Cow Line:题解

    题目链接:https://www.luogu.org/problemnew/show/P2952 分析: 这道题非常适合练习deque双端队列,~~既然是是练习的板子题了,建议大家还是练练deque, ...

  4. 记一次愚蠢的经历--String不可变性

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 记录一次在写代码时愚蠢的操作,本文涉及到的知识点:S ...

  5. SQLServer 问题(一)

    出现这种错误: [DBNETLIB][ConnectionOpen(Connect()).]SQL Server 不存在或拒绝访问 数据库错误 原因: 1.查看是不是没有在数据库中添加数据库服务器地址 ...

  6. C#中线程间操作无效: 从不是创建控件 txtBOX 的线程访问它。

    delegate void 委托名(方法名); void 方法名() { if(txtBox.invokeRequered) { 委托名 d=new 委托名(); txtBox.invoke(d); ...

  7. linux初学者-虚拟机联网篇

    linux初学者-虚拟机联网篇 在虚拟机的使用过程中,本机可以连接WIFI直接上网,但是有时候需要用到虚拟机的联网,那么在本机联网的情况下,虚拟机怎么联网呢?接下来将介绍如何在本机已经连接到WIFI的 ...

  8. 华三F100 系列防火墙 - 浮动路由联动NQA 实现双线路自动切换

    公司 有两条公网线路,一条移动作为日常主用线路,一条联通作为备用线路. 为了实现主备线路自动切换,配置了浮动路由 但浮动路由只能在 主用接口为down状态时才能浮出接管默认路由.如果故障为非物理链路故 ...

  9. web设计_9_CSS常用布局,响应式

    一个完整的页面和其中的组件该如何具备灵活性. 怎么样利用CSS来实现无论屏幕.窗口以及字体的大小如何变化,都可以自由扩展和收缩的分栏式页面. 要决定使用流动布局.弹性布局还是固定宽度的布局,得由项目的 ...

  10. 用wxpy管理微信公众号,并利用微信获取自己的开源数据。

    之前了解到itchat 乃至于 wxpy时 是利用tuling聊天机器人的接口.调用接口并保存双方的问答结果可以作为自己的问答词库的一个数据库累计.这些数据可以用于自己训练. 而最近希望获取一些语音资 ...