我们在使用HISMComponent管理实例时,遇到了从InstanceReorderTable里面取出来的值出现越界的问题
[Image Removed]
具体的操作包括:在同一帧内,对HISMComponent进行调用RemoveInstances和AddInstances
每次出现这个报错时,HISMComponent内,ClusterTree都处在异步构建中,即bIsAsyncBuilding=true
我们正在使用的版本是,UE5.3.2,想知道要定位这个问题,应该从哪些模块处入手,或者虚幻是否在后续版本中已经修复了这个问题
对这个问题再补充一些信息。
当出现这个ensure的check之前,HISMComponent经历了如下的调用:
1. AddInstances被调用后,bIsAsyncBuilding=true,bConcurrentChanges=false,bIsOutOfDate=true。这意味着,构建ClusterTree的任务已经被Dispatch了,PerInstanceSMData、InstanceReorderTable等的值也被更新了;
2. 同一帧的情况下,接着调用RemoveInstances后,此时bIsAsyncBuilding=true,bConcurrentChanges=true,bIsOutOfDate=true。意味着检查到ClusterTree正在构建,但又有修改发生了,所以bConcurrentChanges被设置为true了。相应的,PerInstanceSMData、InstanceReorderTable等的值再次被更新;
3. 在调用HISMComponent的CreateSceneProxy之前,ApplyBuildTreeAsync函数被调用,由于此时bConcurrentChanges=true,ApplyBuildTree不会被调用,而是再次进入BuildTreeAsync(在步骤1中已经被调用过了):
[Image Removed]
此时,在BuildTreeAsync函数中,PerInstanceRenderData->UpdateFromCommandBuffer(InstanceUpdateCmdBuffer);函数会被调用,InstanceUpdateCmdBuffer.NumEditInstances的值被更新:
[Image Removed]
如果Max(InstanceUpdateCmdBuffer.NumEditInstances, GetInstanceCount())的值,比InstanceReorderTable里面记录的值要少,后续的ensure就会被触发。
[Image Removed]
4. 问题的焦点在于InstanceUpdateCmdBuffer.NumEditInstances的值是这样计算的:
[Image Removed]
此时,如果渲染线程还没来得及调用:
InstanceBuffer->UpdateFromCommandBuffer_RenderThread(*NewCmdBuffer);
那么,这个时候,在Game线程中调用InstanceData->GetNumInstances();返回的就是步骤1调用时的值,但此时InstanceUpdateCmdBuffer.NumAdds的值一定为0,因为此时它记录的是步骤2中的值。
那么如果步骤2删除的Instance的数量比步骤1添加的Instance的数量要多,InstanceReorderTable中存储的值,就一定会有比Max(InstanceUpdateCmdBuffer.NumEditInstances, GetInstanceCount())的值要大的值,ensure的check就会被触发