UE4 How do I use InstancedStaticMeshes ?



1

I created a maze generator and I'm currently trying to figure out how to use an InstancedStaticMeshs in c++. Currently it spawns blueprints extended from a StaticMeshActor and I can only get about 10201 static meshes blueprints before i hit some heavy performance decrease, this is just on a maze alone

So when trying to make a rougelike maze dungeon with rooms and floors there are about ten to twenty times the static meshes. That's allot of static mesh blueprints. Anyone have example usage ?

Product Version:  Not Selected
Tags: blueprints c++ instanced mesh
maze101.png (434.8 kB)
more ▼

asked Apr 03 '14 at 1:58 AM

SaxonRah 
221  8  10  22

  Dieselhead  Apr 03 '14 at 9:43 PM

I'm only guessing here but I think a game like this would also benefit greatly from level streaming.

  SaxonRah  Apr 03 '14 at 10:51 PM

How would you level stream from actors spawned at run time ?

  Dieselhead  Apr 04 '14 at 2:04 AM

Well thats what you get when browsing this place the last hour of work :)

Sorry, carry on!


1 answer: sort voted first 
5

Instanced Static Mesh

You can make a new class, InstancedStaticMeshActor

and add a Instanced Static Mesh Component

Then you spawn that actor

and to add additional instances you use this function in the Instanced Static Mesh Component Class


        
          
          
          
          
  1. UFUNCTION(BlueprintCallable, Category="Components|InstancedStaticMesh")
  2. virtual void AddInstance(const FTransform& InstanceTransform);
  3.  
  4.  

That's pretty much all you need to do!

Here's my code from the beta, that I used for my own tests, here's a pic of my tests

In my case I extended a regular SMA so I would see the actor when it spawned :)

Spawning


        
          
          
          
          
  1. //Spawninfo
  2. FActorSpawnParameters SpawnInfo;
  3. //SET NO COLLISION FAIL TO TRUE
  4. SpawnInfo.bNoCollisionFail = true;
  5. SpawnInfo.Owner = VictoryEngine->VSelectedActor;
  6. AVictoryVertex3D* NewVertex =
  7. GetWorld()->SpawnActor<AVictoryVertex3D>(
  8. AVictoryVertex3D::StaticClass(),
  9. Pos,
  10. FRotator::ZeroRotator,
  11. SpawnInfo
  12. );
  13. if(!NewVertex) return NULL;
  14. if(!NewVertex->InstancedStaticMeshComponent) return NULL;
  15. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16. //Mesh
  17. NewVertex->InstancedStaticMeshComponent->SetStaticMesh(VictoryEngine->AssetSM_EngineCube);
  18. //Add Core Instance
  19. FTransform newT = NewVertex->GetTransform();
  20. newT.SetLocation(FVector(0,0,0));
  21. NewVertex->InstancedStaticMeshComponent->AddInstance(newT);
  22. //Scale
  23. NewVertex->SetActorRelativeScale3D(CurrentVerticiesScale);
  24.  
  25.  

.h


        
          
          
          
          
  1. // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
  2. //Power
  3. #pragma once
  4. #include "VictoryVertex3D.generated.h"
  5. /**
  6. * An instance of a StaticMesh in a level
  7. * Note that PostInitializeComponents() is not called for StaticMeshActors
  8. */
  9. UCLASS()
  10. class AVictoryVertex3D : public AStaticMeshActor
  11. {
  12. GENERATED_UCLASS_BODY()
  13. UPROPERTY()
  14. TSubobjectPtr<UInstancedStaticMeshComponent> InstancedStaticMeshComponent;
  15. UPROPERTY()
  16. UStaticMesh* SMAsset_Cube;
  17. };
  18.  

