What are the best alternatives to using actor blueprints for storing function implementations?

Hi, I have some functionality that I do not want to add as part of default classes like the controller or game mode. At the moment, it’s added as a set of functions inside an actor blueprint that is spawned at level start. I’m not using any tick based or begin play events for this actor. It’s just a container that I use to call all functions related to a particular functionality, since I don’t want to bulk up the default classes.

However, there is no need for these classes to exist as an actor in the level. So I’ve been thinking of putting these functions in non actor classes like what we have in traditional programming. But all I can find in that regard are the Blueprint function libraries and macro libraries. I would like to know the advantages/disadvantages of using either of these libraries when compared to an actor blueprint. If there are any other alternatives, I would like to discuss about that as well.

Hey Storm

Are there too many, or could you use level BP?

Hi,

At the moment, I’m using two actors, each containing around 4 functions to deal with two separate gameplay features. But as more features are added, I would end up having more actors if I go down this path. It keeps everything modular and makes sure that the default classes don’t get overwhelmingly big.

Level Blueprint is out of the question for me, since I’m using these actors in every level. With the current setup, I just add the actors to a new level and just start playing.

The function libraries seem like a good way to approach this, but having not used them before, I’m not sure if they’ll ultimately make any difference in the end. So if there’s a standard approach that is generally used for this, I would like to try it out.

it depends what you mean by gameplay features. are they data types like structs or arrays that need some kind of special manipulation? if so, a blueprint function library would work well. without a specific understanding of your needs, i can only give generic advice, but this is how i generally make that decision:

actors are good if you need to keep track of an internal state of some kind. especially if it needs to contain components or receive input or update constantly or detect collision.

macros are good for functions that choose to branch into several execution pins. if you want to control the flow of execution in some generic reusable way, macros are the way to go.

functions return a single execution pin, so they are usually a single action in a linear sequence. these are good for math stuff, like sorting a list or calculating a result. any you have a custom struct data type that needs helper functions to handle custom operations, it should be in a blueprint function library. for example, if you created a custom struct for holding item stats, and wanted a function to calculate how much the item was worth based on its stats, it should be in a function library. you could combine the item stats struct and helper functions into a single actor, but that takes up more memory when stored in an inventory.

so you could try to decide if its an that edits itself, a function that edits some input parameter, a function that edits some it has a reference to, or a macro that makes a decision to change the flow of execution.

if its an operation that edits the state of some unique foreign , it might be a good idea to let that foreign be an actor that owns the operation as a member function. if you ever need to have a lot of those actors in memory at once, or owned by other actors, it might be a good idea to split its data and functionality into a struct and a set of blueprint function library functions.

Hi, Stormrage!
If you wish to store some data in class instance but you’re not interested in Actor functionality, you can go two ways:

  1. Create just a blank C++ class with all functions and data you need to store and use, make #include yourclassname.h in where you want to use it and then just initiate an instance of your container.

-or-
2)Depends on what functionality you wish to realise, it is also profitable to create a container clas as USceneComponent-inheriting and attach it to existing Actor. This way suitable both for only Actor in the scene that need to have this container, and for the case where you need separated container for every single specific Actor.

Thanks for the detailed answer @Omnicypher . I’m using Monokkel’s Advanced Turn based Tile Toolkit system. One of the actors that I use has functions that deal with finding the grid tiles that are visible by the player team units. It has no functionality other than to just sit there and wait for function calls from the Grid manager. And yes it deals mainly with constructing and editing arrays. So based on what you said, it would be better to put it either in player controller or a function library, right?

Hi Xander, thanks for the C++ approach. I’ll keep it in mind for later stages. Currently the project is in the prototype stage and if it’s possible to do it solely in blueprints, I would prefer that instead of compiling C++ code alongside.

since the grid manager holds the state of the grid, and your function uses that state to return a subset of that state, and the function gets called by the grid manager every , i would put that functionality inside the grid manager as a member function.

if many different objects had lists of grid tiles, and you wanted to perform an operation on a generic set of grid tiles, i would put it in a blueprint function library. but in your case, it seems like the only that has a set of grid tiles is a single tile manager, so operations on those tiles don’t need to work for a generic set of tiles, they can be specific to the grid manager, so it makes sense for those operations to be member functions, rather than blueprint function library functions.

later on, you may decide to have multiple sets of grids, owned by separate grid managers, and if you wanted to perform a function on all of those, you may want to put it in a blueprint function library function that is passed a constant reference to an array of grid tiles as a parameter, or make it a member function of a GridManagerManager, which would own all of the grid managers.

Thanks a lot man. Yea that makes sense.