You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity ECS创建大量实体未耗尽内存却触发AddEmptyChunk段错误

问题:内存未耗尽时Unity Entities的AddEmptyChunk触发段错误

我编写了一个测试程序,每帧创建100个带有Buffer组件的实体,代码如下:

void Execute(Entity projectileEntity, [ChunkIndexInQuery] int chunkIndex, ref LocalTransform transform, in Projectile projectile)
{
    for(int j = 0; j < 100; j++) {
        var e = ECBWriter.CreateEntity(chunkIndex);
        var as_path = ECBWriter.AddBuffer<ASN>(chunkIndex, e);
        for(uint i = 0; i < 10; i++){
            as_path.Add(new ASN { routerID = i });
        }
    }
}

将程序编译后在Linux服务器运行,一段时间后,当创建约2×10⁸个实体、生成约1×10⁶个Chunk且占用22GB内存时崩溃(服务器总内存为128GB)。报错信息如下:

编辑器版本2022.3.5f1c1,Entities版本1.0.14

Caught fatal signal - signo:11 code:1 errno:0 addr:(nil)
Segmentation fault (core dumped)

编辑器版本2021.3.11f1c2,Entities版本0.51.1-preview.21

Caught fatal signal - signo:11 code:1 errno:0 addr:(nil)
Obtained 6 stack frames.
#0  0x007f6752ad9980 in funlockfile
#1  0x007f6705882ac4 in Unity.Entities.ChunkDataUtility.AddEmptyChunk(Unity.Entities.Archetype* archetype, Unity.Entities.Chunk* chunk, Unity.Entities.SharedComponentValues sharedComponentValues) -> void_08f2b62234a514a789dc69881ac7811a
#2  0x007f6705890f29 in Unity.Entities.EntityComponentStore.GetChunkWithEmptySlotsWithAddedComponent(Unity.Entities.EntityComponentStore* this, Unity.Entities.Chunk* srcChunk, Unity.Entities.ComponentType componentType, int sharedComponentIndex) -> Unity.Entities.Chunk*_08f2b62234a514a789dc69881ac7811a
#3  0x007f67058dfaf0 in Unity.Entities.EntityDataAccess.AddComponentDuringStructuralChange(Unity.Entities.EntityDataAccess* this, Unity.Entities.Entity entity, Unity.Entities.ComponentType componentType, ref Unity.Entities.SystemHandleUntyped originSystem) -> bool_08f2b62234a514a789dc69881ac7811a
#4  0x007f67058ddd14 in Unity.Entities.EntityCommandBuffer.EcbWalker`1<Unity.Entities.EntityCommandBuffer.PlaybackProcessor>.ProcessChain(Unity.Entities.EntityCommandBuffer.EcbWalker`1<Unity.Entities.EntityCommandBuffer.PlaybackProcessor>* this, Unity.Entities.ECBChainPlaybackState* chainStates, int currentChain, int nextChain) -> void_08f2b62234a514a789dc69881ac7811a
#5  0x000000404b8e18 in (wrapper managed-to-native) object:wrapper_native_0x7f6705982900 (intptr,int,intptr,int,int)
Segmentation fault (core dumped)

请问为何在内存未耗尽的情况下,AddEmptyChunk会触发段错误?


分析与解答

1. Chunk数量超限引发内部索引溢出

Unity Entities的Chunk管理系统中,部分内部数据结构使用32位整数追踪Chunk的索引或计数。当Chunk数量达到约1×10⁶时,部分计数器可能触发溢出,导致空指针引用(对应报错中的addr:(nil)),进而引发段错误。

2. ECB批量操作的结构性变更冲突

每帧通过ECBWriter批量创建实体并添加Buffer组件,高频的结构性变更(创建实体、添加Buffer)会导致ECB回放时频繁调用Chunk分配逻辑。当Chunk数量过大时,AddEmptyChunk在访问或更新全局Chunk管理链表/数组时,可能因索引溢出指向无效内存,触发空指针访问。

3. 旧版本Entities的已知Bug

你使用的两个Entities版本均存在大数量Chunk管理的已知问题:

  • 0.51.x预览版稳定性不足,对超大规模场景的Chunk处理逻辑存在缺陷;
  • 1.0.14正式版的后续更新日志中,明确提到修复了“大量Chunk下的空指针崩溃”问题,比如1.0.17+版本优化了Chunk分配的内存管理逻辑。

4. 内存碎片化的间接影响

虽然总内存未耗尽,但大量小Chunk的创建会导致内存碎片化,使得AddEmptyChunk尝试分配连续内存块时失败,返回空指针后未做校验,最终触发段错误。

解决建议

  • 升级Entities版本:更新到最新的LTS兼容版本(如1.0.20+),官方已修复大量此类大场景下的Chunk管理崩溃问题;
  • 优化实体创建逻辑:避免每帧创建大量小实体,尝试合并同类实体的Buffer数据,或使用对象池复用实体;
  • 调整Chunk容量:通过[ChunkCapacity]属性自定义Archetype的Chunk容量,减少总Chunk数量;
  • 监控内部状态:使用Entities的Profiler工具追踪Chunk数量、结构性变更频率,提前发现异常阈值。

内容的提问来源于stack exchange,提问作者Kaihui Gao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:59:52