Instanced Compoenent with instances only visible in scene if VisibleAnywhere used

I have a InstancedStaticMesh component that is populated during PostInitializedComponenets()… I also check for a couple of changed properties via the PostEditPropertyChanged().

My issue is, the instances show up in the right details panel, and it bogs down the system for a little bit when selecting the actor in the outliner. I tried removing VisibleAnywhere from the InstancedStaticMesh component (it is a UPROPERTY in the class) and then the instances not only disappear in the details panel, but also in the editor scene view.

Is this expected behavior? (btw i know that the addinstance code is still being called because of prints)

code follows:

UCLASS()
class BOTBATTLE_API AHexGrid : public AActor
    {
    GENERATED_UCLASS_BODY()

	private:
		void PositionTiles();

    public:
        static FVector GetHexPosition(int32 x, int32 y, float cornerRadius);
		static EFacing::Type GetReverseFacing(EFacing::Type facing);
		static EFacing::Type GetLeftFacing(EFacing::Type facing);
		static EFacing::Type GetRightFacing(EFacing::Type facing);
		
		void PostInitializeComponents() override;
		void PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent) override;

		UFUNCTION(BlueprintCallable, BlueprintPure, Category = Function)
		static FRotator RotationFromFacing(EFacing::Type facing);

		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
		int32 maxQ;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
		int32 maxR;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
		EGridShape gridShape;

		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
		TArray<ULevelFilter*> levelFilters;

		TMap<FHex, EHexType> HexGrid;

		UPROPERTY(BlueprintReadWrite, VisibleAnywhere, Category = "Hex Tile Instanced Mesh")
		UInstancedStaticMeshComponent* InstancedFloorTile;
		UPROPERTY(BlueprintReadWrite, Category = "Hex Tile Instanced Mesh")
		UStaticMesh* SMAsset_Floor;

		UPROPERTY(BlueprintReadWrite, VisibleAnywhere, Category = "Hex Tile Instanced Mesh")
		UInstancedStaticMeshComponent* InstancedWallTile;
		UPROPERTY(BlueprintReadWrite, Category = "Hex Tile Instanced Mesh")
		UStaticMesh* SMAsset_Wall;

		virtual void BeginPlay() override; 
		bool GetColumnAndRow(AHexTile *hex, int32 *column, int32 *row);
        AHexTile *GetAdjacentHex(AHexTile *hex, EFacing::Type facing);
		
		virtual void OnConstruction(const FTransform& Transform) override;


    };

AHexGrid::AHexGrid(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
	{
	//Mesh
	static ConstructorHelpers::FObjectFinder<UStaticMesh> floorTileMesh((TEXT("StaticMesh'/Game/Meshes/hextile.HexTile'")));
	SMAsset_Floor = floorTileMesh.Object;

	//create new object
	InstancedFloorTile = PCIP.CreateDefaultSubobject<UInstancedStaticMeshComponent>(this, TEXT("InstancedFloorTile"));
	
	//Not Made some reason?
	if (!InstancedFloorTile) return;
	
	InstancedFloorTile->AttachTo(RootComponent);

	//Set to Asset
	InstancedFloorTile->SetStaticMesh(SMAsset_Floor);

	InstancedFloorTile->bOwnerNoSee = false;
	InstancedFloorTile->bCastDynamicShadow = false;
	InstancedFloorTile->CastShadow = false;
	
	//Visibility
	InstancedFloorTile->SetHiddenInGame(false);

	////Mobility
	InstancedFloorTile->SetMobility(EComponentMobility::Static);

	//Collision
	InstancedFloorTile->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	InstancedFloorTile->BodyInstance.SetObjectType(ECC_WorldStatic);
	InstancedFloorTile->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
	InstancedFloorTile->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
	InstancedFloorTile->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);

	////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	//Mesh
	static ConstructorHelpers::FObjectFinder<UStaticMesh> wallTileMesh((TEXT("StaticMesh'/Game/Meshes/hex_wall.hex_wall'")));
	SMAsset_Wall = wallTileMesh.Object;

	//create new object
	InstancedWallTile = PCIP.CreateDefaultSubobject<UInstancedStaticMeshComponent>(this, TEXT("InstancedWallTile"));

	//Not Made some reason?
	if (!InstancedWallTile) return;

	InstancedWallTile->AttachTo(RootComponent);

	//Set to Asset
	InstancedWallTile->SetStaticMesh(SMAsset_Floor);

	InstancedWallTile->bOwnerNoSee = false;
	InstancedWallTile->bCastDynamicShadow = false;
	InstancedWallTile->CastShadow = false;

	//Visibility
	InstancedWallTile->SetHiddenInGame(false);

	////Mobility
	InstancedWallTile->SetMobility(EComponentMobility::Static);

	//Collision
	InstancedWallTile->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	InstancedWallTile->BodyInstance.SetObjectType(ECC_WorldStatic);
	InstancedWallTile->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
	InstancedWallTile->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
	InstancedWallTile->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
	}

