Download

Sharing a single instance of a C++ class with multiple instances of a blueprint

I have been learning UE4 using a mix of C++ and blueprints. A pattern I enjoy is making a C++ base class where most of my logic will reside, and then inheriting from that class in a BP in order to use the visual editor to set property values.

I am trying to figure out how to achieve the following (forgive me if this is obvious and I missed it). In some cases, I would want all instances of an actor blueprint (ie. an instantiated actor in the level) to share a pointer to a single instance of a type. For example, suppose you had a city with thousands of cars. Each car has a given model (Prius, Accord, etc) with specs like speed, turning radius, and so on. To represent this in code you might do something like:



UCLASS()
class Car : public AActor {
 ...
 UPROPERTY()
 CarDefinition * Specification;
...
};


Where CarDefinition describes immutable specifications of a given car model. These are conceptually shared amongst all instances of that particular model, and so (at least in principle) it seems logical to share a single instance of that definition with all actors that are of that car model. (In normal non-unreal C++ you’d probably make CarDefinition const-reference to reflect that it represents immutable properties). CarDefinition itself (from my naive understanding) would probably inherit from UObject and have blueprint children for ease of editing.

However, from the editor, would it be possible to somehow indicate that only one CarDefinition should be instantiated for all actors that share that definition? Obviously if the definition is small, putting it in a simple struct and copying it into every Car would probably be fine. That said, the pattern of sharing an instance feels generally useful in some cases and I would like to understand if it is possible to do this.

If this were plain C++ I would simply allocate one global instance somewhere and share it. But what I can’t yet wrap my head around is how you would achieve this in a way that allows the definition to be a UPROPERTY that can be set from the editor when inheriting a blueprint.

Thanks for any insight.

From my understanding you want to have multiple child blueprints based off a single c++ parent class, like BP_Car1 BP_Car2 ect based off ACarBase. You also want to be able to have exposed text variables for descriptions and whatnot (you can have int/float values for gears/speed also, there are no limitations).

I’ll go through my process from scratch, modify appropriately :slight_smile:

First if you make the CPP class an Actor, name it however you want and wait for it to compile. (CarBase for this example)

In the header file I would do this



public:

UFUNCTION(BlueprintPure) // for access in blueprint with no trigger
FString GetCarDescription(); // retrieve value of private member variable.

UFUNCTION(BlueprintCallable) // for access in blueprint with trigger to call this event at specific times.
void SetCarDescription(FString Value); // set value of private member variable.

private:

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "CarInfo", meta = (AllowPrivateAccess = "true") // Allows default data to be altered, blueprint cannot alter but can read value, catagorise this variable for easy reading, allow private access for the editor.
FString CarDescription = TEXT("Default Text");



Then in the cpp I would do this to make sure you can access the private variable.



FString ACarBase::GetCarDescription()
{
return CarDecription;
}

void ACarBase::SetCarDescription(FString Value)
{
CarDescription = Value;
}


After that is implemented and compiled I would then create a blueprint based on ACarBase (either by right clicking the code file in the editor and selecting that option or by creating a new blueprint class and selecting the custom class after selecting the view all classes check box) I would name it BP_CarBase.

I would then set up any default values (like meshes, but in this example a default description to let you know that you need to modify the values in the children) in the CarBase blueprint, once that is done create children from that blueprint and set them as required. You can now have BP_Car1 with Description = “Car1”, BP_Car2 with description = “Car2” and so on. If you need more variables of different types you would just add them in both the code files as above.

I hope this helps!

I think you are overcomplicating this for no good reason really. Shouldn’t every car have its own specification? What’s the point of making a global spec and then giving a pointer to it for each car? On a side note, check out Subsystems.