.cpp


        
          
          
          
          
  1. // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
  2. #include "VictoryGame.h"
  3. //
  4. // VictoryVertex3D
  5. //MAKE SEPARATE CLASSES OF THIS IF YOU WANT TO CHANGE THE MESH
  6. //
  7. AVictoryVertex3D::AVictoryVertex3D(const class FPostConstructInitializeProperties& PCIP)
  8. : Super(PCIP)
  9. {
  10. //Mesh
  11. static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshOb_torus(TEXT("StaticMesh'/Engine/EngineMeshes/Cube.Cube'"));
  12. SMAsset_Cube = StaticMeshOb_torus.Object;
  13. //create new object
  14. InstancedStaticMeshComponent = PCIP.CreateDefaultSubobject < UInstancedStaticMeshComponent > (this, TEXT("InstancedStaticMeshComponentCOMP"));
  15. InstancedStaticMeshComponent.AttachTo(RootComponent);
  16. //Not Made some reason?
  17. if (!InstancedStaticMeshComponent) return;
  18. //~~~~~~~~~~~~~~~~~~~~~~~~
  19. //Set to Asset
  20. InstancedStaticMeshComponent->SetStaticMesh(SMAsset_Cube);
  21. InstancedStaticMeshComponent->bOwnerNoSee = false;
  22. InstancedStaticMeshComponent->bCastDynamicShadow = false;
  23. InstancedStaticMeshComponent->CastShadow = false;
  24. InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  25. //Visibility
  26. InstancedStaticMeshComponent->SetHiddenInGame(false);
  27. //Mobility
  28. InstancedStaticMeshComponent->SetMobility(EComponentMobility::Movable);
  29. //Collision
  30. InstancedStaticMeshComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  31. InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  32. InstancedStaticMeshComponent->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
  33. InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
  34. InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
  35. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. if (!StaticMeshComponent) return;
  37. //Mobility
  38. StaticMeshComponent->SetMobility(EComponentMobility::Movable);
  39. //Collision
  40. StaticMeshComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  41. StaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  42. StaticMeshComponent->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
  43. StaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
  44. StaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
  45. }
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
more ▼

answered Apr 03 '14 at 8:24 PM

Rama 
7.7k  346  136  507

  SaxonRah  Apr 03 '14 at 10:51 PM

Thanks mate! You are the best :) !

  oOo.DanBO.oOo  May 11 '14 at 6:51 PM

i have a few problems when i try this solution. my objects get spawned in the world. but it seems they dont have a material applied even if i apply it in the code.

so for me the main difference is that instead of TSubobjectPtr MyBlock; i use this: TSubobjectPtr MyBlock;

and of course also in cpp for the pcip createabstractdefaul.....

but then the block has no material :<

  Rama  May 13 '14 at 7:32 AM

you'll have to post your code for us to help you

also, it'd be better to post your issue as a separate topic so we can focus just on your issue :)

:)

Rama

  Neil.Griffiths  Jul 01 '14 at 12:15 AM

I know I'm late to this party but I'm guessing this is because your material isn't set up to work on Instanced Meshes. Open up your material in the Material Editor (by double-clicking it in the Resource Browser) and set the property. :)

  DJ_Lectr0  Aug 05 '14 at 10:58 PM

What if I needed to apply an instanced Material with a parameter wich is different for every instance? Would I just override AddInstance? And how would I get the static mesh created in there?

  DJ_Lectr0  Aug 06 '14 at 12:06 AM

And also: How can I enable collision with my character??

  Hyperloop  Aug 23 '14 at 2:10 AM

Rama, first off, thanks for being so active and helpful in the community I swear every third post I find turns out to be from you :D

I'm trying to solve this exact problem for myself as well and I have two quick(ish) questions:

  1. Does implementing this class help solve the issue of not being able to get a reference to a specific instance of a static mesh component during runtime? I'm running into that limitation, and it's a dealbreaker because I need to be able to spawn AND destroy instances of the static mesh at runtime based on player interaction, but I can't seem to do that via blueprints :/

2: If I place multiple instances of this actor into the world, do they each reference the SAME mesh, thereby helping to limit draw calls?

