c++ Set Mesh and Material For Hierarchical Instanced Static Mesh

Hi, I’m spawning HISM’s and can set my mesh vie the Main Editor (details) in the engine by manually selecting the mesh.

What I’m after is just being able to set the mesh in the c++ code.

.cpp

		MeshInstancesGroundTile50cm = ObjectInitializer.CreateDefaultSubobject<UHierarchicalInstancedStaticMeshComponent>(this, TEXT("MeshInstancesGroundTile50cm"));


								FVector resSpawnLocation = FVector(   ((resj / 3) *10)+ (((j / 3) * 1000)-1500), ((resheight - resi)*10)+ (((height - i) * 1000)-1500), 200.0f    );
								//FRotator SpawnRotation = FRotator(90.0f, 90.0f, 90.0f);

								ResInstanceTransform.SetLocation(resSpawnLocation);
								ResInstanceTransform.SetRotation(FQuat::MakeFromEuler({ 0.0f, 0.0f,0.0f }));
								
								//MeshInstancesGroundTile50cm->SetStaticMesh(GroundTile50cm);
								MeshInstancesGroundTile50cm->AddInstance(ResInstanceTransform);

.h

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		class UHierarchicalInstancedStaticMeshComponent* MeshInstancesGroundTile50cm;

Unfortunately I get identifier GroundTile50cm is undefined.

I just want to be ablt to set the mesh to use and the material instance, anyone know how to set this correctly?

Cheers

Within .cpp I’ve tried adding

#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"

and using…

auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Game/Meshes/Terrain/GroundTile50cm.GroundTile50cm'"));

		if (MeshAsset.Object != nullptr)
		{
			MeshInstancesGroundTile50cm->SetStaticMesh(MeshAsset.Object);
		}

But I can’t see my spaned tiles, suggesting that the mesh isn’t getting set.

I’ve right clicked on the asset and copied the reference, so I know the path should be ok.

When I run this I can see my array of HISM is created, 30+ of them, but the mesh element is still empty.

		if (MeshAsset.Object != nullptr)
		{
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Mesh found!"));
			MeshInstancesGroundTile50cm->SetStaticMesh(MeshAsset.Object);
		}

The text “Mesh found!” appears.

If I run…

		if (MeshAsset.Object == nullptr)
		{
			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Mesh not found!"));
			      //MeshInstancesGroundTile50cm->SetStaticMesh(MeshAsset.Object);
		}

No text appears. So it seems pretty conclusive that it finds the floor tile mesh

UStaticMesh* Mesh = LoadObject(nullptr, TEXT(“StaticMesh’/Game/Meshes/Terrain/GroundTile50cm.GroundTile50cm’”));
MeshInstancesGroundTile50cm->SetStaticMesh(Mesh);

This method works fine, the issue with the other method seems to be that the variable isn’t accessible outside of the constructor.

I’ve been searching for a solution in relation to ISM’s but this should apply to HISM’s as well, so for future peoples.

It is really good to create Blueprints of all your blueprintable classes and use ue macros to access and set references in BP, then use those references in C++ to spawn them/create them.

This is almost universal, and can be used on pretty much anything you can access in the editor.

The idea is to create an assignable reference in your code for the bp to allow you to select it from a drop down in editor.

public:  // or protected // or private (but you need to use  meta=(AllowPrivateAccess = "true"), in the uproperty macro)
UPROPERTY(EditAnywhere, BlueprintReadWrite)
   UstaticMesh* yourStaticMesh;

this is the most basic form it can have. You can pretty much replace the type with whatever you like.
TSubclassOf<UClass> is a really powerful one, if you want to select any child or parent and use that.

The great thing about this is that you completely avoid constructor helpers, and references being hard coded into your game .

On a final note, for h/ism’s, I’ve found that assigning the mesh and even the material doesn’t work for me in the constructor, so I’ve ended up doing it in PostInitializeComponents() instead. I think this makes sense, since the references arent live until they’re loaded, and they might not be ready while all constructors are still running.

ISMComponent->SetStaticMesh(yourStaticMesh);