Where to store global variables?

Hello.

Could you tell me where do I put my variables so I can access them from any other entity(e.g. so they’re global) and they’re also tweakable in the editor? I didn’t manage to find any solution to this problem.

I tried custom ‘world settings’, but when i added variables to them, they didn’t show up in the editor(btw. editor didn’t accept my custom world settings class, it kept changing it back to default on editor startup):

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Globals")
float MapSize;

I tried to add them to game mode, but i can’t manage to access game mode from an actor-how do I do that?

Both of those seem like workarounds-I’m sure there has to be a sensible way to achieve my goal. Any ideas, please? :slight_smile:

1 Like

“If once you start down the dark path, forever it will dominate your destiny” – Yoda to Luke

Please do not consider using global variables - they are the work of the devil. Although Unreal Engine makes extensive use of them, do not follow that path and learn from our suffering :slight_smile:

Someone more knowledgeable about the game framework will tell you about the best place to put your variables. From my game programming experience with UE3 I would think that something like your AGameMode sub-class is probably a good spot. Depending on what your variables are used for, there may be more appropriate case specific classes.

I think you forgot to set up you WorldSetting class in project settings,

File → Package Project → Packaging Settings → Global Settings → Default Classes → World Setting Class

As i said earlier-I did change it in project settings and it didn’t work. It didnt show my variables, and after i closed the editor, it would restore the default class. So basically it wass impossible to change the world settings.

BUT! When i changed that and clicked ‘set as default’-it worked. After reopening the editor, my custom class was active. Thanks alot though, if it wasn’t for you I wouldn’t even try it again. :slight_smile:

and btw. It’s just
Edit->Project settings->(…)
:slight_smile:

Yea and i just remind myself i also did best casting on C++ call example XD

Another good place to put globals is in a GameSingleton. If you set GameSingletonClassName to something in DefaultEngine.ini (or Project Settings → Engine → General settings) it will create an instance of that object for you. You can get then get to it from the variable GameSingleton on UEngine. On Fortnite we set up a game singleton, and then added something to our kismet library to get it on demand. If you subclass public UBlueprintFunctionLibrary, those functions will be available from any blueprint. It creates exactly one game singleton ever, so it’s a good place to put data references that are global across your entire game. You can make that Singleton Class point at any blueprint you may want, and then you can set variables on that as needed.

Where can i then edit properties of GameSingleton inside Editor?

UPD: oh, i think i get it, we are creating Blueprint of subclass of our GameSingleton, and then we get BlueprintGameSingleton, and then we edit all properties inside Blueprint editor.

We can create our GameMode with all properties we need, luckily it is Blueprintable by default, then we create Blueprint with sublass of our GameMode. Then we edit all needed properties inside Blueprint Editor->Defaults, then we use this Blueprinted Game Mode for our game, we can setup it inside World Settings.

Just a quick note that GameMode may not be the best place to store global data in networked multiplayer games.
That’s because GameMode only exists on the server and clients don’t have access to it. This is desirable since it’s in charge of game rules etc. but if you want to for example access a list of inventory item data (which doesn’t change at runtime) from multiple locations and also on clients, then GameSingleton could be a better option.
I’m in the process implementing that right now and came across this topic :stuck_out_tongue:

The definitive solution at this point is the GameInstance rather than gamesingleton or similar, it is a valid solution for all game setups even transitioning between multiplayer levels and maps. It starts with the engine and closes with the engine, so if you say, have a setting you want loaded at startup and then to stay in a persistent, accessible place regardless of what servers or levels the player goes to, or pawns or controllers are created or destroyed, that’s the way to do it.

Don’t abuse the game instance by placing level or current game related variables there, but it’s the perfect place for things like settings that arent specific to levels or pawn, controller etc objects.

In UE v4.26+, released Dec 2020, there are now Programming Subsystems which can have their own lifecycles and were created to avoid having to override engine classes.
https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/Subsystems/

UE 5.3 example:

DataEngineSubsystem.h

UCLASS()
class DEMO_API UDataEngineSubsystem : public UEngineSubsystem
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable) 
	int AddData(FFoliageData data);
	UFUNCTION(BlueprintCallable) 
	void RemoveData(FFoliageData data);
	UFUNCTION(BlueprintCallable) TArray<FData> 
	GetData() const;

private:
	UPROPERTY(EditAnywhere, Category = "Content") 
	TArray<FData> Data;
};

DataEngineSubsystem.cpp

int UGameDataSubsystem::AddFoliage(FData data)
{
	return this->Data.Add(data);
}

void UGameDataSubsystem::RemoveFoliage(FData data)
{
	this->Data.Remove(data);
}

TArray<FFoliageData> UGameDataSubsystem::GetData() const
{
	return this->Data;
}

Data can be obtained in c++

	UDataEngineSubsystem* gameData = GEngine->GetEngineSubsystem<UDataEngineSubsystem>();
	TArray<FData> data = gameData->GetData();