
上一篇完成安装和初始化以后,工程中会生成一套默认模板。 这一篇主要说明:这些目录分别放什么代码,以及框架启动时从哪里开始执行。
一、初始化后的主要目录
初始化完成后,重点关注 Assets/Scripts 下的几个目录:
Assets/Scripts├── AutoGenerated│ ├── HybridCLRGenerate│ └── Obfuz├── Game│ ├── Common│ ├── Game│ ├── GameScene│ └── UI└── HotFix├── Common├── Game├── GameScene└── UI
其中:
AutoGenerated 自动生成代码目录,不建议手动改Game 非热更业务层HotFix 热更业务层
Game 和 HotFix 是最重要的两个目录。
Game 里的代码会直接参与主工程编译,一般放启动流程、热更前资源更新、平台初始化等不能随便热更的逻辑。
HotFix 里的代码属于热更业务层,项目主要玩法逻辑、主场景流程、热更 UI 注册等,后续都应该优先放这里。
二、几个程序集的关系
模板里默认会生成:
Assets/Scripts/Game/Game.asmdefAssets/Scripts/HotFix/HotFix.asmdefAssets/Scripts/AutoGenerated/AutoGenerated.asmdef
框架包内部还有:
Frame_BaseFrame_GameFrame_HotFix
可以简单理解成:
Frame_Base 框架最底层,非热更Frame_Game 框架非热更层Game 项目非热更层Frame_HotFix 框架热更层HotFix 项目热更层AutoGenerated 自动生成代码
实际项目里,建议遵守一个原则:
能放 HotFix 的业务逻辑,就不要放 Game。
Game 层只保留启动、热更前资源更新、平台接入、热更入口等必要代码。
三、启动入口:GameEntry
初始化时,框架会把 GameEntry 脚本挂到启动场景的 GameEntry 节点上。
默认代码很简单:
public class GameEntry : GameEntryBase{publicoverridevoidAwake(){base.Awake();Game framework = new();framework.init();setFrameworkAOT(framework);}}
这里做了三件事:
1. 调用 GameEntryBase.Awake()2. 创建非热更框架 Game3. 初始化 Game,并设置为 AOT 框架实例
GameEntryBase 负责 Unity 生命周期转发,比如:
UpdateFixedUpdateLateUpdateOnApplicationQuit
也就是说,真正每帧驱动框架的入口在 GameEntryBase 中。
四、非热更入口:Game
Game 是非热更部分的项目框架入口。
默认代码核心是:
public class Game : GameFramework{publicoverridevoidinit(){mOnInitFrameSystem += gameInitFrameSystem;mOnRegisteStuff += gameRegiste;mOnPackageName += () => { return ANDROID_PLUGIN_BUNDLE_NAME; };base.init();if (!isEnableHotFix() || isEditor()){mAssetVersionSystem.setAssetReadPath(ASSET_READ_PATH.STREAMING_ASSETS_ONLY);}else{mAssetVersionSystem.setAssetReadPath(ASSET_READ_PATH.SAME_TO_REMOTE);}mGameSceneManager.enterScene<LaunchScene>();}protectedvoidgameInitFrameSystem(){}protectedvoidgameRegiste(){LayoutRegister.registeAllLayout();}}
这里重点看几个位置。
gameInitFrameSystem 用来注册非热更层自己的框架系统。
比如以后需要在热更前使用某些管理器,可以放这里:
protectedvoidgameInitFrameSystem(){// registeFrameSystem<XXXManager>((com) => { mXXXManager = com; });}
gameRegiste 用来注册非热更层资源、布局等内容。
默认会调用:
LayoutRegister.registeAllLayout();最后进入:
mGameSceneManager.enterScene<LaunchScene>();也就是说,非热更启动后,第一个进入的是 LaunchScene。
五、LaunchScene:热更前流程
LaunchScene 是非热更层的启动场景流程。
默认代码:
public class LaunchScene : GameScene{publicoverridevoidassignStartExitProcedure(){mStartProcedure = typeof(LaunchSceneVersion);mExitProcedure = typeof(LaunchSceneExit);}publicoverridevoidcreateSceneProcedure(){addProcedure<LaunchSceneVersion>();addProcedure<LaunchSceneExit>();}}
它有两个流程:
LaunchSceneVersion 启动热更流程LaunchSceneExit 退出启动场景流程
LaunchSceneVersion 里默认调用:
public class LaunchSceneVersion : SceneProcedure{publicoverridevoidinit(){base.init();HybridCLRSystem.launchHotFix(null, null, null);}}
这里就是热更启动入口。
编辑器下会直接从当前 AppDomain 中查找 HotFix 程序集。 真机热更版则会加载热更 DLL,然后启动 GameHotFix。
六、热更入口:GameHotFix
热更启动后,框架会查找 GameHotFix 类型,并创建热更实例。
默认代码:
public class GameHotFix : GameHotFixBase<GameHotFix>{protectedoverridevoidregisterAll(){LayoutRegisterHotFix.registeAll();}protectedoverridevoidinitFrameSystem(){//registeFrameSystem<NetManager>((com) => { mNetManager = com; });}protectedoverridestringgetAndroidPluginBundleName(){return ANDROID_PLUGIN_BUNDLE_NAME;}protectedoverride Type getStartGameSceneType(){return typeof(MainScene);}}
这里有三个重点。
registerAll 用来注册热更层内容,比如热更 UI:
protectedoverridevoidregisterAll(){LayoutRegisterHotFix.registeAll();}
initFrameSystem 用来注册热更层框架系统:
protectedoverridevoidinitFrameSystem(){// registeFrameSystem<NetManager>((com) => { mNetManager = com; });}
getStartGameSceneType 决定热更启动完成后进入哪个场景:
protectedoverride Type getStartGameSceneType(){return typeof(MainScene);}
所以真正的业务主场景默认从 MainScene 开始。
七、MainScene:热更业务主场景
模板中的 MainScene 结构如下:
public class MainScene : GameScene{publicoverridevoidassignStartExitProcedure(){mStartProcedure = typeof(MainSceneLoading);mExitProcedure = typeof(MainSceneExit);}publicoverridevoidcreateSceneProcedure(){addProcedure(typeof(MainSceneLoading));addProcedure(typeof(MainSceneExit));}}
默认有两个流程:
MainSceneLoading 主场景加载流程MainSceneExit 主场景退出流程
MainSceneLoading 目前是空实现:
public class MainSceneLoading : SceneProcedure{protected override void onInit(SceneProcedure lastProcedure) { }protected override void onExit(SceneProcedure nextProcedure) { }}
实际项目可以从这里开始写主业务初始化,比如:
public class MainSceneLoading : SceneProcedure{protectedoverridevoidonInit(SceneProcedure lastProcedure){base.onInit(lastProcedure);// 加载主界面// 初始化玩家数据// 进入主城流程}}
MainSceneExit 中默认调用:
genericExit(0);一般用于卸载当前场景的布局和资源,避免离开场景后还有资源残留。
八、UI 注册入口
非热更 UI 注册在:
Assets/Scripts/Game/UI/LayoutRegister.cs默认结构:
public class LayoutRegister{publicstaticvoidregisteAllLayout(){//registeLayout<UIDemo>((script) => { mUIDemo = script; });}}
热更 UI 注册在:
Assets/Scripts/HotFix/UI/LayoutRegisterHotFix.cs默认结构:
public class LayoutRegisterHotFix{publicstaticvoidregisteAll(){// auto generate start// auto generate end}}
后续使用 UI 代码生成器时,热更 UI 的注册代码通常会写入 auto generate 区域。
九、推荐修改位置
刚接入框架时,建议先只改这些文件:
Assets/Scripts/Game/Common/GameDefine.csAssets/Scripts/Game/Game/Game.csAssets/Scripts/HotFix/Game/GameHotFix.csAssets/Scripts/HotFix/GameScene/MainScene/MainSceneLoading.csAssets/Scripts/HotFix/UI/LayoutRegisterHotFix.cs
大致分工如下:
GameDefine.cs 项目常量,比如安卓插件包名Game.cs 非热更层初始化GameHotFix.cs 热更层初始化MainSceneLoading.cs 主业务入口LayoutRegisterHotFix.cs 热更 UI 注册
不要一开始就去改框架包里的 Runtime/Frame_* 代码。 如果只是正常开发项目,优先在 Game 和 HotFix 目录中扩展。
十、启动流程总结
完整启动流程可以理解为:
start.unity↓GameEntry.Awake↓Game.init↓进入 LaunchScene↓LaunchSceneVersion↓HybridCLRSystem.launchHotFix↓创建 GameHotFix↓GameHotFix.start↓进入 MainScene↓MainSceneLoading↓项目主业务开始
如果不启用热更,编辑器下也会尽量走同一套入口,只是不会从外部加载 DLL,而是直接从当前工程中的程序集启动热更逻辑。
这样做的好处是:
编辑器开发和真机运行的业务入口基本一致,后续调试热更层代码会更方便。
夜雨聆风