void AHexGrid::OnConstruction(const FTransform& Transform) {
	
}

void AHexGrid::PostInitializeComponents() 
	{
	Super::PostInitializeComponents();
	HexGrid.Reset();
	InstancedFloorTile->ClearInstances();
	this->PositionTiles();
	}

#if WITH_EDITOR  
void AHexGrid::PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent)
	{
	//Get the name of the property that was changed  
	FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;

	// We test using GET_MEMBER_NAME_CHECKED so that if someone changes the property name  
	// in the future this will fail to compile and we can update it.  
	if (PropertyName == GET_MEMBER_NAME_CHECKED(AHexGrid, gridShape) ||
		PropertyName == GET_MEMBER_NAME_CHECKED(AHexGrid, maxQ) ||
		PropertyName == GET_MEMBER_NAME_CHECKED(AHexGrid, maxR))
		{
		HexGrid.Reset();
		InstancedFloorTile->ClearInstances();
		this->PositionTiles();
		}

	// Call the base class version  
	Super::PostEditChangeProperty(PropertyChangedEvent);
	}
#endif

Hey joessu-

Are you creating the InstancedStaticMesh as a component to an actor or are you referring to a new class based on the InstancedStaticMesh Component class? Can you post the code relating to the InstancedStaticMesh Component and how it is being implemented?

Cheers

The InstancedStaticMesh component is the child of an actor. I can post the code as soon as I get a chance.

updated question with code

Hey joessu-

I tried a simple setup to match what you have with an instanced static mesh component and a static mesh as follows:

static ConstructorHelpers::FObjectFinderTestMesh(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube'"));
    	MyStaticMesh = TestMesh.Object;
    
    	InstancedMesh = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("something"));
    	InstancedMesh->AttachTo(RootComponent);
    
    	InstancedMesh->SetStaticMesh(MyStaticMesh);

With both the UStaticMesh and UInstancedStaticMeshComponent set to VisibleAnywhere I did not actually see the actor that I added to the level. If I changed the UInstancedStaticMeshComponent to a UStaticMeshComponent (removed Instanced) then it became visible in the level. Can you confirm them in a new project or provide additional steps if I’m missing something in my setup?

Hey ,

Thanks for looking into this. Are you adding instances to the instanced static mesh? i didnt post the PositionTiles function but it calls InstancedFloorTile->AddInstance(FTransform(pos));

I have a blueprint based on the class above. Perhaps that is my issue?

Adding the AddInstance(FTransform()) call allowed the static mesh to show in the editor. When I then removed the VisibleAnywhere specifier the mesh was still visible in the viewport. When I closed and reopened the project the mesh was missing from the blueprint I created based on the class however it appeared again if I added an instance to the level or opened the blueprint for editing. Are you using instances of the class itself or do you have a blueprint based on the class that you’re using?

Hey joessu-

I tried to reproduce this again by copying the code that you posted. I copied lines 35 - 39 of your header to add to my own as well as 58 - 87 (inside your constructor). After creating a blueprint based on my class and adding an instance of the blueprint to the scene I added 2 elements to the Instance array in the details panel. In the code I then removed the VisiableAnywhere specifier and compiled. After the hot reload the mesh was still visible in my level. If possible please test this in a new project and let me know if you have the same result. If you do have a different outcome please list the steps you took that caused the mesh to disappear.

Hey joessu-

I will be marking this post as resolved for tracking purposes. If you are still having issues with instanced components not being visible feel free to add a comment to reopen the post and we will continue investigating.

Cheers

I stopped using visiableanywhere with them and after figuring out how AddInstance and RemoveInstance works, we have no issues anymore. (granted we are avoiding VisibleAnywhere)