C++ class instance as a variable on a blueprint

I’ve got a class which has the following structure:

UCLASS(Blueprintable, BlueprintType)
class MY_GAME_API UContainer : public UObject
{
    GENERATED_BODY()
    
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TArray<Item> items;

    UFUNCTION(BlueprintCallable)
    int32 GetTotalItemCount();

}

I’ve intended this class to be somewhat of a component object that can store a number of items in an Actor (or anything else really). But I’m running into a problem when I try to add this to one of my actors in blueprint:

Instead of my expected item list, I get a Default Value grouping and ‘None’ selected (and no alternate options to pick from). And when I try and interact with my Storage variable in blueprints, during runtime my Storage type is NONE, and nothing actually gets done inside the blueprint.

I’ve implemented the above function in C++, and I’m just trying to use this component inside my blueprints, but the variable just appears to be a type, and not an instance of my container object. I want this variable to be an instance of the container object, with my C++ implementation. Is this possible?

Currently you are creating a pointer for a UContainer object but have not created a UContainer Object to be pointed to. To fix this you need to add a method that constructs your UContainer object either During the game (Tick) or when the parent actor is created (beingplay). You cannot do this in blueprints natively. You have to do this in C++. You can create a method within your parent object that is accessable to blueprints but what I have done is create a Function Library that has the ability to construct UObjects.

Can you demonstrate your function library? The object which this is on isn’t inheriting from a c++ class, so I’m not sure I can effectively go that route.

What ArcainOne says is correct, but even doing this will not allow you to manipulate the properties of your object in the editor at design time, but only at runtime through blueprint nodes.

If you want to see your properties (item list) shown in the editor details panel, the only way to achieve this is to make your UContainer class derive from UActorComponent. This restricts you to using it only inside of actors, but then the support for editor manipulation is exposed - just add it as a component rather than as a variable.

Here you go, this is copied “almost” directly out of my code. Begin by Creating a BlueprintFunctionLibrary object from the editor (it’s one of the standard classes you can choose from)

Function Library Header

#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "ObjectBase.h"
#include "ToolsFunctionLibrary.generated.h"
/**
 * 
 */
UCLASS()
class YOURGAME_API UToolsFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:

	/** 
	* Construct a UObject in Blueprints.
	* @return Object
	*/
	UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Retrobox:Objects")
		static UObject * ConstructNewObject(TSubclassOf<UObject> objectType, UObject * outer = nullptr, FName name = NAME_None, UObject*Template = NULL, bool bCopyTransientsFromClassDefaults = false);

	/**
	* Return's true if the supplied object is null.
	* @return bool
	*/
	UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Retrobox:Objects")
		static bool IsObjectNull(UObject * object);
};

Function Library .cpp

#include "YourGameHeader.h"
#include "UToolsFunctionLibrary.h"




/**
* Construct a UObject in Blueprints.
*/
UObject * UToolsFunctionLibrary ::ConstructNewObject(TSubclassOf<UObject> objectType, UObject * outer, FName name, UObject*Template, bool bCopyTransientsFromClassDefaults)
{
	if (outer == nullptr)
	{
		outer = (UObject*)GetTransientPackage();
	}
	UObject * newObject = ConstructObject<UObject>(objectType, outer, name, EObjectFlags::RF_NoFlags, Template, bCopyTransientsFromClassDefaults, NULL);
	return newObject;
}

/**
* Return's true if the supplied object is null.
* @return bool
*/
bool UToolsFunctionLibrary::IsObjectNull(UObject * object)
{
	if (object == nullptr || object == NULL)
	{
		return true;
	}

	return false;
}

If you Blueprint it first, then you will be able to adjust the properties in the Editor Details panel. The method above will also construct blueprinted objects.

