MyFramework: 同样是 Unity 游戏开发框架,和 HTFramework 的设计取向有什么不同?(下)

上一篇主要对比了两个框架的整体定位、架构风格和 UI 开发方式。

这一篇继续看更偏工程落地的部分:

资源管理。

热更新。

配置表和协议生成。

网络与服务器协作。

对象池和工程检查。

文档生态与框架宣传方式。

还是先说明一点:这不是一篇"谁更强"的文章。

HTFramework 更像一个模块齐全、文档成熟、上手路径清晰的 Unity 客户端快速开发框架;MyFramework 更像一套从长期商业项目中沉淀出来的工程体系,重点不是模块数量,而是项目流程、工具链、热更分层和客户端服务器协作。HTFramework README 中列出了 UI、Resource、Procedure、Network、ObjectPool、ReferencePool 等大量通用模块;MyFramework README 则强调热更新分层、UI 代码生成、配置表工具链、网络协议代码生成、工程检查、低 GC、强生命周期控制以及客户端与服务器协作。

下面的代码都是简化示意,主要用于表达设计取向,不代表两个框架源码逐字实现。


一、资源管理:一个偏通用加载模式,一个偏项目资源管线治理

资源管理是 Unity 框架里绕不开的模块。

HTFramework 的 Resource 模块定位很清楚:它是资源管理器,主要用于动态加载资源,只支持异步加载,并且支持 Resource、AssetBundle、Addressables 三种加载模式,UI 模块也会自动调用资源管理器加载 UI 实体。

所以 HTFramework 的资源系统更像是一个统一的加载入口。

业务层关心的是:

我要加载什么资源?

资源来自 Resources、AssetBundle 还是 Addressables?

加载完成以后回调给我。

用简化代码表示,大概是这种感觉:

复制代码
复制代码
public class LoginProcedure
{
    public void Enter()
    {
        Main.m_Resource.LoadAsset<GameObject>(
            "Assets/Game/UI/Login.prefab",
            onLoadLoginUI
        );
    }

    private void onLoadLoginUI(GameObject prefab)
    {
        GameObject ui = Object.Instantiate(prefab);
        ui.SetActive(true);
    }
}

这种设计的优势是通用。

不同项目可能用 Resources,也可能用 AssetBundle,也可能用 Addressables。

框架提供统一入口,业务层不需要到处写不同加载逻辑。

而 MyFramework 的资源管理更偏"项目资源管线治理"。

MyFramework 当然也需要解决加载问题,但它更关心的是:

资源怎么分包?

AssetBundle 依赖是否合理?

有没有重复打包?

有没有环形依赖?

热更资源和非热更资源有没有互相引用?

图集、材质、Prefab、meta 是否符合项目规范?

资源路径能不能被配置表检查到?

资源问题能不能在编辑器阶段提前发现?

这类问题不只是 LoadAsset 能解决的。

比如一个资源路径写在配置表里,如果路径错了,最好不要等到运行时才报错。

更合理的是在编辑器阶段就检查:

复制代码
复制代码
public class EDItem : ExcelData
{
    public int    mID;          // 道具 ID
    public string mName;        // 道具名
    public string mIconPath;    // 图标路径
}

protected void checkItemIconPath(EDItem item)
{
    if (!mResourceManager.isResourceExist(item.mIconPath))
    {
        logError("道具图标不存在, id:" + item.mID + ", path:" + item.mIconPath);
    }
}

这就是 MyFramework 更偏工程体系的地方。

HTFramework 的 Resource 更强调"统一加载资源"。

MyFramework 的资源体系更强调"资源从配置、引用、打包、检查到运行时加载的完整链路"。

一个是加载模块。

一个是资源生产和使用流程。


二、热更新:一个是框架能力,一个是架构前提

HTFramework 有 Hotfix 模块,也有基于 Deployment + HybridCLR 的资源及代码热更新实战演示。HTFramework 的公开说明里,Hotfix 模块被描述为轻量级热更新框架;它也有单独的 HotfixDemo,用来演示基于 HTFrameworkDeployment 和 HybridCLR 的资源及代码热更新流程。

也就是说,HTFramework 是提供热更新能力的。

但从整体结构看,HTFramework 依然更像是一个模块化客户端框架,热更新是它的能力之一。

而 MyFramework 的热更新更像是整个框架的架构前提。

MyFramework README 里直接把代码按是否可热更进行了明确分层:

复制代码
复制代码
Frame_Base      -> 不可热更,最基础的框架代码
Frame_Game      -> 不可热更,项目非热更代码的框架
Game            -> 不可热更,项目应用层启动逻辑
Frame_HotFix    -> 可热更,框架层热更代码
HotFix          -> 可热更,项目应用层热更代码

它的依赖关系也围绕这个分层展开。

