Download

Best way to make a variable editable in editor and accessible in code, including when not in game

For context, I’m creating a voxel game and I am trying to figure out the best way to set up a variable that everyone needs access to called UVSize. Its a derived variable from another called TextureTiling. TextureTiling is an FIntPoint describing the rows and columns to be used when accessing a section of a texture atlas, for example, FIntPoint(16, 16) would be used to access subsections of a texture that has a grid of 16/16 subtextures, similar to how it’s done in minecraft. UVSize is an FVector2D which is calculated then cached off only once as 1 / TextureTiling. In our 16x16 example, this would give us a UVSize of FVector2D(0.0625f). I want this to only be done once during game and always be accessible from anywhere during game because it is constantly needed by a number of systems.

I initially put the variables on a new class called AVoxelManager that is spawned in by the gamemode, similar to how the gamemode spawns in a gamestate. When AVoxelManager is constructed, I set a static AVoxelManager* var to the new instance so its easily accessible from any systems in code. Since I extended AVoxelManager with a blueprint child ‘BaseVoxelManager’, the variable TextureTiling is also editable in editor. This all works great. But it breaks down as soon as I need to access these variables while not running a game.

For example, there is a blueprint actor that needs to display a voxel block in its viewport in editor. To properly texture the block and have it show correctly in the viewport, in c++ I am calling a function I made called ResetMesh that rebuilds the voxel block mesh on demand for easy viewing in the viewport. The problem is that ResetMesh requires us to fetch UVSize but no instance of AVoxelManager exists yet because we are in editor, not in a game.

I thought about just grabbing the class default object of AVoxelManager and using it’s UVSize but there are two problems with that: first, if I were to change TextureTiling in the blueprint child class, BaseVoxelManager, the CDO of AVoxelManager’s TextureTiling will now be different from the desired TextureTiling, the one on the blueprint class. The second is that UVSize is a derived var anyways so it won’t have the precalculated value if accessed on a CDO.

Ideally, I need an object that always exists so anything can access it from in game or in editor. Does anyone know of something like this? Or maybe there is a better solution? Would extending GameInstance work? I’m pretty sure it always exists. But again, I also need to be able to easily edit the variables (like TextureTiling) in editor. I also want to keep the accessing of variables like this extremely fast, just getting a variable, no 'if’s or anything like that.

I look forward to any ideas you all might have. Thanks for your time!

If you create a static variable in code, it will exist anywhere, in editor too, if the value is change, it’s for the whole system. You won’t be able to make it a UProperty but you can create UFunction that manipulate these statics variables.

I tried static variables but I need to be able to set them like I would set a default - like you pointed out, they can’t be made into UPROPERTY so there doesn’t seem to be a good way to set it in editor like I want. If I were to make UFUNCTION blueprint callable that could set the static variable, where would I call it from in BP?

I’m still interested to see if anyone has any thoughts on this, but for the time being I seem to have found a potential solution.

Following the amazing Rama here:

With additional context here:

I was able to create a blueprint singleton class that I can set defaults on and already exists in editor when anything might want to access it.

For more context, in my new singleton, I have two variables so far: TextureTiling and UVSize.
TextureTiling is set to 16 in the constructor (but can also be edited in BP through EditDefaultsOnly) and UVSize is set in PostInitProperties.

The singleton is accessed in editor during OnComponentCreated - which is fine because the singleton instance already exists.

And of course it also works fine in game too.

There is a good and correct way to do this.
Actually everybody making a project in Unreal should know how to do it. (bad docs don’t help I guess)

Every time I read about “managers” I think somebody is probably coming from Unity. :stuck_out_tongue:
I always hated the “managers for everything” in Unity projects.
(don’t use global static variables either, it’s a bad idea)

I’m feeling patient today, so I will show you a simple way to solve your dilemma with images:
[HR][/HR]

First thing you have to do is create a new module into the project.
This is how:

  1. Edit your uproject file to include a new module which I will show you how to create:

  1. Create the folders for your new module, from windows explorer.
    Add common public and private folders, and a new Build.cs file for the module:

  1. The MyGameSettings.Build.cs file should declare code like this:

  1. In the Public folder, create a IMyGameSettings.h file, declaring this interface:

  1. Also in Public folder, create a MyGameSettings.h file, containing this class:

  1. In Private folder, create a IMyGameSettings.cpp file, add this code to it:


[HR][/HR]
Now from your project’s Build.cs, include a dependency to your new settings module:

From sources in your project’s code you can now access and write to the settings, for example doing this:

If you want non-coders to access and edit the values from Blueprints, you can just create a UFunction or Function to do the same thing shown above.
Or you could create a Function Library for that. [HR][/HR]

The good thing is, if you’ve done everything correctly, everybody working on the project can do this now:

[HR][/HR]

And that’s how you should make “Managers” in Unreal :wink:

Wow - this looks amazing. I’m going to try this out - it looks like exactly what I need. Thanks a ton - you obviously put a lot of time and effort into this response and I appreciate that!

Oh I forgot to add that, after you create the new module files, you should on windows explorerer right click uproject file and regenerate the visual studio solution before compiling!

BrUnO XaVIeR, thank you for putting together this tutorial, learned a lot from it.

I was going to point out that the GameInstance class may be what he is looking for, as that is where I have been putting my persistent across levels data. But, using a module seems much better.

The module isn’t really the point.

The module is just so we have an entry point to create a GUI auto generated for non programmers to edit the values in editor.
This way we don’t waste time creating assets and fighting with the GeneratedClass weirdness and widgets for the settings we need are auto generated by the editor, saving us time… (just declare UPROPERTY() in Settings UObject for new project settings, done).