Hello,
I’m currently stuck for some days and I can’t figure it out by myself.
I am working on a project who create ready to use actors based on a XML description. This XML describe the geometry of the actor. Based on it I can create dynamically the USceneComponent tree of my actor. It works well, the generated actor is well constructed and rendered. I can add it to my world and use it correctly.
The problems are:
- I can’t save a level with an actor inside. I got this error :
Can't save C:/.../MyProject/Content/Main.umap: Graph is linked to external private object StaticMeshComponent /Game/MyAssetFolder/A_MyActor.Default__A_MyActor_C:SM_Base (InstanceComponents)
whereSM_Base
is the name of my StaticMeshComponent.
In the log I have a lot of warnings from the LogSavePackage module who list all the Referencers but this is not very understandable because the names don’t matches every time to something I know. - I can save my actor on my content browser but after a reboot of Unreal all the Component tree just disapear.
I think the boths problems are only one but I didn’t found anything who could help me to solve this.
I use a sub object to generate the Component tree because there is already a lot of mess in my actor.
For reference some extracts of the objects :
MyActor.h
UCLASS(BlueprintType, Blueprintable)
class MYPLUGIN_API AMyActor : public AActor {
GENERATED_BODY()
public:
AMyActor();
void BeginPlay();
void EndPlay(const EEndPlayReason::Type EndPlayReason);
void Tick(float DeltaTime);
UXMLDescription* XMLDescription; // Custom object who contain XML already parsed to properties
FActorGeometryTree GeometryTree;
// Method called during BP creation to set the Component tree
void SetXMLDescription(UXMLDescription* ActorXMLDescription);
};
MyActor.cpp
AMyActor::AMyActor() {
PrimaryActorTick.bCanEverTick = true;
this->SetRootComponent(CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent")));
}
void AMyActor::SetXMLDescription(UXMLDescription* ActorXMLDescription) {
this->GDTFDescription = FixtureGDTFDescription;
// Construction of the Geometries tree
this->GeometryTree = FActorGeometryTree(ActorXMLDescription, this);
<...> // Other stuff but not related with this problem
}
FActorGeometryTree.h
/**
* Manage the Scene components tree of our Actor
*/
class FActorGeometryTree {
private:
AMyActor* ParentActor;
UXMLDescription* XMLDescription;
public:
// Equals to "SM_"
static constexpr const TCHAR* PREFIX_STATIC_MESH = TEXT("SM_");
FActorGeometryTree() {};
/**
* Map to simplify access to Components at Runtime
*/
TMap<FName, USceneComponent*> Components;
/**
* Creates the object, all the SceneComponent tree and attach them to the Actor
*/
FActorGeometryTree(UXMLDescription* XMLDescription, AActor* Actor);
private:
/**
* Creates a branch of the tree (the given geometry and all his childrens)
* RECURSIVE METHOD
*/
USceneComponent* CreateTreeBranch(USceneComponent* Parent, UXMLDescription* Geometry);
/**
* Creates a StaticMeshComponent and attach it to the parent.
*/
bool CreateStaticMeshComponentChild(USceneComponent* Parent, UXMLDescription* Geometry);
/**
* Creates a USceneComponent and attach it to the parent.
*/
USceneComponent* CreateAndAttachSceneComponent(USceneComponent* Parent, FName Name);
};
FActorGeometryTree.cpp
/**
* Creates the object, all the SceneComponent tree and attach them to the Actor
*/
FActorGeometryTree::FActorGeometryTree(UXMLDescription* XMLDescription, AActor* Actor) {
this->ParentActor = Actor;
this->XMLDescription = XMLDescription;
// We create the tree recursively
USceneComponent* TreeBranch = this->CreateTreeBranch(this->ParentActor->GetRootComponent(), XMLDescription);
TreeBranch->AttachToComponent(this->ParentActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
}
/**
* Creates a branch of the tree (the given geometry and all his childrens)
* RECURSIVE METHOD
*/
USceneComponent* CreateTreeBranch(USceneComponent* Parent, UXMLDescription* Geometry); {
// Creation of the container component
USceneComponent* CurrentComponent = this->CreateAndAttachSceneComponent(Parent, Geometry->Name);
this->Components.Add(Geometry->Name, CurrentComponent); // Registering of the component in the Map
CurrentComponent->SetRelativeLocationAndRotation(Geometry->Position, Geometry->Rotation);
// Creation of the sub geometries
for (UXMLDescription* ChildGeometry : Geometry->Childrens) {
USceneComponent* ChildComponent = this->CreateTreeBranch(CurrentComponent, ChildGeometry);
this->Components.Add(ChildGeometry->Name, ChildComponent);
}
// Creation of StaticMesh
if (Geometry->Type == EGeometryType::Mesh) { // If this geometry describe a mesh we create the StaticMeshComponent
CreateStaticMeshComponentChild(CurrentComponent, Geometry);
}
return CurrentComponent;
}
/**
* Creates a StaticMeshComponent and attach it to the parent.
*/
void FActorGeometryTree::CreateStaticMeshComponentChild(USceneComponent* Parent, UXMLDescription* Geometry) {
UStaticMesh* StaticMesh = nullptr;
<...> // We load the good mesh. Not related to this problem.
// We create the UStaticMeshComponent and attach it to his parent
FName Name = FName(FActorGeometryTree::PREFIX_STATIC_MESH + Geometry->Name.ToString());
UStaticMeshComponent* Component = NewObject<UStaticMeshComponent>(this->ParentActor, UStaticMeshComponent::StaticClass(), Name);
Component->AttachToComponent(Parent, FAttachmentTransformRules::KeepRelativeTransform);
this->ParentActor->AddInstanceComponent(Component);
Component->SetStaticMesh(StaticMesh);
// Step 5: We save it here for future use
this->ParentActor->Components.Add(Name, Component);
}
/**
* Creates a USceneComponent and attach it to the parent.
*/
USceneComponent* FActorGeometryTree::CreateAndAttachSceneComponent(USceneComponent* Parent, FName Name) {
USceneComponent* NewComponent = NewObject<USceneComponent>(this->ParentActor, USceneComponent::StaticClass(), Name);
if (Parent != nullptr) NewComponent->AttachToComponent(Parent, FAttachmentTransformRules::KeepRelativeTransform);
this->ParentActor->AddInstanceComponent(NewComponent);
return NewComponent;
}
I don’t have any idea of where my probem could be. Everything related to component is public so I don’t really understand the Unreal error.