这个区别很关键。

如果热更新只是一个模块,那么项目可以先按普通结构写,后面再接热更。

但如果热更新是架构前提,那么项目一开始就要考虑:

哪些代码不能热更?

哪些代码必须放到热更层?

启动逻辑怎么保持稳定?

热更层怎么访问非热更层?

框架层热更和业务层热更怎么隔离?

生成代码应该输出到哪个程序集?

混淆和热更怎么配合?

用简化代码表示,MyFramework 更像这种分层思路:

复制代码
复制代码
// Game 层:不可热更,只负责启动和加载热更入口
public class GameEntry : MonoBehaviour
{
    private void Start()
    {
        initFrame();
        loadHotFixAssembly();
        startHotFix();
    }
}

// HotFix 层:可热更,真正的业务逻辑入口
public class HotFixGameEntry
{
    public void start()
    {
        mSceneManager.enterScene<SceneLogin>();
    }
}

这说明 MyFramework 的热更新不是"加一个 Hotfix 模块"这么简单。

它更关心项目长期运行时,哪些东西能改,哪些东西不能改。

HTFramework 的热更新能力更适合通用框架扩展。

MyFramework 的热更新分层更适合从一开始就按热更项目来组织代码。


三、配置表:一个偏 DataSet,一个偏配置生产工具链

配置表是 MyFramework 和 HTFramework 差异非常明显的地方。

HTFramework 有 DataSet 模块。它的说明是:任何需要存储数据的地方都可以定义为自定义数据集,包括预制配置文件、运行时生成的动态数据、从后台拉取的数据等。

这类设计更偏"数据集管理"。

比如可以把一个玩家数据、设置数据、运行时缓存数据定义成 DataSet:

复制代码
复制代码
public class PlayerDataSet
{
    public int    Level;
    public int    Exp;
    public string Name;
}

public class PlayerSystem
{
    public void LoadPlayerData()
    {
        PlayerDataSet data = Main.m_DataSet.GetDataSet<PlayerDataSet>();

        int level = data.Level;
        string name = data.Name;
    }
}

它解决的是运行时数据如何统一组织和访问。

而 MyFramework 的配置表工具链更偏"生产流程"。

MyFramework README 里明确写到,它使用 CSV 作为配置表格式,并配套自研表格编辑器,支持字段类型检查、枚举合法性检查、ID 唯一性检查、表格引用检查、资源路径检查、客户端代码生成、服务器代码生成、运行时代码检查逻辑生成。

这说明 MyFramework 的配置表不是简单读取一个数据文件,而是完整工作流:

复制代码
复制代码
CSV 配置表
    ↓
表格编辑器
    ↓
字段检查 / 引用检查 / 路径检查
    ↓
生成客户端表格代码
    ↓
生成服务器表格代码

比如一张道具表,最终可能生成这样的客户端代码:

复制代码
复制代码
public class EDItem : ExcelData
{
    public int    mID;          // 道具 ID
    public string mName;        // 道具名称
    public int    mQuality;     // 道具品质
    public string mIconPath;    // 图标路径
}

业务层使用时,不应该到处解析 CSV,而是直接查生成后的强类型数据:

复制代码
复制代码
protected void refreshItem(int itemID)
{
    EDItem item = mExcelItem.query(itemID);
    if (item == null)
    {
        logError("找不到道具配置, id:" + itemID);
        return;
    }

    mNameText.setText(item.mName);
    mIconImage.setSprite(item.mIconPath);
}

这就是两者差异。

HTFramework 的 DataSet 更像通用数据管理模块。

MyFramework 的配置表系统更像项目生产工具链。

尤其是客户端和服务器都要使用同一份配置时,MyFramework 这种配置生成就更有价值。

因为它解决的不只是"客户端如何读表",而是:

配置表能不能提前检查?

客户端和服务器字段是否一致?

ID 是否唯一?

枚举是否合法?

资源路径是否存在?

表之间引用是否正确?

这类问题越到大型项目越重要。


四、协议生成和网络:一个偏客户端通信模块,一个偏客户端服务器协作

HTFramework 有 Network 模块。README 中对 Network 的描述是:网络客户端模块,以单个通信管道为单位,每个管道支持 TCP/UDP 等协议,可以为每个管道定义通信消息格式,能胜任常见通信环境。

这种设计很适合客户端框架。

你需要通信,就创建一个网络管道。

你需要 TCP 或 UDP,就配置对应协议。

你需要定义消息格式,就在管道里处理。

简化示意:

复制代码
复制代码
public class LoginSystem
{
    public void Login(string account, string password)
    {
        LoginMessage msg = new LoginMessage();
        msg.Account = account;
        msg.Password = password;

        Main.m_Network.Send("GameServer", msg);
    }
}

