C++ - Dynamically created components are disappearing

While in the editor, I add an element to the array created by C++ and connect the added element to RootComponent. Everything works fine, but when I close and reopen the engine, size of elements of the array is same, but I cannot see that element in Components window, it disappears. I am not sure if the problem is not being saved or loaded.

.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "SimulatorGame/SimulatorGameGameMode.h"
#include "BuildPreviewActor.generated.h"

USTRUCT(BlueprintType)
struct FBoxComponentInfo
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Components")
    UBoxComponent* BoxComponent;

    FBoxComponentInfo()
        : BoxComponent(nullptr)
    {}
};

UCLASS()
class SIMULATORGAME_API ABuildPreviewActor : public AActor
{
    GENERATED_BODY()
    
public:
    // Sets default values for this actor's properties
    ABuildPreviewActor();

    UPROPERTY(EditDefaultsOnly)
    UStaticMeshComponent* MeshAsset;

    UPROPERTY(EditDefaultsOnly)
    UMaterial* MeshMaterial;
    
    UPROPERTY(EditDefaultsOnly)
    UMaterial* PreviewCanBuildMaterial;

    UPROPERTY(EditDefaultsOnly)
    UMaterial* PreviewNotCanBuildMaterial;

    UPROPERTY()
    ASimulatorGameGameMode* SimulatorGameGameMode;

    UFUNCTION()
    TArray<FBoxComponentInfo> GetClothBoxes();

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
    TArray<FBoxComponentInfo> BoxComponents;

    virtual void OnConstruction(const FTransform& Transform) override;
    virtual void PostLoad() override;
    virtual void PostInitializeComponents() override;
    virtual void PostInitProperties() override;
    virtual void PostActorCreated() override;

    void CreateBoxComponents();
    void SaveChanges();
    void LoadChanges();
    void UpdateComponentRenderStates(); // Yeni fonksiyon

#if WITH_EDITOR
    virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
    
protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UPROPERTY()
    TArray<UBoxComponent*> ClothBoxes;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};
.cpp

.cpp

#include "BuildPreviewActor.h"
#include "Engine/Engine.h" // Log ve gerekli fonksiyonlar için

// Sets default values
ABuildPreviewActor::ABuildPreviewActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    
    MeshAsset = CreateDefaultSubobject<UStaticMeshComponent>("MeshAsset");
    SetRootComponent(MeshAsset);
}

void ABuildPreviewActor::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);
    UE_LOG(LogTemp, Warning, TEXT("OnConstruction called"));
    CreateBoxComponents(); // OnConstruction'da çağrıldı
}

void ABuildPreviewActor::PostLoad()
{
    Super::PostLoad();
    UE_LOG(LogTemp, Warning, TEXT("PostLoad called"));
    CreateBoxComponents(); // PostLoad'da çağrıldı
}

void ABuildPreviewActor::PostInitializeComponents()
{
    Super::PostInitializeComponents();
    UE_LOG(LogTemp, Warning, TEXT("PostInitializeComponents called"));
    CreateBoxComponents(); // PostInitializeComponents'da çağrıldı
}

void ABuildPreviewActor::PostInitProperties()
{
    Super::PostInitProperties();
    UE_LOG(LogTemp, Warning, TEXT("PostInitProperties called"));
    CreateBoxComponents(); // PostInitProperties'de çağrıldı
}

void ABuildPreviewActor::PostActorCreated()
{
    Super::PostActorCreated();
    UE_LOG(LogTemp, Warning, TEXT("PostActorCreated called"));
    CreateBoxComponents(); // PostActorCreated'de çağrıldı
}
 
void ABuildPreviewActor::CreateBoxComponents()
{
    UE_LOG(LogTemp, Warning, TEXT("CreateBoxComponents called"));
    // Yeni veya var olan komponentleri kontrol et ve oluştur
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (!Info.BoxComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("Creating new BoxComponent"));
            Info.BoxComponent = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass(), NAME_None, RF_Transactional);
            Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
            Info.BoxComponent->CreationMethod = EComponentCreationMethod::Instance;
            Info.BoxComponent->RegisterComponent();
        }
        else if (Info.BoxComponent->GetAttachParent() != RootComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("Attaching existing BoxComponent to RootComponent"));
            Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
        }
    }
    SaveChanges(); // Değişiklikleri kaydet
    UpdateComponentRenderStates(); // Bileşen render durumlarını güncelle
}