You could also build a Struct to define the properties in the editor first and use that to set the values of your UContainer. If this is an inventory system this is actually how I do it, but in combonation of what Kamrann said. For my inventory system I have built an “Initializer” component that configures the character with all it’s traits and Inventory Items. This allows a designer to configure the character in the editor and upon running in the game the initializer object constructs the characters traits and inventory then is destroyed all in the “Begin Play” function, that way the initializer object is not hanging around as vestigial data during game play.

True, but not on a per-instance basis - you won’t be able to modify properties of your container directly within the blueprint editor of the actor on which it is a variable, nor on the details panel of an actor in the level. For this you need components.

Blueprinting may be a viable and simpler solution, but it depends what the use case is. If you had 100 different characters each with its own UContainer which needed individually configuring, you’d need to create 100 different blueprint classes.

Struct solution for sure would work, but it’s an extra layer that shouldn’t really be needed. I’m hoping there will be more generalized support for subobjects (not just components) in the editor in future versions.

I’ve tried as you suggest, and changed my UContainer to extend UActorComponent (and changed nothing else). The new object now has a different icon, but is still exhibiting the same behavior (value is None, dropdown in the default values area).

I do hope that as well, but part of me doubts that will happen as there are other methods to do it (such as plugins), but I’ve been proven wrong before.

I will admit that doing the “Initializer Component With Structs” method does come with some extra coding, and absolutely would be nice if it was not needed. However there are a few cool things you can do with it. One is to use an initialization component and override the PostEditChangeProperty and PostEditChangeChainProperty. In the editor you can use these functions to do things to your actor in real time while in the editor such as construct your UContainers with the initialize properties you want from the structs. For instance my inventory component uses an Array of structures that contain the Class, stack count, identifier, friendly name, and effects that item applies when used. When I create a new item structure in the array all I do as a designer is give it a class name and an amount. Then the PostEditChangeChainProperty function is called, It creates an instance of the item in the background from the class specifier and the constructed item fills in all the blanks I did not input and I get all the details about it that I can now view in the editor. You can even control this by detecting if you are working with the Editor or during Game Play. There is a lot of “hidden” power within the edtor but it takes a lot of time to dig it out. If you are feeling VERY ambitious you can create plugins for the editor that would allow you to do all of this in the Editor with a Custom UI. But for the sake of “getting it done” I personally used the Initialize Component method (for now). It allows me to do what I want to do without changing my sub-object hierarchy and it still “feels” natural in the editor (at least to me).

You’ll need to add the UContainer as a component (AddComponent button in top left) rather than as a variable. For it to show up there, you may have to change your UCLASS line for your UContainer class as follows:

UCLASS(EditInlineNew, Meta = (BlueprintSpawnableComponent))

Yep, for sure it’s true UE4 gives a great amount of flexibility. Sometimes though I think it’s too much - there are too many different ways to achieve something, and there is next to no guidance on what is the intended way/best practice. People are going to end up with heaps of bad habits which will lead to issues down the line - you get something to work but by doing something that wasn’t what the devs expected people to do, so then a later engine change breaks it. UE4 is a bit of a monster though so to a degree this is inevitable.

Personally coming from a C++ background, the thing that constantly causes me confusion is the way UE4, with its blueprints and class default objects, blurs the distinction between a class and an object instance. The idea of making a blueprint class purely to modify some property values from the parent doesn’t sit well with me, it feels like making a new class to do something that should be the job of an object instance. This seems to be really common practice though.

I see and have also struggled with the issue of the “blured” line. Coming from UE3 there was the idea of an Archetype and you can still see references to it in UE4. Now it seems that Blueprints are a combination of Kismet, UScript, and Archetypes able to be utilized interchangeably. This defiantly feeds back to your first statement about having no real guidance to the “best practice”. I definatly agree that there is a lot of questions still about “best practices” but I have started to ask around Answer HUB and the Forums when I am faced with such questions.

For those of us who follow the OOP methodologies we want that division between a Blueprint and an Archetype. Something that represents a specialized subobject versus something that represents a preconfigured object. But I can also see the advantage of not having that distinction, as it is more streamlined from a designer’s point of view.