MyFramework:Unity 自动生成 UI 代码怎么避免覆盖手写逻辑

项目地址:

github.com/ZHOURUIH/My...

Unity 项目里,UI 界面通常会有大量节点绑定代码。

比如按钮、文本、图片、列表、输入框:

bash 复制代码
protected myUGUIButton mButtonClose;
protected myUGUIText   mTextTitle;
protected myUGUIImage  mImageIcon;

然后在初始化时找到这些节点:

bash 复制代码
newObject(out mButtonClose, "ButtonClose");
newObject(out mTextTitle, "TextTitle");
newObject(out mImageIcon, "ImageIcon");

这种代码手写很麻烦。

Prefab 改一次,脚本也要跟着改。

所以很多项目都会做 UI 代码生成工具。

但 UI 自动生成有一个很现实的问题:

bash 复制代码
生成代码确实方便
但不能把手写业务逻辑覆盖掉

否则工具就不是提高效率,而是在制造风险。


一、最危险的做法

最简单的 UI 代码生成方式是:

bash 复制代码
根据 Prefab 扫描节点
生成一个完整 C# 文件
覆盖原来的脚本文件

这种方式实现最简单。

但问题也最大。

因为一个界面脚本里通常不只有节点绑定。

还会有业务逻辑:

bash 复制代码
protected override void init()
{
	base.init();

	mButtonClose.setClickCallback(onCloseClick);
	mButtonBuy.setClickCallback(onBuyClick);
}

protected void onCloseClick()
{
	close();
}

protected void onBuyClick()
{
	// 购买逻辑
}

如果生成器每次都覆盖整个文件,那这些手写代码也会被覆盖。

结果就是:

bash 复制代码
Prefab 一改
重新生成代码
业务逻辑没了

这种工具不敢频繁用。

开发者会越来越不信任它。


二、真正需要自动生成的部分

UI 脚本里并不是所有代码都需要自动生成。

真正适合自动生成的,通常只有两类:

bash 复制代码
成员变量声明
节点绑定代码

例如成员变量:

bash 复制代码
protected myUGUIButton mButtonClose;
protected myUGUIText   mTextTitle;
protected myUGUIImage  mImageIcon;

以及节点绑定:

bash 复制代码
newObject(out mButtonClose, "ButtonClose");
newObject(out mTextTitle, "TextTitle");
newObject(out mImageIcon, "ImageIcon");

这些代码和 Prefab 结构强相关。

Prefab 节点变了,它们就应该跟着变。

但点击回调、数据刷新、界面逻辑不应该由生成器覆盖。

这些是业务代码。

所以 MyFramework 的做法是:

bash 复制代码
自动生成结构代码
手写业务逻辑保留

三、自动生成区域

要做到这一点,生成器不能直接覆盖整个文件。

它只能替换固定的自动生成区域。

示例结构类似这样:

bash 复制代码
public class UILogin : LayoutScript
{
	//-------------------自动生成开始-------------------
	protected myUGUIButton mButtonLogin;
	protected myUGUIText   mTextAccount;
	protected myUGUIInput  mInputPassword;
	//-------------------自动生成结束-------------------

	protected override void assignWindow()
	{
		base.assignWindow();

		//-------------------自动绑定开始-------------------
		newObject(out mButtonLogin, "ButtonLogin");
		newObject(out mTextAccount, "TextAccount");
		newObject(out mInputPassword, "InputPassword");
		//-------------------自动绑定结束-------------------
	}

	protected override void init()
	{
		base.init();

		mButtonLogin.setClickCallback(onLoginClick);
	}

	protected void onLoginClick()
	{
		// 手写登录逻辑
	}
}

生成器只处理这两段:

bash 复制代码
自动生成开始 -> 自动生成结束
自动绑定开始 -> 自动绑定结束

其他地方一律不动。


四、重新生成时发生什么

当 Prefab 改动后,重新执行 UI 代码生成。

生成器会做几件事:

