Unity Chuyển Từ Mono Sang CoreCLR: Developer Thực Sự Được Gì?
Minh Khoa
Tác giả
Câu trả lời ngắn: CoreCLR thay thế runtime Mono nằm bên dưới Unity, không thay MonoBehaviour và cũng không loại bỏ IL2CPP. Ba thay đổi đáng quan tâm nhất là Garbage Collector hiện đại hơn, managed code có runtime tốt hơn và reload code trong Editor nhanh hơn.
Nghe “Unity bỏ Mono”, nhiều người dễ nghĩ:
Mono bị bỏ
→ MonoBehaviour biến mất?
→ Project phải viết lại?
→ IL2CPP không còn cần thiết?
Thực tế, bạn vẫn viết code như cũ:
public class Player : MonoBehaviour
{
private void Update()
{
transform.Translate(Vector3.forward * Time.deltaTime);
}
}
GameObject, MonoBehaviour, Awake, Start, Update và Coroutine không thay đổi. Thứ được thay là bộ máy chạy và quản lý C# ở phía dưới Unity API.
CoreCLR Nằm Ở Đâu?
Code C# không được CPU chạy trực tiếp. Roslyn compile nó thành IL và đóng gói vào assembly như Assembly-CSharp.dll.
C#
↓ Roslyn Compiler
IL trong Assembly-CSharp.dll
↓ Mono JIT hoặc CoreCLR RyuJIT
Machine Code
↓
CPU
Mono và CoreCLR giống hai phiên bản của cùng một người phiên dịch: cả hai nhận IL rồi dịch thành machine code khi cần. CoreCLR là runtime mới hơn, được phát triển cùng hệ sinh thái .NET hiện đại.
MonoBehaviour = Unity lifecycle API
Mono/CoreCLR = Runtime chạy managed C# phía dưới
Tên MonoBehaviour chỉ là tên API lịch sử. Nó không bắt buộc Unity phải tiếp tục dùng Mono runtime.
Mono Và CoreCLR Khác Nhau Thực Tế Thế Nào?
Điểm khác biệt
Mono hiện tại
CoreCLR mới
JIT compiler
Mono JIT
RyuJIT
Garbage Collector
Boehm GC, non-moving
Precise, moving, generational GC
Nền tảng C#
Xa dần .NET hiện đại
.NET 10 và C# 14
Reload code
Thường reload cả AppDomain
Reload assembly chi tiết hơn
Tooling
Toolchain riêng của Unity
Gần debugger, profiler và MSBuild chuẩn .NET
Trong đó, GC và code reload là hai thay đổi dễ ảnh hưởng project thực tế nhất.
1. Garbage Collector Hiện Đại Hơn
Unity hiện sử dụng Boehm GC. Đây là GC conservative và non-moving: object được đặt ở đâu trong memory thì thường nằm nguyên ở đó.
CoreCLR dùng generational GC:
Object mới tạo → Gen 0
Sống qua collection → Gen 1
Sống lâu hơn nữa → Gen 2
Điều này giảm fragmentation và tạo nền tảng quản lý memory tốt hơn.
Nhưng đừng hiểu thành:
GC mới tốt hơn → allocation trong Update không còn vấn đề
Allocation vẫn có chi phí. Collection xảy ra sai thời điểm vẫn có thể tạo frame spike. CoreCLR giúp bộ máy dọn rác tốt hơn, chứ không biến rác thành miễn phí.
2. Reload Code Nhanh Hơn, Nhưng Static State Dễ Gây Bug Hơn
Unity với Mono thường reload cả AppDomain khi compile code hoặc Enter Play Mode. Một side effect quen thuộc là static state được reset:
public static class GameSession
{
public static int Score;
public static event Action OnGameOver;
}
Nhiều project vô thức dựa vào hành vi này:
Enter Play Mode
→ Domain Reload
→ Static field trở về giá trị ban đầu
CoreCLR chuyển sang reload chi tiết hơn bằng AssemblyLoadContext. Assembly không đổi có thể được giữ lại; chỉ phần code cần thiết mới được reload.
Editor phải làm ít việc hơn, nhưng static state cũng không còn chắc chắn được reset giúp bạn.
CoreCLR giúp Unity reload ít code hơn. Đổi lại, project không nên dựa vào Domain Reload để âm thầm dọn state giúp mình.
3. RyuJIT Và .NET Hiện Đại Hơn
CoreCLR sử dụng RyuJIT với Tiered Compilation:
Method được gọi lần đầu
→ Compile nhanh để chạy sớm
Method trở thành hot
→ Compile lại với optimization mạnh hơn
Runtime không cần tối ưu nặng một method chỉ mở Settings đúng một lần, nhưng có thể tập trung vào method được gọi hàng triệu lần.
Unity cũng tiến tới .NET 10, C# 14, MSBuild và tooling chuẩn của .NET. Lợi ích dễ thấy trước có thể là:
Compile và reload code nhanh hơn.
Debugger, profiler và IDE tốt hơn.
Tiếp cận API và package .NET hiện đại hơn.
Managed hot path có cơ hội được tối ưu tốt hơn.
Tuy nhiên:
Mono → CoreCLR ≠ FPS tự động tăng mạnh
Unity đang ưu tiên compatibility và performance parity trong giai đoạn đầu. Game có nhanh hơn hay không vẫn phụ thuộc bottleneck nằm ở managed code, rendering, physics, GPU hay nơi khác.
CoreCLR Có Thay IL2CPP Không?
Không. Hai hệ thống đưa IL tới CPU bằng hai con đường khác nhau.
CoreCLR — JIT khi chạy
C# → IL → CoreCLR JIT → Machine Code
Giống một phiên dịch viên đứng cạnh bạn: cần câu nào thì dịch câu đó ngay lúc nói.
Phù hợp với Editor, Desktop Player, debugging và iteration nhanh.
IL2CPP — AOT trước khi chạy
C# → IL → C++ → Native Compiler → Machine Code
Giống việc dịch toàn bộ tài liệu trước, in thành sách hoàn chỉnh rồi mới phát hành.
IL2CPP vẫn cần thiết cho Android, iOS, Meta Quest, console, WebGL và các platform không cho phép JIT.
Vì vậy Editor chuyển sang CoreCLR không có nghĩa APK dùng IL2CPP sẽ tự động nhận optimization từ RyuJIT.
Project Cũ Có Phải Viết Lại Không?
Phần lớn gameplay code vẫn chạy bình thường. Khu vực cần kiểm tra kỹ hơn gồm:
Static field, static event và singleton.
Editor tooling và reflection.
Native plugin hoặc unsafe code.
DLL cũ target .NET Framework.
Save system dùng BinaryFormatter.
Code phụ thuộc AppDomain hoặc Assembly.Location.
Deterministic simulation.
Ví dụ, BinaryFormatter bị loại bỏ trong .NET mới vì vấn đề bảo mật. Save system cũ nên chuyển sang System.Text.Json, JsonUtility hoặc một format được quản lý rõ ràng.
CoreCLR cũng có thể tạo kết quả floating-point hơi khác Mono JIT. Sai số nhỏ thường không đáng kể, nhưng có thể gây desync với lockstep multiplayer, Photon Quantum hoặc replay deterministic sau hàng nghìn tick.
Timeline Và Cách Chuẩn Bị
Roadmap cũ đặt CoreCLR chính thức ở Unity 6.8. Thông báo mới hơn tại Unite Seoul tháng 7/2026 đưa CoreCLR, .NET 10 và C# 14 vào Unity 7, dự kiến đầu năm 2027.
Unity 6.6
→ Fast Enter Play Mode mặc định cho project mới
Unity 6.7
→ Experimental CoreCLR Desktop Player để test
Unity 7
→ CoreCLR + .NET 10 + C# 14 chính thức
Để chuẩn bị project:
Bật Fast Enter Play Mode và thử tắt Domain Reload.
Enter/Exit Play Mode nhiều lần để tìm state bị giữ lại.
Rà static field, singleton và static event.
Cleanup thread, timer, callback và event chủ động.
Chạy Project Auditor, kiểm tra cảnh báo Domain Reload.
Regression test save/load, plugin và deterministic simulation.
Nếu project vẫn chạy đúng khi tắt Domain Reload, đó là tín hiệu tốt cho thấy kiến trúc đã sẵn sàng hơn với CoreCLR.
Cách Nhớ
MonoBehaviour = Unity lifecycle API
CoreCLR = Runtime mới chạy managed C#
IL2CPP = Compile IL thành native code trước khi chạy
Burst = Compiler tối ưu cho Jobs/ECS
Câu chốt: CoreCLR không thay đổi nhiều cách chúng ta viết gameplay. Nó thay đổi cách Unity chạy C#, dọn memory và reload code ở phía dưới. Lợi ích lớn nhất ban đầu có thể không phải FPS tăng ngay, mà là một Editor nhanh hơn và một nền tảng C# không còn tụt lại phía sau hệ sinh thái .NET hiện đại.