That's the other huge issue I am hitting as I try to solve this with blueprints: Each instance of a BP that contains an instanced mesh isn't inheriting or 'grouping'/batching with the other instances even though it's the same mesh. Functionally, that means I can't make use of instanced meshes unless they ALL spawn from the same blueprint....and if they all spawn in the same BP, I can't get a reference to a single instance to destroy it so it's kind of useless for what I need to do :/

Your reply here was the closest thing I have found that might be a solution, I'm not a coder (yet) so I wanted to ask those Questions before I dive in and learn how to implement this :D

  Hyperloop  Aug 23 '14 at 6:43 AM

Editing my post in regards to the first question: it would seem that in 4.4 they have JUST added the ability to do this!

"InstancedStaticMeshComponents now set the FHitResult.Item property with the index an instance hit by a collision event. This can be used with the above functions to remove a specific instance and replace it with a real StaticMeshComponent to provide interactivity with Foliage or other behavior."

This is great news!

Still not sure how/if multiple Blueprints can have objects that are references to the same static mesh.

  Plorax  Oct 08 '14 at 5:19 AM

What is an SMA ?

Sorry, I'm not familiar with the acronyms.

Also, is this code still valid for UE 4.4 ?

Please can someone point me in the right direction or show me a sample project doing the same InstanceStaticMesh thingy..

  SaxonRah  Oct 08 '14 at 6:21 AM

SMA is StaticMeshActor.

I haven't updated this project to 4.4 so im not entirely sure,but it should.

Are you making sure you are adding an instance of it ?

  PhoenixFalcon  Nov 22 '15 at 7:59 PM

Hi, I am trying to add InstancedStaticMeshComponent using the code above. It works for single component. However when I try to add three different instanced mesh componentes they all look the same. For example the first added mesh is floor, the second and the third are cubes. Everything is rendered as floor mesh.

  PhoenixFalcon  Nov 29 '15 at 7:44 PM  Newest

Turns out the problem is with this line static ConstructorHelpers::FObjectFinder StaticMeshOb_torus(TEXT("StaticMesh'/Engine/EngineMeshes/Cube.Cube'")); I removed static and it seems to be working.


1

I created a maze generator and I'm currently trying to figure out how to use an InstancedStaticMeshs in c++. Currently it spawns blueprints extended from a StaticMeshActor and I can only get about 10201 static meshes blueprints before i hit some heavy performance decrease, this is just on a maze alone

So when trying to make a rougelike maze dungeon with rooms and floors there are about ten to twenty times the static meshes. That's allot of static mesh blueprints. Anyone have example usage ?

Product Version:  Not Selected
Tags: blueprints c++ instanced mesh
maze101.png (434.8 kB)
more ▼

asked Apr 03 '14 at 1:58 AM

SaxonRah 
221  8  10  22

  Dieselhead  Apr 03 '14 at 9:43 PM

I'm only guessing here but I think a game like this would also benefit greatly from level streaming.

  SaxonRah  Apr 03 '14 at 10:51 PM

How would you level stream from actors spawned at run time ?

  Dieselhead  Apr 04 '14 at 2:04 AM

Well thats what you get when browsing this place the last hour of work :)

Sorry, carry on!


1 answer: sort voted first 
5

Instanced Static Mesh

You can make a new class, InstancedStaticMeshActor

and add a Instanced Static Mesh Component

Then you spawn that actor

and to add additional instances you use this function in the Instanced Static Mesh Component Class


         
           
           
           
           
  1. UFUNCTION(BlueprintCallable, Category="Components|InstancedStaticMesh")
  2. virtual void AddInstance(const FTransform& InstanceTransform);
  3.  
  4.  

That's pretty much all you need to do!

Here's my code from the beta, that I used for my own tests, here's a pic of my tests

In my case I extended a regular SMA so I would see the actor when it spawned :)

