Unity 7.0 Alpha 拆解:编辑器干掉 Mono 换 CoreCLR

10 月 5 日,Unity 放出 7.0 的第一个公开 Alpha,版本号 7000.0.0a7,走 Unity Hub 的 Pre-releases 通道分发,官方说每周最多推两个构建。定位写得很直白:验证项目兼容性用的,别拿去做生产。

换脚本运行时这件事,Unity 念叨了怕是有七八年。这回是真的落地了。

编辑器第一次不跑 Mono 了

Release Notes 里两条很扎眼:Removed support for Mono-based Editor,以及 Removed support for Mono-based Android players。

注意前半句。编辑器自己就是用 Mono 跑起来的,现在换成 CoreCLR 了,这是头一回。新的运行时布局变成两条腿:CoreCLR Player 走 JIT,管 Desktop 和 Editor;IL2CPP Player 走 AOT,管 Mobile 和 Console。IL2CPP 一点没动,原因后面再说。

但有个落差得先摆桌面上:这个 Alpha 的脚本层还锁在 C# 9 / .NET Standard 2.1。不是 C# 14,也不是 .NET 10。

官方说法是,会往 Beta 和正式版增量推进 .NET 10 与 C# 14,配套的还有 MSBuild、官方 .NET 调试器、Assembly Load Context,但没给日期。原话大意是,第一个支持 .NET 10 / C# 14 的版本优先跟 Unity 6.7 LTS 对齐功能和稳定性,性能优化留给后面的 LTS。

说白了,换底座和升语言版本是两件事,这次先把底座换了。

为什么非得换?说到底,是 Mono 拖不动 Unity 想走的路。Unity 这几年的脚本层一直卡在 C# 9。原因也不复杂:它自己那套编译链跟 .NET 主线脱节太久,升一次语言版本,牵动的是整个编译管线。想用 record、file-scoped namespace、泛型数学这些新东西,想接官方 Roslyn 和 .NET 调试器,前提是先有一个能挂上现代 .NET 的运行时。Mono 不能说不堪用,只是跟不上节奏了。

换完之后编辑器的启动和域重载理论上都该快,因为不再需要为 Mono 那套东西迁就;但这也是官方宣称,得等 Beta 出来实机看。

时间线也顺便记一下:正式版计划 2027 年 Q1,2026 年 12 月开早期 Beta。所以现在这个 Alpha,离能上项目还隔着一年半。

CoreCLR 是个什么东西

Mono 是 Xamarin 时代的产物,2001 年就开写了,Unity 从 5.x 一路用到 6.x。它最大的优点是轻、能塞进各种平台,缺点是性能模型老旧,最成问题的是它的 Boehm GC。

Boehm 是保守式 GC。它扫内存的时候没法精确判断哪些位置是引用、哪些是普通整数,只能"看起来像指针就当指针处理"。代价是不精确,也压不实,回收时机不够可控。这也是为什么 Unity 项目里 GC Spike 一直是老梗。

CoreCLR 是 .NET 官方那套运行时(现在叫 .NET Runtime)。它用的是 RyuJIT 分层编译加分代 GC,JIT 出来的是真正的机器码,不像 Mono 那样一路解释加轻量编译。文件里官方口径就是这么描述的:RyuJIT 分层编译 + 分代 GC,替掉 Boehm。

再往下一层是脚本架构。Unity 过去用自己那套脚本编译管线,跟 .NET 的 MSBuild 世界是割裂的。转 CoreCLR 之后朝 MSBuild 靠,好处是 IDE、调试器、NuGet 这些生态能更自然地接进来。对写大型项目的人,这是实打实的省事。

把三条 Player 路径摆一起看,会清楚很多:

维度 Mono Player(已移除) IL2CPP Player CoreCLR Player
编译方式 解释 + 轻量编译 AOT,提前转 C++ 再编 JIT,RyuJIT 分层编译
GC Boehm(保守式) Boehm(保守式) 分代 GC
目标平台 全平台 Mobile / Console Desktop / Editor
动态代码 支持 受限(AOT) 支持
启动速度 快 慢(编译耗时) 中

