HISM Component causes crash on UpdateInstanceTransform

Hello,
i wanted to report a bug in the function UHierarchicalInstancedStaticMeshComponent::UpdateInstanceTransform() in the HierarchicalInstancedStaticMesh.cpp

In our project we alter the transform of an instance from time to time. It appears when running the client in dedicatedserver mode this can cause a crash at the line :

1943 int32 RenderIndex = InstanceReorderTable[InstanceIndex];

InstanceReorderTable has a size of 0, even though the check at the start of the function

	if (!PerInstanceSMData.IsValidIndex(InstanceIndex))
	{
		return false;
	}

can return true in case you are using a DedicatedServer but the InstanceReorderTable is not populated - thus causing a crash.

Hello Burnz,

Have you been able to reproduce this in a fresh project or is it only occurring in your project? Could you give an example of what type of movements you’re making and how many instances are in one of these components that are causing a crash? I’ll need more information than just the source context to try to reproduce this.

Hello Matthew,
i simply wanted to let you know about the issue, i applied a fix already. You do not need a fresh project as it’s obvious what’s happening here. Dedicated Servers do not process Rendering, therefore the InstanceReorderTable is not populated.

The solution is to check if we are running as a dedicated server and if we do so we’ll just update the transform but do not recalculate bounds as the RenderIndex is not available (as we are not rendering).

	const FMatrix OldTransform = PerInstanceSMData[InstanceIndex].Transform;
	const FTransform NewLocalTransform = bWorldSpace ? NewInstanceTransform.GetRelativeTransform(ComponentToWorld) : NewInstanceTransform;
	const FVector NewLocalLocation = NewLocalTransform.GetTranslation();

	bool Result = Super::UpdateInstanceTransform(InstanceIndex, NewInstanceTransform, bWorldSpace, bMarkRenderStateDirty, bTeleport);
	
	if (IsRunningDedicatedServer())
		return Result;

	// if we are only updating rotation/scale we update the instance directly in the cluster tree
	
	int32 RenderIndex = InstanceReorderTable[InstanceIndex];
	const bool bIsOmittedInstance = (RenderIndex == INDEX_NONE);
	const bool bIsBuiltInstance = !bIsOmittedInstance && RenderIndex < NumBuiltRenderInstances;
	const bool bDoInPlaceUpdate = !bIsOmittedInstance && (!bIsBuiltInstance || NewLocalLocation.Equals(OldTransform.GetOrigin()));

Hi Matthew. I ran into this problem too. I assumed the server would ignore any rendering stuff it didn’t need to handle but I guess I was wrong. It does run with the “server” that you spawn from the editor, by the way. Unfortunately, Burnz’s solution is not the answer (IMO) because it requires end users to modify the engine source. If his solution works, I hope Epic can get it integrated into an update. In the meantime, I would say a more proper workaround is to check for dedicated server in project code/BP and just not call the update instance transform function at all. But again, I think the engine should handle it internally so our code can stay cleaner – or at least it should do something besides crash.

Hello Jin_VE,

I would be happy to look into this, but my questions for you are the same as what I asked of Burnz. Either a reproduction project or specifics on what the setup you’re using is would be helpful. I haven’t messed with this recently but I do vague remember trying to reproduce it but not being able to.