x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Using Instanced Static Meshes in C++?

I was looking to start getting into procedural generation and the first thing I need to be able to do is create an instanced static mesh of a floor via C++ but there doesn't seem to be much on this topic or any help is somewhat outdated or isn't explained completely clearly.

What I seemed to be getting from some of the solutions was that I needed to create a new class for every different instanced static mesh I want to use. e.g. A separate class for floors, walls, corners, etc. Am I wrong in thinking this? It would be nice if someone could come in and clear this all up a little bit.

Is there a way to do it similar to the "Generating Procedural Rooms" video by Unreal in which they simply have one blueprint containing all different meshes that they can create new instances of individually? I would prefer to simply have a "ProceduralGeneration" actor class that I can place into the world that contains all the different instanced meshes which I can iterate between inside the class itself.

tl;dr: How to create instanced static meshes in C++ simply.

Product Version: UE 4.12
Tags:
more ▼

asked Aug 05 '16 at 12:16 AM in C++ Programming

avatar image

Gama97
15 3 6 9

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

There's a component called InstancedStaticMeshComponent. You add this component to any actor. This component has a static mesh field where you specify the mesh you want. It also has an "Instances" array where you add all the transforms you want for your static mesh.

 UInstancedStaticMeshComponent *ISMComp = NewObject<UInstancedStaticMeshComponent>(YourActor);
 ISMComp->RegisterComponent();
 ISMComp->SetStaticMesh(YourStaticMesh);
 ISMComp->SetFlags(RF_Transactional);
 YourActor->AddInstanceComponent(ISMComp);

Then you can add transforms like this:

 ISMComp->AddInstance(NewTran);

The transforms will be relative to your actor's transform.

You can spawn the actor in c++:

 YourActor = GetWorld()->SpawnActor<AActor>(AActor::StaticClass());

You can add as many Instanced static mesh components to your actor as you like.

more ▼

answered Aug 05 '16 at 01:14 AM

avatar image

rantrod
1.6k 49 48 218

avatar image Gama97 Aug 05 '16 at 01:36 AM

This looks great and I will definitely try it out tomorrow once I get up but briefly looking over it I'm assuming your examples imply that the InstancedStaticMeshComponent is on the actor of the class you're calling this code from? If so this is perfect.

avatar image rantrod Aug 05 '16 at 04:09 AM

Yes, the first two code snippets can be called from the actor creating the component. If you already have an actor and you want to put those snippets in that actor, then obviously you don't need the third snippet (the "SpawnActor" part).

avatar image Gama97 Aug 05 '16 at 10:04 AM

Hey sorry about this I'm kind of new to Unreal but I'm assuming that if I wanted to call this code from the actor creating the component I just replace "YourActor" with "this"? Or is there more to it than that because doing so makes me crash?

For example do I just do:

 UInstancedStaticMeshComponent *ISMComp = NewObject<UInstancedStaticMeshComponent>(this);

EDIT: Nevermind I got it working; I'm just not able to use the above in the constructor.

avatar image Gama97 Aug 05 '16 at 11:02 AM

For anyone reading this, I managed to get this working eventually by adding the first few code snippets into an override of the "OnConstruction" function to make all of this happen in the editor rather than only after pressing play. I had to do it like this instead of in the constructor because NewObject requires a valid actor within the world which my class wouldn't be during the constructor calls. I'm sure if you're adding this component to a different class you might be able to call the first snippets in the constructor but I just wanted to clarify it from my position. For reference here's the code that allowed it to work:

 void AProceduralGeneration::OnConstruction(const FTransform& Transform)
 {
     ISMComp = NewObject<UInstancedStaticMeshComponent>(this);
     ISMComp->RegisterComponent();
     ISMComp->SetStaticMesh(SMFloor);
     ISMComp->SetFlags(RF_Transactional);
     this->AddInstanceComponent(ISMComp);
 }

Thanks a bunch Rantrod, I really appreciate the help!

avatar image j_zeitler Oct 12 '16 at 07:24 AM

Great thread, saved me a couple of head aches I'm sure.

For some reason Gama97's code leaves references still present in the editor when re-running that OnConstruction method in my case. This adds up to a lot of InstancedStaticMeshComponent_#s when fiddling with parameters for the actor.

I solved it with a cleanup method running before anything else in OnConstruction.

 void AInstancedMeshField::cleanupInstanceComponents()
 {
     TArray<UActorComponent*> currentICs = this->GetInstanceComponents();
     for (UActorComponent* ic : currentICs)
         ic->DestroyComponent();
 }

Of course, this is a bit of a shotgun approach for cleanup. Did you guys manage to re-add ISMC's in any better way?

avatar image Fernando.Cesi Sep 03 '18 at 05:17 PM

So, I got it to work in a different way and doesn't create unwanted reference but its tricky to make it spawn …

.h file

 UPROPERTY(EditAnywhere)
 class UInstancedStaticMeshComponent* Spawner;

.cpp file

    #include "Engine/Classes/Components/InstancedStaticMeshComponent.h"
     AProceduralMeshSpawner::AProceduralMeshSpawner()
     {
         Spawner = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ROOT"));
         RootComponent =Spawner;
         
     }

this way you also have the transform of the "Root Component" working

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question