而 MyFramework 的网络系统更偏客户端服务器配套。

MyFramework README 里写到,它有配套服务器框架 MyServerFramework,客户端与服务器可以共享协议生成、配置表生成等工具链,适合需要长期维护的中大型项目。它还明确列出了网络协议代码生成,支持消息类生成、字段序列化生成、字段反序列化生成、消息注册代码生成、客户端消息代码生成、服务器消息代码生成和手写逻辑代码保留。

这说明 MyFramework 的网络不是单纯客户端发包收包。

它关注的是:

协议怎么定义?

客户端消息代码怎么生成?

服务器消息代码怎么生成?

字段序列化和反序列化能不能自动生成?

消息注册能不能自动生成?

手写处理逻辑能不能保留?

客户端和服务器能不能共用同一套协议配置?

比如协议配置中定义了登录消息:

复制代码
复制代码
CSLogin
    string account
    string password

SCLoginRet
    int result
    long playerGUID

生成后的客户端可能是:

复制代码
复制代码
public class CSLogin : NetPacket
{
    public string mAccount;
    public string mPassword;

    public override void write(PacketWriter writer)
    {
        writer.writeString(mAccount);
        writer.writeString(mPassword);
    }
}

服务器也可以生成对应的读取代码:

复制代码
复制代码
class CSLogin : public NetPacket
{
public:
    std::string mAccount;
    std::string mPassword;

    void read(PacketReader& reader)
    {
        reader.readString(mAccount);
        reader.readString(mPassword);
    }
};

业务层只关心发送消息:

复制代码
复制代码
protected void onLoginButtonClick()
{
    CSLogin msg = new();
    msg.mAccount = mAccountInput.getText();
    msg.mPassword = mPasswordInput.getText();

    mNetManager.sendMessage(msg);
}

这就是 MyFramework 更偏 MMORPG / 网络游戏工程体系的地方。

HTFramework 的 Network 更像客户端网络通信模块。

MyFramework 的协议生成更像客户端和服务器之间的协作工具链。

对单机游戏、小型联网功能来说,HTFramework 这种 Network 模块已经足够。

对 MMO、长连接、协议数量多、客户端服务器强协作的项目来说,MyFramework 这种双端协议生成更贴近实际需求。


五、对象池和低 GC:一个提供通用池模块,一个强调生命周期和重置

HTFramework 的 ObjectPool 模块专用于 GameObject 类型对象池,用来复用 GameObject,减少频繁创建和删除对象时的开销;ReferencePool 则可用于任意引用类型对象池。

这是一套很标准的池化体系。

简化示意:

复制代码
复制代码
public class BulletSystem
{
    public void Fire()
    {
        GameObject bullet = Main.m_ObjectPool.Spawn("Bullet");
        bullet.transform.position = getFirePosition();
        bullet.SetActive(true);
    }

    public void Recycle(GameObject bullet)
    {
        bullet.SetActive(false);
        Main.m_ObjectPool.Despawn("Bullet", bullet);
    }
}

这类对象池主要解决:

少 Instantiate。

少 Destroy。

减少 GC。

提高频繁对象创建场景的性能。

而 MyFramework 的对象池体系更强调"重置"和"生命周期"。

在 MyFramework 里,池化对象不是简单拿出来再塞回去,而是要考虑:

对象是否已经销毁?

对象是否正在回收?

这一次分配和上一次分配如何区分?

回收以后外部引用是否置空?

临时对象是否忘记归还?

对象字段是否全部重置?

List、Dictionary、Array、byte\[\] 这些容器是否也要池化?

简化示意:

复制代码
复制代码
public class DamageNumberData : ClassObject
{
    public Vector3       mPosition;
    public float         mTime;
    public List<byte>    mNumberList;
    public List<Vector2> mKeyFrameList;

    public override void resetProperty()
    {
        base.resetProperty();

        mPosition = Vector3.zero;
        mTime = 0.0f;

        if (mNumberList != null)
        {
            mNumberList.Clear();
        }

        if (mKeyFrameList != null)
        {
            mKeyFrameList.Clear();
        }
    }
}

申请对象:

复制代码
复制代码
CLASS(out DamageNumberData data);

data.mPosition = pos;
data.mNumberList.Add(1);
data.mNumberList.Add(2);
data.mNumberList.Add(3);

回收对象:

复制代码
复制代码
UN_CLASS(ref data);

注意这里用的是 ref,目的就是回收以后把外部引用置空,避免旧逻辑继续访问已经回池的对象。

这就是 MyFramework 对象池更强调的点:

对象池真正麻烦的不是复用,而是复用前后的状态干净。

如果一个对象回池时没有清理干净,下次拿出来就可能带着上一次的脏数据。

普通项目里,池化 GameObject 就能解决很多问题。

