How to efficiently update InstancedStaticMesh in C++

I am trying to create a set of instanced objects in Unreal and update their locations and color each frame. I have not coded (looked into how to do) the color modification yet. Tips on changing color would be helpful.

The below code demonstrates creating a set of instances and modifying their location each frame, but the amount of memory read and manipulated seems excessive for only needing to change the location (transform). The updated location data will come from sources external to unreal so it can be assumed that there is an array of float3 with new locations each frame.

What would be the most efficient way to update instance locations each frame?

**Is there a way to change the rendered count, rendering all or a subset of the instances each frame? **
Such as rendering all one frame then the first 70% the next frame, and so on.

Also the same should work with UHierarchicalInstancedStaticMeshComponent?

(I am trying to port my scientific partial simulation visualization from DirectX12 to Unreal. Typical particle counts are 20k to 500k.)

From header file
virtual void Tick(float DeltaTime) override;

UPROPERTY(EditAnywhere, BlueprintReadWrite)
//UPROPERTY(VisibleDefaultsOnly)
UInstancedStaticMeshComponent* MeshInstances;

float Increment = 0.0f;
From cpp file
void AInstMeshActor::BeginPlay()
{
	Super::BeginPlay();

	for (int32 y = 0; y < 20; y++) {
		for (int32 x = 0; x < 20; x++) {
			FTransform Trans;
			FVector Spawn(x * 10.0f - 100.0f, y * 10.0f - 100.0f, 20.0f);
			FVector Scale(0.08f, 0.08f, 0.08f);
			Trans.SetLocation(Spawn);
			Trans.SetScale3D(Scale);
			MeshInstances->AddInstance(Trans);
		}
	}
}

void AInstMeshActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	for (int32 i = 0; i < MeshInstances->GetInstanceCount(); i++) {
	
		// Only for making this test
		// ** In future there will be a data source with updated locations
		FTransform Trans;
		MeshInstances->GetInstanceTransform(i, Trans, false);
		FVector Spawn = Trans.GetLocation();
		Spawn.Z = 10.0f + cos(Increment) * 10.0f;
		Trans.SetLocation(Spawn);

		// Is there a way to update location without touching as much data
		// ** FTransform is 3 vectors and I only need to modify one
		// ** Something like using memcpy to update instance locations would be nice

		if(i < MeshInstances->GetInstanceCount() - 1)
			MeshInstances->UpdateInstanceTransform(i, Trans, false, false, true);
		else
			MeshInstances->UpdateInstanceTransform(i, Trans, false, true, true);
	}

	Increment += 0.01f;
}
2 Likes