Spawning


         
           
           
           
           
  1. //Spawninfo
  2. FActorSpawnParameters SpawnInfo;
  3. //SET NO COLLISION FAIL TO TRUE
  4. SpawnInfo.bNoCollisionFail = true;
  5. SpawnInfo.Owner = VictoryEngine->VSelectedActor;
  6. AVictoryVertex3D* NewVertex =
  7. GetWorld()->SpawnActor<AVictoryVertex3D>(
  8. AVictoryVertex3D::StaticClass(),
  9. Pos,
  10. FRotator::ZeroRotator,
  11. SpawnInfo
  12. );
  13. if(!NewVertex) return NULL;
  14. if(!NewVertex->InstancedStaticMeshComponent) return NULL;
  15. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16. //Mesh
  17. NewVertex->InstancedStaticMeshComponent->SetStaticMesh(VictoryEngine->AssetSM_EngineCube);
  18. //Add Core Instance
  19. FTransform newT = NewVertex->GetTransform();
  20. newT.SetLocation(FVector(0,0,0));
  21. NewVertex->InstancedStaticMeshComponent->AddInstance(newT);
  22. //Scale
  23. NewVertex->SetActorRelativeScale3D(CurrentVerticiesScale);
  24.  
  25.  

.h


         
           
           
           
           
  1. // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
  2. //Power
  3. #pragma once
  4. #include "VictoryVertex3D.generated.h"
  5. /**
  6. * An instance of a StaticMesh in a level
  7. * Note that PostInitializeComponents() is not called for StaticMeshActors
  8. */
  9. UCLASS()
  10. class AVictoryVertex3D : public AStaticMeshActor
  11. {
  12. GENERATED_UCLASS_BODY()
  13. UPROPERTY()
  14. TSubobjectPtr<UInstancedStaticMeshComponent> InstancedStaticMeshComponent;
  15. UPROPERTY()
  16. UStaticMesh* SMAsset_Cube;
  17. };
  18.  

.cpp


         
           
           
           
           
  1. // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
  2. #include "VictoryGame.h"
  3. //
  4. // VictoryVertex3D
  5. //MAKE SEPARATE CLASSES OF THIS IF YOU WANT TO CHANGE THE MESH
  6. //
  7. AVictoryVertex3D::AVictoryVertex3D(const class FPostConstructInitializeProperties& PCIP)
  8. : Super(PCIP)
  9. {
  10. //Mesh
  11. static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshOb_torus(TEXT("StaticMesh'/Engine/EngineMeshes/Cube.Cube'"));
  12. SMAsset_Cube = StaticMeshOb_torus.Object;
  13. //create new object
  14. InstancedStaticMeshComponent = PCIP.CreateDefaultSubobject < UInstancedStaticMeshComponent > (this, TEXT("InstancedStaticMeshComponentCOMP"));
  15. InstancedStaticMeshComponent.AttachTo(RootComponent);
  16. //Not Made some reason?
  17. if (!InstancedStaticMeshComponent) return;
  18. //~~~~~~~~~~~~~~~~~~~~~~~~
  19. //Set to Asset
  20. InstancedStaticMeshComponent->SetStaticMesh(SMAsset_Cube);
  21. InstancedStaticMeshComponent->bOwnerNoSee = false;
  22. InstancedStaticMeshComponent->bCastDynamicShadow = false;
  23. InstancedStaticMeshComponent->CastShadow = false;
  24. InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  25. //Visibility
  26. InstancedStaticMeshComponent->SetHiddenInGame(false);
  27. //Mobility
  28. InstancedStaticMeshComponent->SetMobility(EComponentMobility::Movable);
  29. //Collision
  30. InstancedStaticMeshComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  31. InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  32. InstancedStaticMeshComponent->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
  33. InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
  34. InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
  35. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. if (!StaticMeshComponent) return;
  37. //Mobility
  38. StaticMeshComponent->SetMobility(EComponentMobility::Movable);
  39. //Collision
  40. StaticMeshComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
  41. StaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
  42. StaticMeshComponent->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
  43. StaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
  44. StaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
  45. }
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
more ▼

answered Apr 03 '14 at 8:24 PM

Rama 
7.7k  346  136  507

  SaxonRah  Apr 03 '14 at 10:51 PM

Thanks mate! You are the best :) !

  oOo.DanBO.oOo  May 11 '14 at 6:51 PM

