This issue is occurring as part of our internal engine upgrade to 5.6. We were previously on version 5.5.
The crash specifically happens on line 249 of InstanceDataUpdateUtils.h but the data it is operating on is `ChangeSet.PrevTransforms` at line 171 of ISMInstanceDataSceneProxy.cpp
As far as I can tell, the data array is emptied during the Changeset build function, when it performs the delta write, as no elements have changed.
We’ve fixed this locally by checking if `PrevTransforms` is empty before calling `ApplyTransformUpdates` and don’t seem to be encountering any issues but we haven’t performed extensive tests just yet.
If this should be an invalid state at this point in the pipeline, any guidance on what could cause it would be appreciated.
Steps to Reproduce
I haven’t had the time to try and create a repro project, but our setup involves deferred registration of an Instanced Static Mesh Component for our vehicle wheels.
We initialize some ISM data before finalizing the registration via `AddInstances`, `SetHasPerInstancedPrevTransforms(true)`, and `BatchUpdateInstancesTransforms`.
`BatchUpdateInstancesTransforms` is called once more via `OnRegister` on the component as well.
When the vehicle is spawned in the crash occurs due to `ChangeSet.PrevTransforms` being empty.
Hi.
There ought to be an 1:1 between the transforms & prev transform in the change set, as they use the same delta (if they are enabled), so this seems like an unexpected state to me. Does the change set have transforms at this point? I assume so or it should have crashed at that point instead. So the question is why it does not populate the prev transforms in the change set. It would be helpful if you could look into that. It should be populated alongside the transforms in UInstancedStaticMeshComponent::BuildComponentInstanceData.
Hi Ola,
I can confirm that PrevTransforms fails to be set in UInstancedStaticMeshComponent::BuildComponentInstanceData
`ChangeSet.SetInstancePrevTransforms(MakeArrayView(PerInstancePrevTransform));
if (PerInstancePrevTransform.Num() != ChangeSet.PrevTransforms.Num())
{
UE_LOG(LogTemp, Error, TEXT(“Prev Transforms not modified correctly! PerInstancePrevTransform: %i, PrevTransforms: %i”), PerInstancePrevTransform.Num(), ChangeSet.PrevTransforms.Num());
}`When our vehicles spawn in we get a spam of the error posted above.
LogTemp: Error: Prev Transforms not modified correctly! PerInstancePrevTransform: 4, PrevTransforms: 0
Can you see what it is inside SetInstancePrevTransforms that causes it to skip them, since there’s data there it seems it has to be either some flag or the used delta. It’s be helpful to know which it is.
I made a similar setup out of a test component I have where inside TickComponent I call:
if (ISMC->GetNumInstances() == 0) { ISMC->AddInstances(InstanceTransforms, false, false, false); ISMC->SetHasPerInstancePrevTransforms(true); } TArray<FTransform> PrevInstanceTransforms = InstanceTransforms; FTransform Rot(FRotator(0.0, RotationSpeed, 0.0)); for (FTransform& Tfm : InstanceTransforms) { Tfm = Tfm * Rot; } ISMC->BatchUpdateInstancesTransforms(0, InstanceTransforms, PrevInstanceTransforms);
This works as expected so feels like there must be something about your specific use case.
Hey Ola. From what I can tell the Delta should only be empty if bForceEmpty is true, or if NumSourceInstances is 0, correct?
I can confirm NumSourceInstances is 4 prior to the call, as well as that bHasPerInstanceDynamicData is true so bForceEmpty is false.
Here’s a screenshot of the ChangeSet data. I did cache NumSourceInstances before the call so I can confirm that’s not a side-effect of the call.
[Image Removed]
Here’s a log of the relevant data also:
Error LogTemp Prev Transforms not modified correctly! PerInstancePrevTransform: 4, PrevTransforms: 0 Error LogTemp Flags: 0000000000000101 Error LogTemp Force Full Flags: 0000000000000000 Error LogTemp bNeedFullUpdate: No Error LogTemp Num Source Instances: 4
Here’s a screenshot of the Delta Setup as well along with the Delta expanded:
[Image Removed]
A bit more info on our setup:
We update the instance transforms when the vehicle is spawned, and as part of NativePostEvaluateAnimation in our Vehicle Anim Instance.
- Component is created with deferred registration
- AddInstances and SetHasPerInstancePrevTransforms is called
- UpdateWheelMeshTransforms is called
- Component is registered
- UpdateWheelMeshTransforms is called
- NativePostEvaluateAnimation is called on our vehicle anim instance
- UpdateWheelMeshTransforms is called
UpdateWheelMeshTransforms pseudo-code:
`CurrentTransforms = {}
for WheelSocket in VehicleMovementComponent:
CurrentTransforms.Add(GetSocketTransform(WheelSocket))
BatchUpdateInstancesTransform(0, CurrentTransforms, PreviousTransforms, false, true, false)
PreviousTransforms = CurrentTransforms` I can also confirm from logging that the issue doesn’t just occur when spawning in the vehicle. The logging I added is also happening when driving around.
Ok, pretty sure I can see the issue at play now - seems more of a mystery why it has not come up before now. I guess it probably doesn’t cause a crash in shipping builds (most of the time).
GetTransformSetup() uses bUpdateAllInstanceTransforms to determine if it should populate the array, but the GetPrevTransformSetup() doesn’t. So in the case where that flag is set to force a full tfm update it may not populate the prev transforms. In ApplyDataChanges we just use GetTransformDelta directly, hence the mismatch.
Based on this, I’ve been able to make a local repro now. Preliminary fix:
auto GetPrevTransformSetup() { return GetSetup<FInstanceAttributeTracker::EFlag::TransformChanged>(Flags.bHasPerInstanceDynamicData, ForceFullFlags.bHasPerInstanceDynamicData || bUpdateAllInstanceTransforms, PrevTransforms); }
Basically this would happen e.g., if the primitive transform is modified but not the instance transforms.
Great! I’ll get the fix into 5.7, not sure if there are any more hotfixes before then or if this would warrant hotfix priority.
Thank you for reaching out and helping track this down! All the details were super helpful to narrow this down quickly.
Best,
Ola
Can confirm that seems to fix the issue. No longer seeing any of my error logs.