MyFramework 用法说明(二):工程目录和启动流程
上一篇完成安装和初始化以后,工程中会生成一套默认模板。
这一篇主要说明:这些目录分别放什么代码,以及框架启动时从哪里开始执行。
一、初始化后的主要目录
初始化完成后,重点关注 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.asmdef
Assets/Scripts/HotFix/HotFix.asmdef
Assets/Scripts/AutoGenerated/AutoGenerated.asmdef
框架包内部还有:
Frame_Base
Frame_Game
Frame_HotFix
可以简单理解成:
Frame_Base 框架最底层,非热更
Frame_Game 框架非热更层
Game 项目非热更层
Frame_HotFix 框架热更层
HotFix 项目热更层
AutoGenerated 自动生成代码
实际项目里,建议遵守一个原则:
能放 HotFix 的业务逻辑,就不要放 Game。
Game 层只保留启动、热更前资源更新、平台接入、热更入口等必要代码。
三、启动入口:GameEntry
初始化时,框架会把 GameEntry 脚本挂到启动场景的 GameEntry 节点上。
默认代码很简单:
public class GameEntry : GameEntryBase
{
public override void Awake()
{
base.Awake();
Game framework = new();
framework.init();
setFrameworkAOT(framework);
}
}
这里做了三件事:
GameEntryBase 负责 Unity 生命周期转发,比如:
Update
FixedUpdate
LateUpdate
OnApplicationQuit
也就是说,真正每帧驱动框架的入口在 GameEntryBase 中。
四、非热更入口:Game
Game 是非热更部分的项目框架入口。
默认代码核心是:
public class Game : GameFramework
{
public override void init()
{
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>();
}
protected void gameInitFrameSystem(){}
protected void gameRegiste()
{
LayoutRegister.registeAllLayout();
}
}
这里重点看几个位置。
gameInitFrameSystem 用来注册非热更层自己的框架系统。
比如以后需要在热更前使用某些管理器,可以放这里:
protected void gameInitFrameSystem()
{
// registeFrameSystem<XXXManager>((com) => { mXXXManager = com; });
}
gameRegiste 用来注册非热更层资源、布局等内容。
默认会调用:
LayoutRegister.registeAllLayout();
最后进入:
mGameSceneManager.enterScene<LaunchScene>();
也就是说,非热更启动后,第一个进入的是 LaunchScene。
五、LaunchScene:热更前流程
LaunchScene 是非热更层的启动场景流程。
默认代码:
public class LaunchScene : GameScene
{
public override void assignStartExitProcedure()
{
mStartProcedure = typeof(LaunchSceneVersion);
mExitProcedure = typeof(LaunchSceneExit);
}
public override void createSceneProcedure()
{
addProcedure<LaunchSceneVersion>();
addProcedure<LaunchSceneExit>();
}
}
它有两个流程:
LaunchSceneVersion 启动热更流程
LaunchSceneExit 退出启动场景流程
LaunchSceneVersion 里默认调用:
public class LaunchSceneVersion : SceneProcedure
{
public override void init()
{
base.init();
HybridCLRSystem.launchHotFix(null, null, null);
}
}
这里就是热更启动入口。
编辑器下会直接从当前 AppDomain 中查找 HotFix 程序集。
真机热更版则会加载热更 DLL,然后启动 GameHotFix。
六、热更入口:GameHotFix
热更启动后,框架会查找 GameHotFix 类型,并创建热更实例。
默认代码:
public class GameHotFix : GameHotFixBase<GameHotFix>
{
protected override void registerAll()
{
LayoutRegisterHotFix.registeAll();
}
protected override void initFrameSystem()
{
//registeFrameSystem<NetManager>((com) => { mNetManager = com; });
}
protected override string getAndroidPluginBundleName()
{
return ANDROID_PLUGIN_BUNDLE_NAME;
}
protected override Type getStartGameSceneType()
{
return typeof(MainScene);
}
}
这里有三个重点。
registerAll 用来注册热更层内容,比如热更 UI:
protected override void registerAll()
{
LayoutRegisterHotFix.registeAll();
}
initFrameSystem 用来注册热更层框架系统:
protected override void initFrameSystem()
{
// registeFrameSystem<NetManager>((com) => { mNetManager = com; });
}
getStartGameSceneType 决定热更启动完成后进入哪个场景:
protected override Type getStartGameSceneType()
{
return typeof(MainScene);
}
所以真正的业务主场景默认从 MainScene 开始。
七、MainScene:热更业务主场景
模板中的 MainScene 结构如下:
public class MainScene : GameScene
{
public override void assignStartExitProcedure()
{
mStartProcedure = typeof(MainSceneLoading);
mExitProcedure = typeof(MainSceneExit);
}
public override void createSceneProcedure()
{
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
{
protected override void onInit(SceneProcedure lastProcedure)
{
base.onInit(lastProcedure);
// 加载主界面
// 初始化玩家数据
// 进入主城流程
}
}
MainSceneExit 中默认调用:
genericExit(0);
一般用于卸载当前场景的布局和资源,避免离开场景后还有资源残留。
八、UI 注册入口
非热更 UI 注册在:
Assets/Scripts/Game/UI/LayoutRegister.cs
默认结构:
public class LayoutRegister
{
public static void registeAllLayout()
{
//registeLayout<UIDemo>((script) => { mUIDemo = script; });
}
}
热更 UI 注册在:
Assets/Scripts/HotFix/UI/LayoutRegisterHotFix.cs
默认结构:
public class LayoutRegisterHotFix
{
public static void registeAll()
{
// auto generate start
// auto generate end
}
}
后续使用 UI 代码生成器时,热更 UI 的注册代码通常会写入 auto generate 区域。
九、推荐修改位置
刚接入框架时,建议先只改这些文件:
Assets/Scripts/Game/Common/GameDefine.cs
Assets/Scripts/Game/Game/Game.cs
Assets/Scripts/HotFix/Game/GameHotFix.cs
Assets/Scripts/HotFix/GameScene/MainScene/MainSceneLoading.cs
Assets/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,而是直接从当前工程中的程序集启动热更逻辑。
这样做的好处是:
编辑器开发和真机运行的业务入口基本一致,后续调试热更层代码会更方便。
上一篇完成安装和初始化以后,工程中会生成一套默认模板。
这一篇主要说明:这些目录分别放什么代码,以及框架启动时从哪里开始执行。
浙公网安备 33010602011771号