i have a few problems when i try this solution. my objects get spawned in the world. but it seems they dont have a material applied even if i apply it in the code.

so for me the main difference is that instead of TSubobjectPtr MyBlock; i use this: TSubobjectPtr MyBlock;

and of course also in cpp for the pcip createabstractdefaul.....

but then the block has no material :<

  Rama  May 13 '14 at 7:32 AM

you'll have to post your code for us to help you

also, it'd be better to post your issue as a separate topic so we can focus just on your issue :)

:)

Rama

  Neil.Griffiths  Jul 01 '14 at 12:15 AM

I know I'm late to this party but I'm guessing this is because your material isn't set up to work on Instanced Meshes. Open up your material in the Material Editor (by double-clicking it in the Resource Browser) and set the property. :)

  DJ_Lectr0  Aug 05 '14 at 10:58 PM

What if I needed to apply an instanced Material with a parameter wich is different for every instance? Would I just override AddInstance? And how would I get the static mesh created in there?

  DJ_Lectr0  Aug 06 '14 at 12:06 AM

And also: How can I enable collision with my character??

  Hyperloop  Aug 23 '14 at 2:10 AM

Rama, first off, thanks for being so active and helpful in the community I swear every third post I find turns out to be from you :D

I'm trying to solve this exact problem for myself as well and I have two quick(ish) questions:

  1. Does implementing this class help solve the issue of not being able to get a reference to a specific instance of a static mesh component during runtime? I'm running into that limitation, and it's a dealbreaker because I need to be able to spawn AND destroy instances of the static mesh at runtime based on player interaction, but I can't seem to do that via blueprints :/

2: If I place multiple instances of this actor into the world, do they each reference the SAME mesh, thereby helping to limit draw calls?

That's the other huge issue I am hitting as I try to solve this with blueprints: Each instance of a BP that contains an instanced mesh isn't inheriting or 'grouping'/batching with the other instances even though it's the same mesh. Functionally, that means I can't make use of instanced meshes unless they ALL spawn from the same blueprint....and if they all spawn in the same BP, I can't get a reference to a single instance to destroy it so it's kind of useless for what I need to do :/

Your reply here was the closest thing I have found that might be a solution, I'm not a coder (yet) so I wanted to ask those Questions before I dive in and learn how to implement this :D

  Hyperloop  Aug 23 '14 at 6:43 AM

Editing my post in regards to the first question: it would seem that in 4.4 they have JUST added the ability to do this!

"InstancedStaticMeshComponents now set the FHitResult.Item property with the index an instance hit by a collision event. This can be used with the above functions to remove a specific instance and replace it with a real StaticMeshComponent to provide interactivity with Foliage or other behavior."

This is great news!

Still not sure how/if multiple Blueprints can have objects that are references to the same static mesh.

  Plorax  Oct 08 '14 at 5:19 AM

What is an SMA ?

Sorry, I'm not familiar with the acronyms.

Also, is this code still valid for UE 4.4 ?

Please can someone point me in the right direction or show me a sample project doing the same InstanceStaticMesh thingy..

  SaxonRah  Oct 08 '14 at 6:21 AM

SMA is StaticMeshActor.

I haven't updated this project to 4.4 so im not entirely sure,but it should.

Are you making sure you are adding an instance of it ?

  PhoenixFalcon  Nov 22 '15 at 7:59 PM

Hi, I am trying to add InstancedStaticMeshComponent using the code above. It works for single component. However when I try to add three different instanced mesh componentes they all look the same. For example the first added mesh is floor, the second and the third are cubes. Everything is rendered as floor mesh.

  PhoenixFalcon  Nov 29 '15 at 7:44 PM  Newest

Turns out the problem is with this line static ConstructorHelpers::FObjectFinder StaticMeshOb_torus(TEXT("StaticMesh'/Engine/EngineMeshes/Cube.Cube'")); I removed static and it seems to be working.


你可能感兴趣的:(Unreal,引擎工具,开发工具,游戏开发,图形引擎,游戏引擎)