#if WITH_EDITOR
void ABuildPreviewActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    Super::PostEditChangeProperty(PropertyChangedEvent);

    FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;

    if (PropertyName == GET_MEMBER_NAME_CHECKED(ABuildPreviewActor, BoxComponents))
    {
        UE_LOG(LogTemp, Warning, TEXT("PostEditChangeProperty: BoxComponents property changed"));
        CreateBoxComponents(); // BoxComponents değiştiğinde yeniden oluşturuluyor
        SaveChanges(); // Değişiklikleri kaydet
        UpdateComponentRenderStates(); // Bileşen render durumlarını güncelle
    }
}
#endif
void ABuildPreviewActor::SaveChanges()
{
    UE_LOG(LogTemp, Warning, TEXT("SaveChanges called"));
    // Değişiklikleri kaydet
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (Info.BoxComponent)
        {
            Info.BoxComponent->Modify();
            UE_LOG(LogTemp, Warning, TEXT("Modified BoxComponent"));
        }
    }

    if (MarkPackageDirty())
    {
        UE_LOG(LogTemp, Warning, TEXT("Package marked dirty"));
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("Package not marked dirty"));
    }
}

void ABuildPreviewActor::LoadChanges()
{
    UE_LOG(LogTemp, Warning, TEXT("LoadChanges called"));
    // Yükleme işlemi
    // Burada gerekli yükleme işlemleri yapılabilir, örneğin bir SaveGame/LoadGame mekanizması kullanılabilir.
}

TArray<FBoxComponentInfo> ABuildPreviewActor::GetClothBoxes()
{
    return BoxComponents;
}

void ABuildPreviewActor::UpdateComponentRenderStates()
{
    UE_LOG(LogTemp, Warning, TEXT("UpdateComponentRenderStates called"));
    // Tüm bileşenlerin render durumlarını güncelle
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (Info.BoxComponent)
        {
            Info.BoxComponent->MarkRenderStateDirty();
            UE_LOG(LogTemp, Warning, TEXT("Marked render state dirty for BoxComponent"));
        }
    }
}

For looking to the problem;

[video] When editing the array
[video] After close and reopening the engine

You can also give me examples to look at instead of solving the problem :slight_smile:

try to open your project file (*.sln) , build it again maybe help

I tried. It didn’t work. A new update to the code is that it saves the location of the BoxComponent. but it doesn’t appear in the Components window and I can’t interact with it by clicking it.

Can you please try, I would like to know if it is a problem with my local dev environment or with the code.

.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "SimulatorGame/SimulatorGameGameMode.h"
#include "BuildPreviewActor.generated.h"

USTRUCT(BlueprintType)
struct FBoxComponentInfo
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Components")
    UBoxComponent* BoxComponent;

    FBoxComponentInfo()
        : BoxComponent(nullptr)
    {}
};

UCLASS()
class SIMULATORGAME_API ABuildPreviewActor : public AActor
{
    GENERATED_BODY()
    
public:
    // Sets default values for this actor's properties
    ABuildPreviewActor();

    UPROPERTY(EditDefaultsOnly)
    UStaticMeshComponent* MeshAsset;

    UPROPERTY(EditDefaultsOnly)
    UMaterial* MeshMaterial;
    
    UPROPERTY(EditDefaultsOnly)
    UMaterial* PreviewCanBuildMaterial;

    UPROPERTY(EditDefaultsOnly)
    UMaterial* PreviewNotCanBuildMaterial;

    UPROPERTY()
    ASimulatorGameGameMode* SimulatorGameGameMode;

    UFUNCTION()
    TArray<FBoxComponentInfo> GetClothBoxes();

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TArray<FBoxComponentInfo> BoxComponents;

    virtual void OnConstruction(const FTransform& Transform) override;
    virtual void PostLoad() override;
    virtual void PostInitializeComponents() override;
    virtual void PostInitProperties() override;
    virtual void PostActorCreated() override;

    void CreateBoxComponents();
    void SaveChanges();
    void LoadChanges();
    void UpdateComponentRenderStates();

#if WITH_EDITOR
    virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
    
protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    UPROPERTY()
    TArray<UBoxComponent*> ClothBoxes;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};

