Can't save Blueprint when component is stored in array. Graph is linked to private object(s) in an external package

I have a custom AActor class AStreet that creates an instance of a custom USceneComponent class UPath in its constructor (it also creates instances at runtime, but that doesn’t seem to cause any errors).

AStreet::AStreet(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
	// If Path is added here, blueprint object cannot be saved anymore.
	AddPath();
}

The function creating the instance of Path in AStreet also stores a reference to the Path object in a TArray. This ‘add to the array’ causes the following error message when I try to save the blueprint based on class AStreet:

Can’t save
…/…/…/…/…/…/Users/IgorIII/Documents/Unreal
Projects/GraphLinkError/Content/BP_Street.uasset:
Graph is linked to private object(s)
in an external package. External
Object(s): Path

If I don’t add the Path object to the array, the error doesn’t show.

bool AStreet::AddPath()
{
    // Either of the two versions produce the same result
	//UPath* path = ConstructObject<UPath>(UPath::StaticClass(), this, TEXT("Path"));
	UPath* path = NewNamedObject<UPath>(this, TEXT("Path"));

    // If the path is not added to the array, the Street Blueprint can be saved
	Paths.Add(path);
	path->AttachParent = RootComponent;
	return true;
}

I’m not sure if this is a bug, or if it’s just a basic misunderstanding of how object instantiation, object references and garbage collection works (I suspect the graph link error is caused by a reference in Paths not being found anymore).

If I use AddPath() at runtime (not in the AStreet constructor, but for example in BeginPlay), everything works fine.
If I create the UPath object via FObjectInitializer (from the constructor), I can save the blueprint, but I get a whole bunch of crashes once I try to place an object based on this blueprint in the world.

How do I properly add a component at runtime? How do I properly add a component in the constructor? Why can’t I store a reference to the sub-component in an array?

Here’s an example project that’s reduced to the components that cause the error.
You’ll need to:

  1. Re-generate the Visual Studio Project files.
  2. Compile.
  3. Once the editor has started, create a Blueprint based on Class ‘Street’.
  4. Try to save the project.

Hey TaurusI76-

In the second code snippet you posted, if you change line 5 to “CreateDefaultSubobject…” then you won’t get the error while saving.

Cheers

Thank you for the suggestion. It helps getting rid of the error in the sample project I provided.
However, if I execute AddPath() twice in the Street constructor (i.e. create two UPath subcomponents), I get an error in SSCSEditor.cpp

ensure(!InSceneComponent->HasAnyFlags(RF_PendingKill));

when I try to add a Blueprint instance of the Street Blueprint to the scene.
Why can’t I add multiple subcomponents to an actor?
I fear that there’s a fundamental concept to object instantiation I’m not getting, but I haven’t found any comprehensive documentation on that matter (just code snippets here and there).

Hey TaurusI76-

When you make the call twice it is essentially trying to recreate the same component twice which is causing the problem. I’m not sure what you’re creating the component for, but it may be a better option to do so directly inside the constructor.

Hi
Thanks for the hint! I just recently realized that if you create a component with the same FName it doesn’t create a new component. (Is that correct? I’m still have to learn a lot about the Engine…)

What I’m trying to achieve is the following:
I want a AStreet actor that the player can modify in-game. The AStreet actor can have multiple lanes and the player can add/remove lanes. That’s why I need to add the components dynamically (in-game as well as in the editor).

That’s why I can’t add the lanes (paths) in constructor, because I don’t know how many there will be. If there’s 0 lanes (like there will be if you create a new AStreet object), I want to add two default lanes. That’s why I want to add a path twice in the constructor. Additionally, I want to have an array with all the paths so I can access them quickly.

It currently kinda works (I’m creating the path components with a number in the FName and don’t add them to an array), but I’m getting an error because I’m trying to add an instanced component (path component) to a templated component (root component of AStreet). I feel that there’s a fundamental concept about templated Instances/instances, DefaultSubobjects/EditorOnlyDefaultSubobjects that I don’t get. Maybe you can help me out here?

Hey TaurusI76-

Your recent question about templated instances deviates from the original issue of the blueprint not being able to save. Could you create a new post for this question in order to track each topic separately? Doing so will help others in the future who search for either issue find the relevant information quickly and easily.