MyFramework 用法说明(二):工程目录和启动流程

上一篇完成安装和初始化以后,工程中会生成一套默认模板。
这一篇主要说明:这些目录分别放什么代码,以及框架启动时从哪里开始执行。


一、初始化后的主要目录

初始化完成后,重点关注 Assets/Scripts 下的几个目录:

Assets/Scripts
 ├── AutoGenerated
 │   ├── HybridCLRGenerate
 │   └── Obfuz
 ├── Game
 │   ├── Common
 │   ├── Game
 │   ├── GameScene
 │   └── UI
 └── HotFix
     ├── Common
     ├── Game
     ├── GameScene
     └── UI

其中:

AutoGenerated    自动生成代码目录,不建议手动改
Game             非热更业务层
HotFix           热更业务层

GameHotFix 是最重要的两个目录。

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_* 代码。
如果只是正常开发项目,优先在 GameHotFix 目录中扩展。


十、启动流程总结

完整启动流程可以理解为:

start.unity
  ↓
GameEntry.Awake
  ↓
Game.init
  ↓
进入 LaunchScene
  ↓
LaunchSceneVersion
  ↓
HybridCLRSystem.launchHotFix
  ↓
创建 GameHotFix
  ↓
GameHotFix.start
  ↓
进入 MainScene
  ↓
MainSceneLoading
  ↓
项目主业务开始

如果不启用热更,编辑器下也会尽量走同一套入口,只是不会从外部加载 DLL,而是直接从当前工程中的程序集启动热更逻辑。

这样做的好处是:

编辑器开发和真机运行的业务入口基本一致,后续调试热更层代码会更方便。

posted @ 2026-07-10 00:46  _zhourui_h  阅读(8)  评论(0)    收藏  举报