这张表其实解释了两个问题。移动端为什么还得靠 IL2CPP?因为 AOT 是 iOS 唯一能走的合规路线,跟性能没什么关系,是平台规则卡死的。那桌面端为什么收益最大?JIT 加分层编译在长时间运行、热循环密集的场景里占优,而桌面恰好不缺运行内存,也不缺预热的时间。

基准数字好看,但别当真

社区里流传最广的那个测试,是 Unity 论坛上一个路径追踪(path tracing)基准,纯 C# 写的,没用 unsafe、没上 JobSystem、没碰内建 intrinsic:

Windows 实测,单线程下 Mono 跑了 101041.867ms(0.072M rays/s),IL2CPP 15862.338ms(0.457M),CoreCLR 8775.239ms(0.826M)。多线程差距更狠:Mono 7119.707ms,CoreCLR 758.274ms(9.555M)。内存方面 CoreCLR 反而省一点,501.7MB 对 Mono 的 556.8MB。

单线程算下来,CoreCLR 比 Mono 快了 17.1 倍。

这个数量级不是孤例。有人用独立构建(6000.7.0a2)在 macOS 的 Apple M4 / ARM64 上复现过,单线程口径 17.11×,配上 Parallel.For 是 17.85×,场景生成比 IL2CPP 快约 2.88×。两套硬件、两套代码,量级对得上。

然后反转来了。社区里 Dilmer 拿真实项目测过:Boat Attack 的平均帧时比 Mono 低大约 10%,Happy Harvest 低大约 15%。17 倍和 10% 摆在一起,落差快有 170 倍。

为什么会这样?路径追踪是纯 CPU 计算,几乎全在 C# 的循环里烧时间,JIT 出来的机器码优势能 100% 兑现。真实游戏里大头是渲染、物理、UI、资源加载,这些本就不在 C# 热路径上,脚本层再快也快不到哪儿去。微基准测的是语言运行时的上限,不是游戏帧率的下限。

所以 17× 这个数,看看就好,那是在一个极端受控的场景里跑出来的。

迁移要盯的坑

这个 Alpha 顺手砍了几样东西,值得单独列出来。

Progressive CPU Lightmapper 直接没了,受影响的项目会自动升到 GPU 方案。Editor 里那套烘焙式遮挡剔除(Baked Occlusion Culling)创作流程也废了。系统需求页上,macOS 的 "x64 architecture with SSE2" 标成了 Deprecated,只留 Apple Silicon。理由里提到一条:macOS 的 Rosetta 退役之后,没法再支持在 ARM 上做 CPU 光照烘焙。

这里有个容易吵起来的点。Unity 在 Unite Seoul 2026(2026 年 7 月 21 日,CEO Matt Bromberg 主讲)上把 Unity 7 讲成"Unity 6 架构的直接延续""零重建升级",SVP Adam Smith 说 CoreCLR、Surface Cache GI 这些先在 Unity 6 里生产验证再并进来。

听上去跟"破坏性变更"矛盾,其实是一回事:架构没断,断的是具体功能。Mono 编辑器没了、CPU Lightmapper 没了,这是功能级移除,不是引擎底座被推倒重来。写迁移方案的时候这两个概念得分清楚,否则容易被吓着。

代码上其实不用改太多。真正要注意的是那些显式依赖 Mono 行为的黑科技:反射加动态代码生成、依赖 System.Reflection.Emit 的 AOT 边缘 case,还有些老插件直接编译进了 Mono 的私有 API。这些在 CoreCLR 下要么更顺,要么直接炸,得实机跑。

顺便写个多线程并行的小例子,感受下 CoreCLR 环境下 Parallel.For 这类 API 的收益:

csharp 复制代码
using System;
using System.Diagnostics;
using System.Threading.Tasks;

// 一个纯 C# 的蒙特卡洛算积分,故意走全托管路径
static double MonteCarloPi(int samples)
{
    int inside = 0;
    // 用固定种子保证两次运行输入一致,只比运行时
    var rng = new Random(12345);
    for (int i = 0; i < samples; i++)
    {
        double x = rng.NextDouble();
        double y = rng.NextDouble();
        if (x * x + y * y <= 1.0) inside++;
    }
    return 4.0 * inside / samples;
}

