Under Construction

Prometheus Lab

Portfolio & Resources

Back to Blog
Unity15 min3 views

Boxing trong unity

Author

Minh Khoa

Author

🎯 1. Boxing là gì? (định nghĩa chuẩn)

Boxing = hành động chuyển một giá trị kiểu value type (int, float, bool, struct…) thành một object (kiểu reference type).

Tức là C# đóng value vào một “hộp object” trên heap.

Ví dụ:

int x = 5;
object obj = x;   // ← boxing xảy ra

x từ value type (lưu trên stack) → copy vào một object (lưu trên heap).


🎯 2. Unboxing là gì?

Lấy value từ object ra:

object obj = 10;
int y = (int)obj;  // ← unboxing

🎯 3. Tại sao BOXING gây hại trong Unity?

(1) Boxing tạo ra memory allocation → gây GC

Khi boxing, C# tạo ra một object mới trên heap.

→ Alloc

→ Sau đó GC phải dọn → gây spike, drop FPS.

Trong game, đặc biệt là update loop → rất nguy hiểm.


(2) Xảy ra ngầm → khó phát hiện

Ví dụ:

int x = 10;
Debug.Log(x);

Có boxing vì Log nhận parameter là object.


(3) Boxing xảy ra khi dùng interface

Nếu struct implement interface → gọi interface method → BOX.

public interface IAttack { void Do(); }

public struct Sword : IAttack
{
    public void Do() { }
}

IAttack atk = new Sword();  // boxing!

(4) Boxing khi dùng generic không constraint tốt

Ví dụ:

void Print<T>(T value)
{
    Debug.Log(value);  // boxing nếu value là struct
}


(5) LINQ rất hay gây boxing

LINQ to Object tạo delegate, iterator → allocation + boxing.


🎯 4. Một số ví dụ boxing phổ biến trong Unity


❌ Ví dụ 1: Debug.Log

int score = 10;
Debug.Log(score); // boxing

Cách fix:

Debug.Log($"{score}"); // không boxing (string format)

❌ Ví dụ 2: Struct trong List<object>

List<object> list = new();
list.Add(5); // boxing

❌ Ví dụ 3: Sử dụng interface với struct

IMovement mover = new MovementStruct(); // boxing

❌ Ví dụ 4: foreach với struct enumeration

foreach (var item in myStructList) { ... }
// nếu enumerator là struct → có thể boxing tùy implement

❌ Ví dụ 5: Event với struct argument

Action<MyStruct> onChange;
onChange(myStruct); // có thể boxing

🎯 5. Làm sao để tránh boxing?


✔ 1. Tránh dùng object để chứa value type

Sai:

object obj = 5;

Đúng:

int x = 5;

✔ 2. Tránh interface nếu struct implement interface

Dùng generic thay thế.

*Generic (hay lập trình tổng quát) không phải là một kiểu dữ liệu cụ thể (như intstring), mà là khái niệm tham số hóa kiểu dữ liệu (parameterized types). Nó cho phép định nghĩa các lớp (class), giao diện (interface) và phương thức (method) với kiểu dữ liệu chưa xác định, giúp mã nguồn linh hoạt, tái sử dụng cao và kiểm soát lỗi chặt chẽ tại thời điểm biên dịch

Sai:

IAttack atk = new Sword();

Đúng:

void Perform<T>(T atk) where T : IAttack
{
    atk.Do();
}

✔ 3. Debug.Log → ép string để tránh boxing

Debug.Log(score.ToString());

✔ 4. Tối ưu system dùng struct (job system, ECS)

ECS / Burst hoàn toàn không boxing.


✔ 5. Tránh boxing trong Dictionary key

Nếu key là struct → có thể boxing khi GetHashCode() override kém.


🎯 6. Làm sao biết trong code có boxing?

Unity Editor:

  • Bật Profiler → GC Alloc
  • Hoặc bật Deep Profile

Nếu mỗi frame có:

System.Object
System.Int32
System.ValueType

→ đó là BOXING.


🎯 7. Tóm tắt siêu dễ nhớ

BOXING = struct → object → tạo rác → gây GC → drop FPS

Unity sợ nhất GC → phải tránh boxing trong:

  • Update()
  • LateUpdate()
  • FixedUpdate()
  • UI event spam
  • DOTS / Jobs
  • Network serialization