ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

如何读懂 Unity C 参考源码:从 .bindings.cs 到引擎桥接的完整指南

如何读懂 Unity C 参考源码:从 .bindings.cs 到引擎桥接的完整指南

如何读懂 Unity C# 参考源码:从 .bindings.cs 到引擎桥接的完整指南

【免费下载链接】UnityCsReferenceUnity C# reference source code.项目地址: https://gitcode.com/gh_mirrors/un/UnityCsReference

UnityCsReference 是 Unity 6(版本 6000.7.0a3)的 C# 参考源码,全仓库约 8085 个.cs文件,覆盖 Runtime、Editor、Modules 三大区。它不是给你拿来搭建游戏工程的 SDK,而是一份"只读"的引擎 C# 层实现,适合那些想搞清楚 Unity 各个 API 底层怎么写、C# 脚本和 C++ 引擎之间到底怎么衔接的开发者。换句话说,你查 API 文档时看到的行为,在这里能看到对应的真实代码。📖

它的授权模式是 Reference Only,也就是仅供阅读,不允许修改或再分发,仓库里也不收 Pull Request。所以把它当"活字典"和"实现原理手册"用,比当"可编辑项目"用更对路。

先搞清楚五大目录各管什么

拿到源码,第一件事不是打开某个文件,而是认清目录分工。仓库顶层就五个内容区,读源码时的检索效率全取决于这一步:

三大内容区按角色划分

  • Modules/(约 5962 个文件):体量最大。每个子目录对应一个功能模块,比如Physics、Animation、Audio、ParticleSystem,且大多成对出现——Animation是运行时部分,AnimationWindow、AnimationEditor就是对应编辑器的部分。
  • Editor/(约 1495 个文件):Unity 编辑器(Unity 编辑器窗口、菜单、Inspector)的 C# 实现。你写EditorWindow、MenuItem、自定义 Inspector 时用到的逻辑,源头就在这里。
  • Runtime/(约 527 个文件):游戏运行时那一层的公共代码,Runtime/Export/下按命名空间再拆成 81 个目录,Scripting/、Transform/、Profiler/都在这里。

剩下两区是支撑与构建

External/放的是第三方库(LibTessDotNet、Clipper、JsonParser 等),约 85 个文件;Tools/与Projects/负责构建。Projects/CSharp/UnityReferenceSource.sln是入口解决方案,里面挂了 7 个工程,其中UnityEngine.csproj和UnityEditor.csproj是两个主程序集。

读代码的建议顺序:先在Modules/<模块名>/找公开类,再顺着它引用的接口往Runtime/里追。

.bindings.cs 与特性:C# 和 C++ 是这样接上的

这是整个仓库最值得花时间的地方。统计下来有969 个.bindings.cs文件,它们不是普通的 C# 类,而是"C# 侧的桩",靠一组特性告诉编译器"这个成员的真身在 C++ 里"。

extern 桩与托管实现混在同一个 partial 类

以Transform为例(见 Runtime/Transform/ScriptBindings/Transform.bindings.cs),同一个partial class Transform里两种写法并存:

[RequiredByNativeCode] public partial class Transform : Component, IEnumerable { public extern Vector3 position { get; set; } // C++ 提供实现 public Vector3 eulerAngles { // 纯 C# 计算 get { return rotation.eulerAngles; } set { rotation = Quaternion.Euler(value); } } }

extern的成员没有函数体,编译时由引擎生成的 native 绑定补上;非extern的成员就是你能直接读懂的普通 C#。看懂这一点,你读任何一个 API 就知道哪些行为是引擎直接做的、哪些是 C# 逻辑算出来的。

几个关键特性决定了类的"身份"

这些特性定义在 Modules/Scripting/Attributes/Attributes.cs 与 Runtime/Export/Scripting/ExtensionOfNativeClassAttribute.cs:

  • [NativeHeader("Runtime/Transform/Transform.h")]:指出对应 C++ 头文件,定位原生实现时用。
  • [RequiredByNativeCode]/[UsedByNativeCode]:标记"被原生代码需要"或"被原生代码调用",是裁剪程序集的依据。
  • [NativeConditional("UNITY_EDITOR")]:某成员只在编辑器构建下暴露,解释了你为什么在 Player 里看不到某个方法。
  • [ExtensionOfNativeClass]:表示这个 C# 类是对某个原生类的扩展封装,MonoBehaviour就带着它。

把这四个特性当成"读代码的图例",遇到任何陌生类先扫一眼类头,基本就能判断它和原生层的边界在哪。

从 MonoBehaviour 与 Transform 看一个 API 怎么拼起来

光懂特性还不够,拿两个你最熟的东西走一遍,把前面的规则落到具体类上。

MonoBehaviour:每个脚本的基类

MonoBehaviour 是Behaviour的派生类,类头同时挂着[RequiredByNativeCode]和[ExtensionOfNativeClass]。它在 C# 侧保留了一批真实可看的逻辑,比如destroyCancellationToken属性——用CancellationTokenSource管理销毁时的取消,this == null时抛MissingReferenceException。这类"纯 C# 部分"正是理解 Unity 行为的钥匙:生命周期、回调这些机制,很多实现就写在这些非extern成员里。

Transform:旋转顺序是怎么约定的

Transform.bindings.cs里还藏着一个internal enum RotationOrder { OrderXYZ, OrderXZY, ... },配GetLocalEulerAngles(RotationOrder)这种internal extern方法。它解释了"为什么 eulerAngles 和 localEulerAngles 会有不同的取值"——欧拉角在本地空间里的旋转顺序是显式指定的,而不是隐式约定。遇到"数值对不上"的疑问时,往这类internal桩里找,通常比翻公开文档更快。

打开解决方案阅读的正确姿势

最后落到"怎么读得动"。这个仓库是只读的参考实现,编译配置和正常 Unity 工程不一样,照着下面来。

两个工程与一套编译宏

用 Projects/CSharp/UnityReferenceSource.sln 打开后,主程序集是UnityEngine与UnityEditor。UnityEngine.csproj里能看到几条关键信息:目标框架netstandard2.1、LangVersion为 12.0、并且开了COMBINED_ASSEMBLIES——意味着运行时和编辑器被编成少数几个大程序集,而不是每个模块一个 dll。

DefineConstants里那一大串ENABLE_PHYSICS、ENABLE_AUDIO、ENABLE_BURST等宏,就是各模块"开没开"的开关。读懂这些宏,你能解释"为什么我看到的代码和某个 Unity 版本行为不一致"。

三步把源码用起来

  1. 定位:按模块名在Modules/或Runtime/Export/下找对应命名空间目录,先读非extern的成员。
  2. 追边界:看到extern成员,用类头的[NativeHeader]找到对应 C++ 头文件路径,判断真身在哪。
  3. 判条件:留意[NativeConditional]与工程里的ENABLE_*宏,确认该行为在你的构建目标下是否真正存在。

需要本地拿一份源码时执行:git clone https://gitcode.com/gh_mirrors/un/UnityCsReference,然后直接打开解决方案即可。🔍

把它当参考手册的日常用法:API 行为存疑 → 找到对应.bindings.cs→ 分清楚extern与纯 C# 两部分 → 用特性定位原生实现。走通这一条链路,Unity 大部分"黑盒"都会变得可解释。

【免费下载链接】UnityCsReferenceUnity C# reference source code.项目地址: https://gitcode.com/gh_mirrors/un/UnityCsReference

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进