.cpp
#include "BuildPreviewActor.h"
#include "UnrealEdGlobals.h"
#include "Editor/UnrealEdEngine.h"
#include "Engine/Engine.h" // Log ve gerekli fonksiyonlar için
#include "Kismet/GameplayStatics.h" // UGameplayStatics için

// Sets default values
ABuildPreviewActor::ABuildPreviewActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    
    MeshAsset = CreateDefaultSubobject<UStaticMeshComponent>("MeshAsset");
    SetRootComponent(MeshAsset);

    LoadChanges(); // 1. Actor oluşturulduğunda değişiklikleri yükle
}

void ABuildPreviewActor::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);
    UE_LOG(LogTemp, Warning, TEXT("2. OnConstruction called"));
    CreateBoxComponents(); // 3. OnConstruction'da çağrıldı
    SaveChanges(); // 4. Değişiklikleri kaydet
}

void ABuildPreviewActor::PostLoad()
{
    Super::PostLoad();
    UE_LOG(LogTemp, Warning, TEXT("5. PostLoad called"));
    LoadChanges(); // 6. PostLoad'da çağrıldı
}

void ABuildPreviewActor::PostInitializeComponents()
{
    Super::PostInitializeComponents();
    UE_LOG(LogTemp, Warning, TEXT("7. PostInitializeComponents called"));
    CreateBoxComponents(); // 8. PostInitializeComponents'da çağrıldı
    SaveChanges(); // 9. Değişiklikleri kaydet
}

void ABuildPreviewActor::PostInitProperties()
{
    Super::PostInitProperties();
    UE_LOG(LogTemp, Warning, TEXT("10. PostInitProperties called"));
    CreateBoxComponents(); // 11. PostInitProperties'de çağrıldı
    SaveChanges(); // 12. Değişiklikleri kaydet
}

void ABuildPreviewActor::PostActorCreated()
{
    Super::PostActorCreated();
    UE_LOG(LogTemp, Warning, TEXT("13. PostActorCreated called"));
    CreateBoxComponents(); // 14. PostActorCreated'de çağrıldı
    SaveChanges(); // 15. Değişiklikleri kaydet
}

void ABuildPreviewActor::BeginPlay()
{
    Super::BeginPlay();
}

void ABuildPreviewActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

void ABuildPreviewActor::CreateBoxComponents()
{
    UE_LOG(LogTemp, Warning, TEXT("16. CreateBoxComponents called"));
    // Yeni veya var olan komponentleri kontrol et ve oluştur
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (!Info.BoxComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("17. Creating new BoxComponent"));
            Info.BoxComponent = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass(), NAME_None, RF_Transactional);
            Info.BoxComponent->CreationMethod = EComponentCreationMethod::Instance;
            Info.BoxComponent->SetHiddenInGame(false);
            Info.BoxComponent->RegisterComponent();
        }
        else if (Info.BoxComponent->GetAttachParent() != RootComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("18. Attaching existing BoxComponent to RootComponent"));
            Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
        }
    }
    UpdateComponentRenderStates(); // 19. Bileşen render durumlarını güncelle
}

void ABuildPreviewActor::SaveChanges()
{
    UE_LOG(LogTemp, Warning, TEXT("20. SaveChanges called"));
    // Değişiklikleri kaydet
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (Info.BoxComponent)
        {
            Info.BoxComponent->Modify();
            UE_LOG(LogTemp, Warning, TEXT("21. Modified BoxComponent"));

            if (MarkPackageDirty())
            {
                UE_LOG(LogTemp, Warning, TEXT("22. Package marked dirty"));
            }
            else
            {
                UE_LOG(LogTemp, Warning, TEXT("23. Package not marked dirty"));
            }
        }
    }
}

void ABuildPreviewActor::LoadChanges()
{
    UE_LOG(LogTemp, Warning, TEXT("24. LoadChanges called"));
    // Bileşenleri geri yükle
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (Info.BoxComponent && !Info.BoxComponent->IsRegistered())
        {
            Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
            Info.BoxComponent->RegisterComponent();
        }
    }
}

TArray<FBoxComponentInfo> ABuildPreviewActor::GetClothBoxes()
{
    return BoxComponents;
}

