Transfering custom asset's editor-time UObjects into a standalone game

I do have a custom asset type with it’s custom editor. Editor has some UEdGraphNodes filled with needed at runtime data and in order to use that data I copy all node content into a chain of UObjects which are spawned when graph is saved.

Here’s the header of custom asset.


UCLASS(Blueprintable)
class TestGame_API UCustomAsset : public UObject
{
GENERATED_BODY()
public:

UPROPERTY(BlueprintReadWrite)
class UCustomNodeBaseRuntime* StartNode;

#if WITH_EDITORONLY_DATA
UPROPERTY()
UEdGraph* CustomEditorGraph;
#endif //WITH_EDITORONLY_DATA

};

When graph is compiled or saved FCustomEditor runs InitRuntimeTree() which simply does NewObject() and spawns all UObjects that would store UEdGraphNode data.
As the result I have a chain of UObjects placed inside of custom asset, they comfortably exist at editor-time. These UObjects are respawned automatically when editor restarts without need to run InitRuntimeTree() over and over again, looks like reference system stores UObject data somehow and turn objects back to life on editor start (by the way, are there any resources I could read about how exactly restoration happens?)

As supposed - that UObjects could easily be used at PIE and such, but running Standalone game wipes these objects.

Here’s the question:
How can I transfer these UObjects so they would exist in Standalone mode? Is there any mechanism to store UObject data somehow (hopefully without use of external files) and than recreate it at Standalone runtime?

I’ve made a debug session and looks like ProcessNewlyLoadedUObjects() is responsible for spawning UObjects stored inside of module.
But why does it only spawn necessary UObjects in editor and doesn’t do that at standalone run?

If you show the code that creates these objects I may be able to help you. You mention a chain, but your asset only references a single object so I’m wondering how the rest are referenced.

When I was posting object-constructing code right here I’ve carefully re-read it and found the issue.
Previously I’ve referred to UBehaviorTreeDecoratorGraphNode_Decorator::PostPlacedNewNode() when were making my own nodes.


            UBehaviorTree* BT = Cast<UBehaviorTree>(OwningNode->GetOuter()->GetOuter());
            if (BT)
            {
                UBTDecorator* MyDecorator = NewObject<UBTDecorator>(BT, NodeClass);
            }

when were making new objects, but I guess that’s not something that should work at runtime and indeed outer is not correct if working with runtime.

So I’ve figured out my runtime objects also referred some editor-only outer. I’ve changed outer of runtime nodes to CustomAssetInstance and everything seems to work right now.

Thanks for always being ready to help, **kamrann **:slight_smile:

Yep, that makes sense.

I’d suggest also marking your StartNode property with the Instanced specifier (inside the UPROPERTY macro). You generally want to use this on any UObject-type properties where the containing class ‘owns’ the object pointed to. Without it, its considered a non-owning reference, which can lead to some weird behaviour when you start doing things like duplicating objects, and the copy ends up with a reference back to the original instance, instead of to a new deep-copied instance.

Thanks for the tip, looks like something where I could optimize and rewrite some logic since right now whole chain of UObjects is rebuilt anytime graph is being saved.
I might get rid of rebuilding over and over when copy-pasting nodes.