但在低 GC、热更、网络消息、临时容器、UI 子窗口、伤害数字、配置解析这些场景里,只池化 GameObject 远远不够。

所以 MyFramework 的低 GC 不是单点优化,而是一种整体习惯:

普通类对象池化。

List / Dictionary / Array 池化。

UI 子窗口池化。

特效和 Prefab 池化。

临时对象跨帧未回收时给出检查。

池化对象必须 resetProperty。

这也是 MyFramework 和 HTFramework 在对象池上的设计取向差异。

HTFramework 提供通用池模块。

MyFramework 更强调池化对象的生命周期规则。


六、编辑器工具链:一个偏框架工具箱,一个偏项目质量兜底

HTFramework 的公开文档和模块展示非常成熟,它有编码规范、文档博客、游戏实战教程,以及大量模块说明。README 中能看到超级坦克大战、FTG2D 横版格斗、RPG2D、MMORPG + 中国象棋联网对战等实战教程入口。

这对开源框架来说非常重要。

因为新用户接触一个框架时,最怕的不是功能少,而是不知道怎么开始。

HTFramework 在这方面做得很好:

模块说明清楚。

博客入口明确。

教程案例多。

使用者容易找到学习路径。

MyFramework 目前更偏"项目质量兜底"。

它的工具链不是只为了方便开发,而是为了提前发现项目问题。

比如:

资源路径检查。

配置表字段检查。

协议代码生成。

UI 代码生成。

热更引用检查。

资源引用反查。

AssetBundle 依赖分析。

重复打包检测。

图集检查。

Prefab 规范检查。

代码规范检查。

这类工具的价值,通常只有项目做大以后才会特别明显。

小项目可能觉得麻烦。

大项目会发现这是救命的。

因为大型项目里很多问题不能靠人工检查:

哪个资源被重复打包了?

哪个配置表引用了不存在的资源?

哪个热更资源引用了非热更资源?

哪个 UI 节点改名导致生成代码失效?

哪个协议字段客户端和服务器不一致?

哪个对象池对象没有正确 resetProperty?

这些问题如果都等运行时发现,成本就太高了。


七、总结:HTFramework 更像模块框架,MyFramework 更像工程体系

对比下来,两个框架的差异可以这样概括。

HTFramework 更适合这样描述:

它是一个模块化 Unity 快速开发框架。

它把 UI、Resource、Procedure、FSM、Entity、Network、ObjectPool、ReferencePool 等能力拆成清晰模块。

它的文档、博客和教程更成熟。

它更适合希望快速搭建 Unity 客户端项目的使用者。

MyFramework 更适合这样描述:

它是一套面向长期项目的 Unity 工程化框架。

它不只关心模块有没有,而是更关心整个项目流程是否可控。

它把热更分层、UI 生成、配置表工具链、协议代码生成、资源检查、对象池、低 GC、强生命周期和客户端服务器协作放在一起考虑。

它更适合 RPG、MMO、长线运营项目,或者那些 UI 多、配置多、协议多、资源多、需要热更新和服务端协作的项目。

所以这两个框架不是同一种问题的答案。

HTFramework 解决的是:

Unity 项目常见模块如何快速组织起来。

MyFramework 解决的是:

一个长期商业项目里,容易失控的流程如何被框架和工具链接管。

如果用一句话总结:

HTFramework 更像"模块齐全的 Unity 客户端框架"。

MyFramework 更像"服务长期项目的 Unity 工程化框架"。

相关推荐
SmalBox1 天前
【节点】[ComputeVertexPosition节点]原理解析与实际应用
unity3d·游戏开发·图形学
孟无岐1 天前
LayaAir IDE 插件开发入门:用 TypeScript 给编辑器加一个自己的面板
typescript·游戏开发·工程化·编辑器扩展·layaair·ide 插件
丁小未1 天前
基于MVVM框架的XUUI 扩展的UI管理系统教程
unity·mvvm·ui框架·xuui·ui管理器
丁小未2 天前
基于MVVM框架的XUUI HelloWorld 新手教程
unity·性能优化·c#·游戏引擎
丁小未2 天前
基于MVVM框架的XUUI MoreComplex案例
unity·c#
EQ-雪梨蛋花汤2 天前
【Unity笔记】VR 一体机画面锯齿、模型边缘闪烁、接缝抖动排查:MSAA、Mipmap、Render Scale、Z-Fighting 全流程记录
笔记·unity·vr
SmalBox2 天前
【节点】[ScleraUVLocation节点]原理解析与实际应用
unity3d·游戏开发·图形学
松树戈2 天前
【Godot4精进之路】03~Godot编辑器常用界面介绍
编辑器·游戏引擎·godot
YigAin2 天前
Unity Spine 资源出现白边的解决办法
unity·游戏引擎·spine