void ABuildPreviewActor::UpdateComponentRenderStates()
{
    UE_LOG(LogTemp, Warning, TEXT("25. UpdateComponentRenderStates called"));
    // Tüm bileşenlerin render durumlarını güncelle
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (Info.BoxComponent)
        {
            Info.BoxComponent->MarkRenderStateDirty();
            UE_LOG(LogTemp, Warning, TEXT("26. Marked render state dirty for BoxComponent"));
        }
    }
}

#if WITH_EDITOR
void ABuildPreviewActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
    Super::PostEditChangeProperty(PropertyChangedEvent);

    FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;

    if (PropertyName == GET_MEMBER_NAME_CHECKED(ABuildPreviewActor, BoxComponents))
    {
        UE_LOG(LogTemp, Warning, TEXT("27. PostEditChangeProperty: BoxComponents property changed"));
        CreateBoxComponents(); // 28. BoxComponents değiştiğinde yeniden oluşturuluyor
        SaveChanges(); // 29. Değişiklikleri kaydet
        UpdateComponentRenderStates(); // 30. Bileşen render durumlarını güncelle
    }
}
#endif
void ABuildPreviewActor::CreateBoxComponents()
{
    UE_LOG(LogTemp, Warning, TEXT("16. CreateBoxComponents called"));
    // Yeni veya var olan komponentleri kontrol et ve oluştur
    for (FBoxComponentInfo& Info : BoxComponents)
    {
        if (!Info.BoxComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("17. Creating new BoxComponent"));
            Info.BoxComponent = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass(), NAME_None, RF_Transactional);
            Info.BoxComponent->CreationMethod = EComponentCreationMethod::Instance;
            Info.BoxComponent->SetHiddenInGame(false);
            Info.BoxComponent->SetMobility(EComponentMobility::Movable);
            Info.BoxComponent->RegisterComponent();
        }
        else if (Info.BoxComponent->GetAttachParent() != RootComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("18. Attaching existing BoxComponent to RootComponent"));
            Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
        }
    }
    UpdateComponentRenderStates(); // 19. Bileşen render durumlarını güncelle
}

Two demo boxes

You can move the boxes after first compile after package is marked a dirty. Should probably just update the component in some way.

Though cleanup doesn’t seem to work after removing the boxes. They need to be deleted by hand as they are created with the new command.

Two instances in level after restart of editor

loaded
Boxes are intact and positions load.

1 Like

I’m sorry I don’t exactly understand what you are saying :frowning: , after using SetMobility function it still doesn’t work for me. When I close Unreal Engine and reopen, the BoxComponent disappears again.

Also, after adding BoxComponent, if I drag the actor to the scene, I cannot save the level, it gives following error;

Yes it’s till missing something about the update. I’m looking through engine source to see how epic does it in the engine.

1 Like

I edited the code a bit, now it saves the BoxComponent’s settings (location etc) in the Details window. But when I close and reopen the engine, I can’t see the BoxComponent in the Components window;
Video 1
Video 2

.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/BoxComponent.h"
#include "SimulatorGame/SimulatorGameGameMode.h"
#include "BuildPreviewActor.generated.h"

USTRUCT(BlueprintType)
struct FBoxComponentInfo
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Components")
	UBoxComponent* BoxComponent;

	FBoxComponentInfo()
		: BoxComponent(nullptr)
	{}
};

UCLASS()
class SIMULATORGAME_API ABuildPreviewActor : public AActor
{
	GENERATED_BODY()
	
public:
	// Sets default values for this actor's properties
	ABuildPreviewActor();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TArray<FBoxComponentInfo> BoxComponents;

	virtual void OnConstruction(const FTransform& Transform) override;

	void CreateBoxComponents();
	void SaveChanges();
	void LoadChanges();
	void UpdateComponentRenderStates();

#if WITH_EDITOR
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
	
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};

.cpp
#include "BuildPreviewActor.h"
#include "UnrealEdGlobals.h"
#include "Editor/UnrealEdEngine.h"
#include "Engine/Engine.h" // Log ve gerekli fonksiyonlar için
#include "Kismet/GameplayStatics.h" // UGameplayStatics için

