
開場很多 Unity 開發者在性能調優時都會遇到一個疑問:調用Transform.Translate這種高頻 API 時,是不是每次都要穿越 C# 與 C++ 的邊界?答案是肯定的,而且開銷遠比你想象的小。當你在 C# 腳本里寫下transform.Translate(1, 0, 0),這個方法并沒有托管實現——它會直接跳轉到引擎底層的 C++ 函數。這個跨語言跳轉對開發者幾乎透明,背后靠的是一套啟動期建立的注冊與查找機制:ICall(Internal Call)。理解這套機制有三個實際收益:一是能正確評估"托管/原生邊界"的真實開銷,不再憑直覺誤判性能熱點;二是能讀懂 Unity 托管層源碼(UnityCsReference)里大量沒有方法體的extern聲明;三是寫自定義原生插件時,知道哪條路是官方支持的、哪條是內部通道。一、核心概念:一張啟動期建好的映射表ICall 是 Mono/IL2CPP 運行時提供的"托管調原生"通道。它的本質是一張哈希映射表:鍵是 C# 方法的完整簽名(含命名空間),值是 C++ 函數指針。這張表在引擎啟動早期一次性建好,之后每次跨語言調用就是一次 O(1) 查表加一次直接的函數調用。1.1 托管側:只有聲明,沒有方法體C# 側被原生實現的方法有兩個標志:extern關鍵字,以及[MethodImpl(MethodImplOptions.InternalCall)]特性。開發者只寫聲明——因為實現根本不在托管