UE4 How do I use InstancedStaticMeshes ?

1649 篇文章 12 订阅
1623 篇文章 23 订阅


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 ?

alt text

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

asked Apr 03 '14 at 1:58 AM

SaxonRah gravatar image

SaxonRah 
221  8  10  22

Dieselhead gravatar image  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 gravatar image  SaxonRah  Apr 03 '14 at 10:51 PM

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

Dieselhead gravatar image  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 gravatar image

Rama 
7.7k  346  136  507

SaxonRah gravatar image  SaxonRah  Apr 03 '14 at 10:51 PM

Thanks mate! You are the best :) !

oOo.DanBO.oOo gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  DJ_Lectr0  Aug 06 '14 at 12:06 AM

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

Hyperloop gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 ?

alt text

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

asked Apr 03 '14 at 1:58 AM

SaxonRah gravatar image

SaxonRah 
221  8  10  22

Dieselhead gravatar image  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 gravatar image  SaxonRah  Apr 03 '14 at 10:51 PM

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

Dieselhead gravatar image  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 gravatar image

Rama 
7.7k  346  136  507

SaxonRah gravatar image  SaxonRah  Apr 03 '14 at 10:51 PM

Thanks mate! You are the best :) !

oOo.DanBO.oOo gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  DJ_Lectr0  Aug 06 '14 at 12:06 AM

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

Hyperloop gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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 gravatar image  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.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值