默认对齐行为

在 C# / Unity 中:

字段对齐:
编译器会根据字段类型自动插入 padding,使每个字段对齐到自己的自然边界。
结构体整体大小:
编译器会把结构体整体大小对齐到最大字段的大小(自然对齐)。

struct MyStruct
{
    byte a;     // 1 byte
    int b;      // 4 bytes
}

a 占 1 byte
padding 3 bytes 插入,保证 b 对齐到 4-byte 边界
结构体总大小 = 8 bytes(不是 5 bytes)

控制结构体整体对齐

C# 提供了两个主要特性:

1.[StructLayout(LayoutKind.Sequential, Pack = X)]

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 16)]
struct MyStruct
{
    public byte a;
    public int b;
}

Pack 指定字段的最大对齐,同时影响结构体整体对齐。
Unity + Burst 会遵循这个 Pack,使结构体在数组中连续排列时更容易被 SIMD 加速。
常用 Pack 值:1, 2, 4, 8, 16。
注意:设置 Pack = 16 并不保证字段都 16-byte 对齐,但会尽量按 16-byte 边界排列结构体。

2.[StructLayout(LayoutKind.Explicit)] + FieldOffset

如果你想精确控制内存布局(甚至让结构体整体 16-byte 对齐):

[StructLayout(LayoutKind.Explicit, Size = 16)]
struct MyStruct
{
    [FieldOffset(0)]
    public int a;
    [FieldOffset(4)]
    public float b;
    [FieldOffset(8)]
    public Vector3 c;  // 12 bytes
    // 由于 Size=16,整体结构体占 16 bytes
}

Size 强制结构体整体大小对齐。
FieldOffset 可以精确控制每个字段在结构体中的位置。
Burst + Jobs 可以直接用这种结构体数组做 SIMD 运算。

Unity / Burst 的注意事项

Unity 的 NativeArray 或 UnsafeUtility 访问内存时:
结构体整体对齐对性能很重要。
SIMD/Vectorized 运算要求 16-byte 或 32-byte 对齐。
可以用 UnsafeUtility.AlignOf() 查看类型实际对齐要求。
例如:

Debug.Log(UnsafeUtility.SizeOf<MyStruct>());
Debug.Log(UnsafeUtility.AlignOf<MyStruct>());

最佳实践

小结构体(<16 bytes):默认 Sequential 即可。
大结构体(>16 bytes 或用于 SIMD/Jobs):
使用 [StructLayout(LayoutKind.Sequential, Pack=16)] 或 [StructLayout(LayoutKind.Explicit, Size=16)]。
确保字段顺序按 从大到小 排列,减少 padding。
避免在结构体里放引用类型 (class 或 string)。
对于 Burst + Jobs,可以考虑使用 SoA + NativeArray 结合 SIMD,这样整体对齐最优。

小结

在这里插入图片描述

更多推荐