bash 复制代码
读取原来的 C# 文件
找到自动生成区域
重新生成成员变量
替换成员变量区域

找到自动绑定区域
重新生成 newObject 代码
替换绑定区域

保留其他所有手写代码

所以开发者可以放心写:

bash 复制代码
protected override void init()
{
	base.init();

	mButtonClose.setClickCallback(onCloseClick);
	mButtonBuy.setClickCallback(onBuyClick);
}

重新生成时,这些代码不会被动到。

生成器只更新和 Prefab 结构相关的部分。


五、为什么不能只生成一个新文件

也有人会选择生成一个单独文件。

例如:

bash 复制代码
UILogin.Generated.cs
UILogin.cs

用 partial class 拆开。

这个方案也能避免覆盖手写代码。

但 MyFramework 里更偏向直接在同一个文件中保留自动区域。

原因是 UI 脚本本身是一个界面类。

成员变量、绑定代码、业务逻辑放在同一个文件里,查看和调试更直接。

只要生成器严格只替换标记区域,就能同时满足两个要求:

bash 复制代码
代码集中
不会覆盖手写逻辑

这种方式对项目成员也更直观。

打开一个界面脚本,就能看到这个界面的节点绑定和业务逻辑。


六、生成器必须守规则

只替换自动区域听起来简单,但工具必须严格遵守规则。

不能因为某个标记没找到,就直接重建整个文件。

正确做法应该是:

bash 复制代码
文件不存在
    创建完整模板

文件存在且标记完整
    只替换标记区域

文件存在但标记缺失
    报错
    停止生成

标记缺失时,直接覆盖文件是很危险的。

因为这说明文件可能被手动改坏了,或者不是当前生成器生成的文件。

这时应该让开发者处理问题,而不是由工具猜测。

自动化工具最重要的不是"能生成"。

而是"不会破坏已有代码"。


七、节点变动时的价值

UI Prefab 在开发过程中经常变。

比如:

bash 复制代码
新增一个按钮
删除一个文本
改一个节点名
某个 Image 改成 RawImage
列表结构调整
子窗口拆分

如果没有代码生成,每次都要手动同步脚本。

很容易出现:

bash 复制代码
Prefab 里节点已经改名
代码里字段还是旧名字

Prefab 里删除了节点
代码里还在绑定

Prefab 里新增了按钮
代码里忘了声明成员

UI 自动生成能减少这些重复工作。

但前提是重新生成足够安全。

如果重新生成会覆盖业务代码,那开发者就不敢频繁使用。

MyFramework 的自动区域替换,就是为了让重新生成变成常规操作。

Prefab 改了,就重新生成。

不用担心手写逻辑被清掉。


八、成员变量和业务逻辑分离

自动生成区域里只放结构代码。

例如:

bash 复制代码
protected myUGUIButton mButtonClose;
protected myUGUIButton mButtonBuy;
protected myUGUIText   mTextPrice;

业务逻辑放在自动区域外:

bash 复制代码
protected override void init()
{
	base.init();

	mButtonClose.setClickCallback(onCloseClick);
	mButtonBuy.setClickCallback(onBuyClick);
}

protected void refreshPrice()
{
	mTextPrice.setText(getPriceText());
}

这样职责很清楚。

bash 复制代码
生成器负责:
    节点字段
    节点绑定
    子窗口创建
    控件类型同步

开发者负责:
    按钮回调
    数据刷新
    界面打开逻辑
    界面关闭逻辑
    网络回包处理

生成器不应该理解业务。

它只应该理解 UI 结构。


九、为什么这很适合 Unity

Unity UI 的问题是 Prefab 和 C# 脚本天然分离。

Prefab 里有节点树。

C# 里有成员变量。

两边必须保持同步。

手动同步成本很高。

尤其是复杂界面:

bash 复制代码
几十个按钮
几十个文本
多个列表
多个子窗口
多个动态节点

如果每个节点都手写查找和声明,代码量很大。