// Sets default values
ABuildPreviewActor::ABuildPreviewActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	
	MeshAsset = CreateDefaultSubobject<UStaticMeshComponent>("MeshAsset");
	SetRootComponent(MeshAsset);

	LoadChanges(); // 1. Actor oluşturulduğunda değişiklikleri yükle
}

void ABuildPreviewActor::OnConstruction(const FTransform& Transform)	 
{
	Super::OnConstruction(Transform);
	UE_LOG(LogTemp, Warning, TEXT("2. OnConstruction called"));
	SaveChanges(); // 4. Değişiklikleri kaydet
	CreateBoxComponents(); // 3. OnConstruction'da çağrıldı
}

void ABuildPreviewActor::CreateBoxComponents()
{
	UE_LOG(LogTemp, Warning, TEXT("16. CreateBoxComponents called"));
	// Yeni veya var olan komponentleri kontrol et ve oluştur
	for (FBoxComponentInfo& Info : BoxComponents)
	{
		if (!Info.BoxComponent)
		{
			UE_LOG(LogTemp, Warning, TEXT("17. Creating new BoxComponent"));
			Info.BoxComponent = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass(), NAME_None, RF_Transactional);
			Info.BoxComponent->CreationMethod = EComponentCreationMethod::Instance;
			Info.BoxComponent->SetHiddenInGame(false);
			Info.BoxComponent->SetMobility(EComponentMobility::Movable);
			Info.BoxComponent->RegisterComponent();
		}
		else if (Info.BoxComponent->GetAttachParent() != RootComponent)
		{
			UE_LOG(LogTemp, Warning, TEXT("18. Attaching existing BoxComponent to RootComponent"));
			Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
		}
	}
	UpdateComponentRenderStates(); // 19. Bileşen render durumlarını güncelle
}

void ABuildPreviewActor::SaveChanges()
{
	UE_LOG(LogTemp, Warning, TEXT("20. SaveChanges called"));
	// Değişiklikleri kaydet
	for (FBoxComponentInfo& Info : BoxComponents)
	{
		if (Info.BoxComponent)
		{
			Info.BoxComponent->Modify();
			UE_LOG(LogTemp, Warning, TEXT("21. Modified BoxComponent"));

			if (MarkPackageDirty())
			{
				UE_LOG(LogTemp, Warning, TEXT("22. Package marked dirty"));
			}
			else
			{
				UE_LOG(LogTemp, Warning, TEXT("23. Package not marked dirty"));
			}
		}
	}
}

void ABuildPreviewActor::LoadChanges()
{
	UE_LOG(LogTemp, Warning, TEXT("24. LoadChanges called"));
	// Bileşenleri geri yükle
	for (FBoxComponentInfo& Info : BoxComponents)
	{
		if (Info.BoxComponent && !Info.BoxComponent->IsRegistered())
		{
			Info.BoxComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
			Info.BoxComponent->RegisterComponent();
		}
	}
}

void ABuildPreviewActor::UpdateComponentRenderStates()
{
	UE_LOG(LogTemp, Warning, TEXT("25. UpdateComponentRenderStates called"));
	// Tüm bileşenlerin render durumlarını güncelle
	for (FBoxComponentInfo& Info : BoxComponents)
	{
		if (Info.BoxComponent)
		{
			Info.BoxComponent->MarkRenderStateDirty();
			UE_LOG(LogTemp, Warning, TEXT("26. Marked render state dirty for BoxComponent"));
		}
	}
}

#if WITH_EDITOR
void ABuildPreviewActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;

	if (PropertyName == GET_MEMBER_NAME_CHECKED(ABuildPreviewActor, BoxComponents))
	{
		UE_LOG(LogTemp, Warning, TEXT("27. PostEditChangeProperty: BoxComponents property changed"));
		CreateBoxComponents(); // 28. BoxComponents değiştiğinde yeniden oluşturuluyor
		SaveChanges(); // 29. Değişiklikleri kaydet
		UpdateComponentRenderStates(); // 30. Bileşen render durumlarını güncelle
	}
}
#endif

void ABuildPreviewActor::BeginPlay()
{
	Super::BeginPlay();
}

void ABuildPreviewActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

I opened a new project and tried the code in it. now it works, BoxComponents do not disappear. But there is a new problem, I can’t save scene after placing the actor in scene. I get following error;

Video