Skip to content

Instanced Objects 2.7+

Using instanced objects within custom node classes is possible but only has limited support in the details panel. Exposing these properties on the graph node is not supported.

The standard EditInlineNew approach is not supported. Instead you must create the instanced object manually and make sure the outer is the node instance template. The instanced object UPROPERTY should be marked Instanced.

Example Code

UCLASS(Abstract)
class UInstancedObjectBase : public UObject
{
    GENERATED_BODY()
};

UCLASS()
class UInstancedObject : public UInstancedObjectBase
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, Category=Default)
    FString TestVar;
};

UCLASS()
class USMCustomStateInstance : public USMStateInstance
{
    GENERATED_BODY()

public:
#if WITH_EDITOR
    virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override
    {
       Super::PostEditChangeProperty(PropertyChangedEvent);

       if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(USMCustomStateInstance, InstancedObjectClass))
       {
          Modify();

          // Remove existing instanced object
          if (InstancedObject && InstancedObject->GetClass() != InstancedObjectClass)
          {
             const ERenameFlags RenFlags = REN_DontCreateRedirectors | REN_ForceNoResetLoaders | REN_DoNotDirty;
             FName TrashName = *("TRASH_" + InstancedObject->GetName());

             InstancedObject->Modify();
             TrashName = MakeUniqueObjectName(GetTransientPackage(), InstancedObject->GetClass(), TrashName);
             InstancedObject->Rename(*TrashName.ToString(), GetTransientPackage(), RenFlags);
             InstancedObject = nullptr;
          }

          // Create new instanced object with this node instance as the outer
          if (!InstancedObject && IsValid(InstancedObjectClass))
          {
             InstancedObject = NewObject<UInstancedObjectBase>(this, InstancedObjectClass);
          }
       }
    }
#endif

private:
    UPROPERTY(EditDefaultsOnly, Category=Default)
    TSubclassOf<UInstancedObjectBase> InstancedObjectClass;

    UPROPERTY(VisibleDefaultsOnly, Category=Default, Instanced)
    TObjectPtr<UInstancedObjectBase> InstancedObject;
};

In this example there is an editable class type InstancedObjectClass property which the user can change in the editor. Then the InstancedObject is created through PostEditChangeProperty. Once created the object's properties will be available to edit in the details panel, even though the object is marked VisibleDefaultsOnly.

Requirements

  • This is only supported on Logic Driver Pro 2.7+.
  • You should only be doing this if you have experience with creating instanced sub-objects in the editor.
  • Your method needs to be tested, both with general editor use and in packaged builds.
  • Instanced maps and sets are not supported in packaged builds.

Complications

EditInlineNew does not work and most likely won't ever work without engine level changes. It makes some assumptions about how the object should be created which does not work in Logic Driver assets. When you use a custom node class it is technically an archetype sub-object of the USMInstance blueprint generated class. This adds a layer of complication not normally found in blueprints.

There are also packaging issues which can arise even when using the supported Instanced approach. For some reason, when compiling for packaging UE will add a transient flag to these subobjects which will prevent them from serializing to disk. This is likely an engine bug. In Logic Driver Pro 2.7 it will check for this case and remove the transient flag during packaging, but only if it can find a matching UPROPERTY to verify it isn't actually marked transient. It will check arrays, but not maps or sets. Therefor maps and sets will have the transient flag added in packaged builds, regardless if you intended them to be transient or not, and will not save.

UE 5.3 and 5.4 may improve sub-object packaging, but still need to be tested. Due to all of these complications, it is recommended to avoid using instanced sub-objects unless you know exactly what you are doing and can thoroughly test they work properly for your project and your engine version.