Blueprints: Deriving objects as classes for data and then using them in other blueprints

Coming from other game engines, Blueprints are a bit difficult to wrap my head around how to think about them.

In my game I’m going to be having many space stations scattered around. Each space station may have stats, a model, a name, etc. My question is, how do I define all of this inside of my game via blueprints?

I initially thought I could have a base Blueprint Object class for each station, then make a child of that blueprint object for each Type of station. (each type of station will have its own stats). Then I could have a base Station blueprint that I could construct objects off of via code. And then take that object and change its stats based on the respective blueprint object, but this is proving to be really cumbersome and difficult.

Not to mention when I also add in that I want each station itself to be its own actors. Such as a each space station model will have its own trigger sphere surrounding it. But when I went to create a Child Actor in the base station blueprint, then create a station object out of the actor class… it crashed haha.

Usually in another engine anyway, this is how I’d do it. But in this engine, I’m wondering if there is a better way to handle things like this.

TL;DR - What I want to do is

  • Have multiple space stations in the world
  • Multiple types of space stations
  • Each type of space station can be instanced into the world as its own space station (so a space station of Type 1 can be of Faction A, have its own ID and location, and a name. But there can be 2 or 3 Type 1 space stations owned by different factions (or the same faction) and called something different.

Thanks so much!

Hey Scarlet,

I just did something very similar (it’s not space stations but different tile types in a tilebased project) and I can feel the pain lol - took me a while to translate Blueprint to the OO languages I’m used to in my head.

When you create a blueprint, you can select what kind of blueprint it will be, one option is Actor. So I suggest your baseStation Blueprint should be of that type so you got something visible to spawn.

In your baseStation, you define all variables all stations have in common like Name, Model etc. then you can create more Blueprint Classes for each Station Type and let them inherit that BaseStation Class. You can then define specific variables in each of those derived classes.

Here’s an example of how I’m using my BaseClass to spawn specific Childs (you got to translate that to your SpaceStations but it should give a general idea):

The screenshot basically shows a Tile Factory, where I enter the (specific) TileType and the target X/Y coordinate in my grid.

Here’s another example, this is the initial world generation:

Basically, GetFittingTileForCoordinate checks if it is a coordinate at the edge of the map (or in the corners) and returns a straight or corner wall tile type or an empty floor tile otherwise. That type can then be passed into the spawn function.

And here’s an example output:

Note that each wall type (each corner, horizontal straight, vertical straight and empty floor) are different “child” tile classes and all of them are derived from my BaseTile class.

Hope this helps to get you on the right track.

1 Like

Hmmm okay I see now.

So you have different tiles that derive off of a base tile class. Then you have a tile factory that spawns them via code. Is it possible to spawn a derived actor without code? In case I’d like to build star systems via the UE editor?

Secondly, this works really good for the first part of the plan, but the second part requires instances of each separate type of space station.

So at this point I can create all the separate space stations. But now if I want to instantiate different space stations of Type A with new variables (such as Faction and specific Station name), how would I go about that? These variables wouldn’t be per station type, but they would rather be per instance of a station.

Like you can have a station owned by Faction A, but that same station type would be in a different location owned by Faction B?

I couldn’t just derive a new child from the Type A object, because this new “idea” has different variables.

What I thought was that I could have a separate StationInstance BP class, and a StationInstance factory could spawn various station instances.

But how can I take the Type A class and attach it to each instance of a StationInstance that gets created?

Thanks for the reply by the way! This really put things into perspective.

Yes, you just drag them into the viewport.

Then you call the factory with the same StationType twice (or multiple times, once for each instance). In my example above, I also only have one FloorTile child class but many more than one instance of it in the scene. If you want to do it without code, you drag your child class into the viewport more than once (each time you create a new instance).

My Factory creates one INSTANCE of the child class type every time it is called. The x,y I pass in just tells the tileMap where to place that instance in the world. You could easily just use a vector3 parameter and spawn it anywhere in your world, but my tileMap is 2D, so I just need x and y.

Hmm actually I see now. But I may have to alter this a bit.

Since Faction and Name, etc are not in each station variable, as they are not part of a station type but rather a station instance, I might create a StationObject class that just holds variables, and attach that to each instance of a station.

Therefore I can always access the information of each individual station.

Thanks! This is definitely putting me on the right path!

I think you have an incorrect understanding of the term instance. Take C#, C++ or Java for example. When you write the code for a class, you basically define a type. When you call the constructor of that class you create an instance of that type.

In Blueprint, it’s the same. You create your blueprint class and thus define a type. Now when you spawn that type anywhere in your world (or drag it into your viewport), you create an instance of it.

That being said and from what I understand about what you want to do:

Every station has a name, no matter what type of station it is and every station belongs to a faction, no matter what type of station it is. That means, those variables (name and faction) belong into your baseStation class.

Now, let’s say you have a station type MiningStation. And that station needs a variable which specifies how much minerals it mines per day. So that variable belongs in your MiningStation class, because some other station type (for example ResearchStation) doesn’t need a MineralsPerDay variable.

Now, when you create an instance of your MiningStation, that instance will have a Name, Faction and MineralsPerDay variable, because it inherits Name and Faction from the BaseStation class and gets the MineralsPerDay parameter from it’s derived implementation.

When you create a second station type ResearchStation, you might want variables like ResearchPerDay, ChanceForResearchAccident - so you define those in your ResearchStation child class.

When you create an instance of that ResearchStation type, that instance will now have Name and Faction (inherited from base class) and ResearchPerDay and ChanceForResearchAccident, but no MineralsPerDay - because that’s defined in a different child class.

1 Like

I’m doing similar things like this:

Base class actor holds common data and functions

child classes derived from the base class can be used for any instance of that class that needs special logic

Any data that is not going to change at runtime can be stored and read from a data table asset.

So, an example:
SpaceStationBase actor class has an instance editable string variable called “Type”
You use that string to lookup a data table row.
The data table row holds all information for whatever that type is.
Could be “enemy station large,” “allied station small”, etc.
The data table can hold variables about how long it takes to construct a station, what static mesh to use, etc.

If you have a type of space station that needs unique logic, you can make a child from the space station base class, then you can attach actor components to it for that special behavior.

You could also use the data table to determine what sort of components a station type might use and attach components on the actors BeginPlay event, thus eliminating the need for children classes. This could be a bit messy though so I’d probably separate things if there is going to be more than a few types with unique behavior sets.

If some other class needs to communicate with a station, have the Station base class implement a blueprint interface called something like, “space station BPI”. any children of that class are also going to implement that interface as well.

1 Like

Okay yeah that makes more sense. To be honest this is how I would handle it via code, but I guess when my brain thinks of blueprints it thinks of it differently. As I know exactly how to define all this in code, it didn’t exactly process via blueprints haha.

Thank you!

EDIT:

So I implemented it the way you have outlined and it took 5 seconds to create different derived stations of different shapes all with triggers and data, and deploy them into the world haha. Worked really well. Appreciate it!!

1 Like

Sounds great, congrats :slight_smile:

Blueprint IS OO, you’re creating derived classes from a baseclass.

If you have a Blueprint SpaceStationBase, which has a bunch of default parameters, then you have a SpaceStationType1 that is a child of that, with different parameters, and a SpaceStationType2 that is a child of SpaceStationBase, with different parameters …

then when you place or spawn one of those into the world, they will be SpaceStationBase with different settings.

Of course it is, I just mean it takes a while to grasp how to set up things like inheritance or interfaces in Blueprint, when all you know is .NET, C++, Java

1 Like

While it is OO, it just doesn’t come across as OO initially when you’re used to writing actual scripts. Once it clicked though, everything since then has been smooth sailing the same way I’d normally work in OO languages.

1 Like