In UE5.7, using UpdateInstanceTransform on InstanceStaticMesh performs poorly.

In UE5.7, calling UpdateInstanceTransform on InstanceStaticMesh 10,000 times in a C loop takes 50-100 times longer than in UE5.1. The performance of UpdateInstanceTransform is very poor.

Testing found that if all objects in collisions are set to ignore responses and collision is enabled only for queries, the performance is very good.

In UE5.1, calling UpdateInstanceTransform on InstanceStaticMesh 10,000 times in a C loop performs well. This is true even when queries and physics are enabled and all object responses are set to block.

UE5.7
Collision Presets:BlockAllDynamic
C++ UpdateInstanceTransform :10000
Time:3.43s

UE5.7
Collision Presets:Custom
Object Responses:All Ignore
C++ UpdateInstanceTransform :10000
Time:0.05s

UE5.1

Collision Presets:BlockAllDynamic
C++ UpdateInstanceTransform :10000
Time:0.05s

Try using batch update, its got better performance


#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ActorInst.generated.h"

class UInstancedStaticMeshComponent;
class UStaticMesh;

UCLASS()
class YOUR_API AActorInst : public AActor
{
	GENERATED_BODY()
	
public:	

	AActorInst();

protected:

	virtual void BeginPlay() override;

public:	

	virtual void Tick(float DeltaTime) override;

public: 
	UPROPERTY(BlueprintReadWrite, Editanywhere)
	UInstancedStaticMeshComponent* MeshComp;

	UPROPERTY(BlueprintReadWrite, Editanywhere)
	UStaticMesh* Mesh;

	UPROPERTY(BlueprintReadWrite, Editanywhere)
	float size = 100;

	TArray<FTransform> transforms;
};

cpp

#include "ActorInst.h"

#include "Components/InstancedStaticMeshComponent.h"


AActorInst::AActorInst()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	MeshComp = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("Mesh"));
}


void AActorInst::BeginPlay()
{
	MeshComp->SetStaticMesh(Mesh);
	Super::BeginPlay();

	
	int index = 0;
	for (int x = 0; x < 21; x++) {
		for (int y = 0; y < 21; y++) {
			for (int z = 0; z < 21; z++) {				
				FTransform tr;
				tr.SetRotation(FQuat::MakeFromRotator(FRotator::ZeroRotator));
				tr.SetScale3D(FVector(1,1,1));
				tr.SetLocation(FVector(x * size, y * size, z * size));

				transforms.Init(tr,index);

				MeshComp->AddInstance(tr,false);
				index++;
			}
		}
	}
}


void AActorInst::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	
	int index = 0;
	for (int x = 0; x < 21; x++) {
		for (int y = 0; y < 21; y++) {
			for (int z = 0; z < 21; z++) {
				FTransform tr;
				tr.SetRotation(FQuat::MakeFromRotator(FRotator::ZeroRotator));
				tr.SetScale3D(FVector(1, 1, 1));
				tr.SetLocation(FVector(x * size + FMath::RandRange(0, 99), y * size + FMath::RandRange(0, 99), z * size+ FMath::RandRange(0, 99)));				
				if (transforms.IsValidIndex(index)) {
					transforms[index] = tr;
				}
				index++;
			}
		}
	}

	MeshComp->BatchUpdateInstancesTransforms(0, transforms);

}


It updates the whole instance mesh matrix transform via an array instead of per index