// 单线程 vs Parallel.For:CoreCLR 的分代 GC 和 RyuJIT 更容易吃满多核
static void Bench(int total, int threads)
{
    var sw = Stopwatch.StartNew();
    long[] partial = new long[threads];
    Parallel.For(0, threads, t =>
    {
        var rng = new Random(12345 + t);
        long c = 0;
        for (int i = 0; i < total / threads; i++)
        {
            double x = rng.NextDouble(), y = rng.NextDouble();
            if (x * x + y * y <= 1.0) c++;
        }
        partial[t] = c;
    });
    sw.Stop();
    Console.WriteLine($"threads={threads} elapsed={sw.ElapsedMilliseconds}ms");
}

这段本身跑不出 17 倍,它没到那个计算密度。想自己量的话,把热循环体换成真正的浮点重负载,然后同版本号下切 Mono / IL2CPP / CoreCLR 三种 Player 各跑一遍,别跨版本比,没意义。

移动端是最大争议点

国内以移动端为主的团队,最关心的问题就一个:CoreCLR 的红利,手机上能不能吃到。

答案大概率是不能。

iOS 明确禁止运行时动态生成机器码,JIT 这条路走不通。Unity 也承诺过 IL2CPP 仍是移动端的长期方案。这是硬约束,不是 Unity 愿不愿意的问题。于是国内一大批做手游的,换了半天运行时,实际收益有限。

这个尴尬还有旁证。技术演讲资料里提到,.NET 要到 11 才"移动端支持完全完成",WASM 在 .NET 11 还挂在 Mono 上,.NET 12 才计划支持。换句话说,Unity 想给移动端上 CoreCLR,得等 .NET 自己先把移动端和 WASM 的坑填了。

中文社区已经出现那种"Unity 7 发布会很热闹,而我还在用 2021 LTS"式的反思帖,B 站和 CSDN 上都有。这情绪倒不全是段子。对移动端项目来说,升到 Unity 7 的收益,可能还不够抵迁移成本。

我的判断是:做 PC 或主机、对脚本性能有要求的团队,Unity 7 值得排进明年的升级计划;纯移动端团队,不如先盯着 6.7 LTS 那条线的动向,没必要为了版本号硬跳。

其他亮点,以及一句提醒

官方还提了几样:Play Mode 近乎即时、Domain Reload 只重载变更的代码、着色器编译最多提速 90%。这几个数字挺吸引人,但都是官方宣称、待独立验证,暂时别写进立项 PPT。另外还有 Surface Cache GI、新的 CLI 和公开 API,以及一个给 AI 编码代理用的免费 MCP。

那 90% 的着色器提速,和 17× 的路径追踪一样,得等真实项目复现了才算数。

参考链接

相关推荐
淡海水2 小时前
02-06-原理篇-增量式GC与并发GC
算法·unity·c#·并发·gc·增量
Vertira2 小时前
C# 函数封装成 DLL,
开发语言·c#
浅尝辄止;3 小时前
设计模式在HIS/LIS医疗系统中的完整实践指南(C#版)
开发语言·设计模式·c#
kimloner13 小时前
开源一个 376KB 的 Windows 桌面小工具:便签 + 截图标注 + OCR + 待办提醒(C# / WinForms)
windows·开源·c#·ocr·winforms
SmalBox14 小时前
03-06-架构篇-资源依赖与分组架构
unity3d·游戏开发
阿松爱学习14 小时前
【Unity开发】Aspose.PDF的使用
unity·pdf·c#
半亩码田15 小时前
C#转Python第4.8篇:正则表达式:Python re 模块 vs C# System.Text.RegularExpressions
python·正则表达式·c#
FPGA小徐15 小时前
【一生一芯 / PA】异常响应机制:RISC-V 中 ecall → mtvec → mret 的完整代
开发语言·数据库·c#
淡海水16 小时前
02-04-原理篇-GC Roots与对象图遍历
算法·unity·c#·图·gc·遍历·roots