而且这些代码没有多少业务价值。

自动生成可以把重复劳动交给工具。

开发者只关注真正的界面逻辑。


十、重新生成后的代码可读性

UI 代码生成不能只追求"能用"。

生成出来的代码还应该可读。

因为 UI 脚本是经常被打开的。

MyFramework 的思路不是把所有东西都隐藏起来,而是生成普通 C# 代码。

例如:

bash 复制代码
newObject(out mButtonClose, "ButtonClose");
newObject(out mTextTitle, "TextTitle");
newObject(out mImageIcon, "ImageIcon");

这种代码可以直接看懂。

出问题时,也方便断点调试。

工具生成代码不是为了让代码不可见。

而是为了减少重复手写。


十一、和运行时查找的区别

还有一种做法是运行时按字符串查找节点:

bash 复制代码
getObject("ButtonClose");
getObject("TextTitle");

需要用时再查。

这种方式减少了声明字段。

但问题是:

bash 复制代码
运行时才知道节点是否存在
字符串散落在业务代码里
重命名不安全
重复查找也容易变乱

自动生成成员变量的好处是:

bash 复制代码
节点集中声明
绑定集中执行
业务代码直接使用成员变量
节点缺失可以在初始化时统一报错

业务代码里不需要到处写路径字符串。

这更适合中大型 UI 工程。


十二、设计边界

自动生成区域替换也有边界。

它要求开发者遵守规则:

bash 复制代码
不要手动修改自动生成区域
不要删除自动区域标记
业务逻辑写在标记区外
Prefab 节点改动后重新生成

生成器也要遵守规则:

bash 复制代码
只改标记区域
标记缺失时报错
不要覆盖整个文件
不要替开发者生成业务逻辑

双方规则清楚,工具才稳定。


十三、这个设计解决的不是代码量

UI 自动生成表面上是在减少代码量。

但更重要的是减少同步成本。

真正的问题不是少写几行代码。

而是:

bash 复制代码
Prefab 变了
脚本必须同步变
同步过程不能破坏手写逻辑

所以 MyFramework 的 UI 自动生成重点不是"生成多少代码"。

而是:

bash 复制代码
哪些代码可以交给工具
哪些代码必须留给开发者
工具修改范围必须可控

自动区域替换就是这个边界。


总结

Unity UI 自动生成最大的问题,不是怎么生成字段和绑定代码。

这些都不难。

真正的问题是:

bash 复制代码
重新生成时,怎么不覆盖手写业务逻辑

MyFramework 的做法是把 UI 脚本分成两类区域:

bash 复制代码
自动生成区域
    成员变量声明
    节点绑定代码

手写业务区域
    初始化逻辑
    点击回调
    数据刷新
    网络处理

生成器每次只替换自动生成区域。

自动区域之外的代码原样保留。

这样 Prefab 改动后可以反复重新生成 UI 代码,而不用担心业务逻辑被覆盖。

这也是 UI 代码生成工具真正能在项目里长期使用的前提。

相关推荐
SmalBox3 小时前
【节点】[Taiji节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox1 天前
【节点】[Stripes节点]原理解析与实际应用
unity3d·游戏开发·图形学
qiqizizzz2 天前
Unity引擎底层 | ”Fake Null“ 假空现象
unity3d
_zhourui_h_2 天前
MyFramework:Unity TypeID 如何替代字符串和反射
unity3d
SmalBox2 天前
【节点】[Spiral节点]原理解析与实际应用
unity3d·游戏开发·图形学
_zhourui_h_2 天前
MyFramework:Unity SafeList0 的延迟压缩设计
unity3d
_zhourui_h_3 天前
MyFramework:Unity SafeList 如何支持遍历中修改
unity3d
SmalBox3 天前
【节点】[SmoothWave节点]原理解析与实际应用
unity3d·游戏开发·图形学
SmalBox4 天前
【节点】[RoundedRectangle节点]原理解析与实际应用
unity3d·游戏开发·图形学