Global variables: how to get something similar with blueprints? Example provided

Okay, now I realize global variables aren’t really a concept in blueprint scripting, so I need help understanding how to make my blueprints interact in a way that will make this possible.

I have multiple random spawning actors in my level, and when the player clicks one, it becomes selected (signified by change of color). I want this to add 1 to a variable which will count how many actors are currently selected. I also have a button that destroys all selected actors, which when destroyed, should reset the ‘selected’ variable to 0.

I also want to be able to reference this variable in a UMG hud that will display the variable as text. (Not sure how to do this either.)

I’m having a hard time wrapping my head around this and have been researching options for over two hours now with no results. Any ideas? Your help is much appreciated.

Off the top of my head, I’d put the variable in your GameMode Blueprint; which you could read from in UMG. Then you could either use a Blueprint Interface to communicate with the GameMode, or you could use an Event Dispatcher to setup a series of custom events, that would be called whenever an actor is “selected.”; or even a combination of the two.

Blueprint is best used in an event driven way, as opposed to having global state that everything reads from; so you’ll want to have custom events fire off to set everything to their individual states when something happens, instead of having everything be polling a variable every frame.

I’d recommend going through the UMG Inventory Tutorial series, as it covers how to use UMG and has a good example of using an Event Dispatcher: UI Inventory Tutorial (pre. v4.7) - YouTube

You can put the variable into a Save Game object and read from it.

That would technically work, but my concern with that would be that’s a lot of reading and writing to disk, which is really slow compared to just reading and writing to variables that are stored In RAM.

**Global variables database, accessible throughout your entire level! **

In this case, an extensive read/write to file is not time efficient. And for most questions on this matter, everyone directs you to direct blueprint communication, and it almost never works. The problem with blueprint communication is that it’s hard (especially for non-advanced users) to use/get the right object or reference or class variable, or not miss a single detail of the setup, which are so many. Even when you do set it up correctly, some variables just won’t go through, depending on context. Then you must also define in every class, widget, or blueprint, an instance of the other object that contains your variables. So just DON’T use the Direct Blueprint Communication. It should be used only for its purpose, which is to allow an actor to affect another actor, such as turning on a light. It should not be used to handle your database.

SOLUTION DATABASE:

From any Event Graph or Function, whether from your Level Blueprint, an actor or a widget, you can use the blueprint node “All Actors of Class”, and drag out of it an array of all actors from the specified class that exists in your level. Here follows a step by step setup of your local database:

  • Create a new blueprint ACTOR, because you are going to put in in your level, and it has to be an actor. Call it “LevelDatabaseActor”
  • Place your new LevelDatabaseActor in your level (I put it at origin 0,0,0).
  • Add/edit the blueprint of your LDA
  • In the Event Graph, create all the variables you wish, and make them visible.
  • Compile and save.
  • Open any other actor, widget, or blueprint, anywhere with an event graph.
  • on any event (BeginPlay?) connect the node “All Actors of Class” and select your “LevelDatabaseActor”.
  • From the array output drag a “Get” array item, and leave it to 0.
  • From the Get 0, you have access to set or get any variable in your LevelDatabaseActor, from anywhere.

Test your database:

  • In your LevelDatabaseActor, create a String variable called “TestVariable”, make it visible, and set the default value to “This will print if I did it correctly.”.
  • In your other actor/widget/blueprint/eventgraph, Get All Actors from Class, Get array element 0, get variable “TestVariable”, connected to the Print node.
  • Compile and run your level.
  • Enjoy some coffee and cookies. You have a new database in blueprint only.

Get 0 vs ForEachLoop:

The ForEachLoop code uses a bit more CPU ressources than a direct call to an item in your array. By habit, most blueprint coders use a ForEachLoop after an “All Actors of Class” because there usually are many instances of that actor calss in your level. Since you are absolutely confident that there is only a single instance of your LocalDatabaseActor class in your entire level, the “All Actors of Class” is certain to return an array containing only one item, in the index 0. For that reason, we are saving a very small amount of CPU by refering directly to the item we want, rather than calling a ForEachLoop structure.

Use the ForEachLoop only when there is a possibility to have more than one instance of a class in your level. When you are certain to have only 1, use the Get arrya item 0. Every micro-cycle of your CPU saved, here and there, is a tad more visual effects your user’s computer or mobile will be able to handle.

Passing your database through levels

To keep your database alive from one level to another, learn to save and load files using the SaveGame blueprint (many tutorials exist). I will hereby take from granted that you know how to use a SaveGame blueprints class.

  • Put a single instance of your LocalDatabaseActor in every level.
  • Create a SaveGame blueprint called “TransistionFileSG”, containing the same variables as your LocalDatabaseActor.
  • Create 2 functions in your LocalDatabaseActor:
    - One to save every variable of you LocalDatabaseActor in a transition file (I personally call this file “transitionFile”).
    - One to load every variable from your transition file back into your LocalDatabaseActor.
    - In both functions you have to get/set each variable separately.
  • On the verge of exiting a level, call the function to save all your variables in your transition file.
  • On entering your new level, call the function to load back all variables.

You passed all your variables from one level to another. More cookies and coffee, or whatever you use to celebrate which won’t prevent you to pursue coding your game.

Hint: In your LocalDatabaseActor and TransitionFileSG, add a few variables that will help you handle your project. Try to plan your debuging needs a head. Add string variables like DataTimeOfFile, GameName, CharacterPlayerName, CharacterSGFileName. You could add a boolean LoadMe that is verified before you load all your stats. When changing a level, set LoadMe to true before calling your save function. On game quit, save your transitionFile with LoadMe set to false. You will know in your load fuction if your transitionFile is outdated from a previous quit game, or fresh from an actual level transition.

I really hope that helps you guys. If my Unreal Engine was not loading a new mesh for the last 6 hours, I would do screen captures of all this. But I figured if you are using variables like that, just reading step by step made sense to you.

I’ll go get myself more coffee and cookies.

Maha,
Maha Merrymaking

I replicated your setup exactly, but none of it works for me.

But blueprints are actors, and present in the level. The Test variable in the database BP is set to exposed and given a default value. The only step I added was to store the data in a local variable in the receiving BP. Nothing prints on game beginplay.

Help?

Just to avoid confusion, the unexposed test variable in the low left corner is not the database’s variable, it is the receiving BP’s test variable.