Boxing in Unity
Minh Khoa
Author
🎯 1. What is boxing? (standard definition)
Boxing = the action of converting a value of a value type (int, float, bool, struct…) into an object (a reference type).
In other words, C## wraps the value in an “object box” on the heap.
Example:
int x = 5;
object obj = x; // ← boxing xảy ra
x from a value type (stored on the stack) → copied into an object (stored on the heap).
🎯 2. What is unboxing?
Take the value out of the object:
object obj = 10;
int y = (int)obj; // ← unboxing
🎯 3. Why is BOXING harmful in Unity?
❌ (1) Boxing creates memory allocation → causes GC
When boxing, C## creates a new object on the heap.
→ Alloc
→ Then GC it has to be cleaned up → causing spikes, drops FPS.
In games, especially in the update loop → very dangerous.
❌ (2) Happens implicitly → hard to detect
Example:
int x = 10;
Debug.Log(x);
There is boxing because Log receives the parameter as object.
❌ (3) Boxing occurs when using an interface
If a struct implements an interface → calling the interface method → BOX.
public interface IAttack { void Do(); }
public struct Sword : IAttack
{
public void Do() { }
}
IAttack atk = new Sword(); // boxing!
❌ (4) Boxing when using a generic without good constraints
Example:
void Print<T>(T value)
{
Debug.Log(value); // boxing nếu value là struct
}
❌ (5) LINQ often causes boxing
LINQ to Object creates delegates, iterators → allocation + boxing.
🎯 4. Some common boxing examples in Unity
❌ Example 1: Debug.Log
int score = 10;
Debug.Log(score); // boxing
How to fix:
Debug.Log($"{score}"); // không boxing (string format)
❌ Example 2: Struct in List<object>
List<object> list = new();
list.Add(5); // boxing
❌ Example 3: Using an interface with a struct
IMovement mover = new MovementStruct(); // boxing
❌ Example 4: foreach with struct enumeration
foreach (var item in myStructList) { ... }
// nếu enumerator là struct → có thể boxing tùy implement
❌ Example 5: Event with a struct argument
Action<MyStruct> onChange;
onChange(myStruct); // có thể boxing
🎯 5. How can boxing be avoided?
✔ 1. Avoid using object to hold value types
Wrong:
object obj = 5;
Correct:
int x = 5;
✔ 2. Avoid interfaces if the struct implements an interface
Use generics instead.
*Generic (or generic programming) is not a specific data type (like the above, but is the concept of parameterized data typesint, string)parameterized types**. It allows defining classes(class)**, interfaces (interface)and methods (method) with unspecified data types, helping source code be flexible, highly reusable, and tightly controlled for errors at compile time (Wrong:) Correct:
→ cast to string to avoid boxing
IAttack atk = new Sword();
✔ 4. Optimize systems using structs
void Perform<T>(T atk) where T : IAttack
{
atk.Do();
}
✔ 3. Debug.Log job system,
Debug.Log(score.ToString());
/ Burst entirely (no boxing ECS)
ECS ✔ 5. Avoid boxing in Dictionary key If the key is a struct → boxing may occur when.
overrides are poor.
- How can you tell if there is boxing in the code? GetHashCode() Unity Editor:
🎯 Enable
Profiler →
- Allocations Allocations? Actually source says Alloc. Need exact translation of segment 77/78. Let's correct final JSON? Can't. Need valid JSON. Let's provide Alloc. We included an extra note accidentally. Need proper JSON only. Let's reissue clean.}]}】{ GC title_segments
- Or enable Deep Profile
If each frame has:
System.Object
System.Int32
System.ValueType
→ that is BOXING.
🎯 7. Ultra-memorable summary
BOXING = struct → object → creates garbage → causes GC → drop FPS
Unity fears most GC → avoid boxing in:
- Update()
- LateUpdate()
- FixedUpdate()
- UI event spam
- DOTS / Jobs
- Network serialization