x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

Singleton pattern in c++

Hello,

I am trying to implement a singleton pattern in c++ for manager objects. This are objects like a LevelManager that keeps track of all data of all the levels in the world like: name, description, spawnable tiles, images etc all stored in a struct TArray. and an UnlockManager which keeps track of all unlocks in my game. Which item the player has unlocked and which are still locked etc.

I got it to work, but it gives me problems while playing in editor (PIE). Because static variables are carried over between play sessions in the editor.. and somehow, my static instance variables become invalid after the second play.

To make it all work again, I have to restart the editor.. This is very annoying, and I can't seem to find a solution for this.

Does anyone know how to properly implement the singleton pattern for use in UE4? Or know another way to get global accessible classes in c++ ?

alt text alt text alt text

Product Version: UE 4.19
Tags:
1.png (8.7 kB)
2.png (8.9 kB)
3.png (10.7 kB)
more ▼

asked Jul 28 '18 at 01:04 PM in C++ Programming

avatar image

iProspartan117
27 5 5 11

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

I ran into a similar problem in the past. ONE solution is not to use singletons (i.e. try to force general programming patterns into an engine with its own framework and workflow). The way to cleanly integrate single-instance objects into Unreal is to put them either into the GameMode or GameInstance. The former is per-level, while the latter carries over. You have to decide which one is better for your particular use case.

For example: My SaveGameManager is instantiated by the GameInstance, since I can't have it reset whenever the player switches levels. This means that it's created before the first level is loaded and destroyed just before the game quits. I have a class that manages footstep sound mappings (surface to a set of sounds). Since all characters use the same mappings, I only need one instance of it. That one goes into the GameMode and is thus created at the beginning of a level and destroyed once it's left. And for the intended purpose, that's perfectly alright, because that object doesn't need to carry over data across level transitions.

I faced the same situation in Unity and it has been the same thing: Using the framework as intended (in your case: designing your systems around the lifecycle the engine expects objects to have) unfailingly was less work than trying to force the engine to play nice with a system that wasn't designed with the engine's framework in mind. I had to deal with cascading workarounds, because something always broke somewhere. Then I redesigned it around how Unity expects GameObjects to work and guess what? It just worked.

So my recommendation to you would be to reassess the problem at hand. Study the UObject/AActor life-cycles and the gameplay framework. As big as the latter is, chances are Epic has already put something into place where your system would integrate beautifully and headache-free.

more ▼

answered Jul 28 '18 at 02:05 PM

avatar image

TheSniperFan
184 1 3 7

avatar image iProspartan117 Jul 28 '18 at 02:35 PM

Thank you for your reply and clarification! I have a strong Unity background where I always used singleton classes for manager objects, so that's why it was my first instinct to use those in Unreal as well.

I understand your example with your save game manager, but could you maybe provide me with a coding example of how you did this? I want to do everything as OOP as possible.. So it sounds very counterintuitive to put data/functionality from what would normally be in different manager classes, into one big game instance class. I.e. Putting the save manager code in the exact same class as the code that takes care of managing all the levels in the game.

avatar image TheSniperFan Jul 29 '18 at 11:12 AM

Header:

 UCLASS()
 class YOURGAME_API UYourGameInstance : public UGameInstance
 {
     GENERATED_BODY()
     
     
 public:
     // Accessor for C++ & BP. Should be self-explanatory
     UFUNCTION(
         BlueprintPure,
         Category = "Persistence",
         meta = (
             DisplayName = "Get Savegame Manager",
             Keywords = "SavegameManager"))
     USavegameManager *SavegameManager();


 protected:
     // This is where we will clean up, as the game is shut down
     virtual void Shutdown() override;


 private:
 // Needs to be an UPROPERTY(), so the GC does its thing
 // Transient, so it doesn't get serialized itself. Will be nulled when the
 // game starts. Initialization happens later by hand.
     UPROPERTY(
         Transient)
     USavegameManager *SavegameManagerInstance;
 };

Source:

 // Singleton-like accessor. I only use this as a workaround for PIE
 // The GameInstance lifecycle is different in PIE
 // In proper builds, this wouldn't be necessary (I'll explain this further down)
 USavegameManager *UYourGameInstance::SavegameManager()
 {
     return
         IsValid(SavegameManagerInstance) ?
         SavegameManagerInstance :
         SavegameManagerInstance = NewObject<USavegameManager>(
             this,
             FName("SavegameManager"));
 }

 // Cleanup. This acts as a quasi-destructor
 void UYourGameInstance::Shutdown()
 {
     // Important, if you overwrite functionality in UE4.
     // Omitting this, may cause errors (depending on the class).
     Super::Shutdown();

     // PIE may cause this to be invalid. During the game, it will always be valid
     if (IsValid(SavegameManagerInstance))
     {
         SavegameManagerInstance->ClearStoredActors();
         SavegameManagerInstance->ClearLevelStorage();
         ClearPlayerInventoryCache();
     }
 }
avatar image MLarsson98 Jan 20 '19 at 11:27 AM

Hey, first, sorry for reviving an old thread, however, after reading this I had an obvious question. I'm writing a custom EventManager for my project, and found this question as I was searching for singleton patterns in UE4.

As I understand it, only one GameInstance can exist, which is a huge problem if I want to use it as a singleton solution, since I don't want to just pack whole bounch of different logics into one GameInstance. Second, even if I was allowed to create multiple GameInstances (please correct me if I'm wrong on that only one per game can exist at the same time), they will still come with a whole lot of unnecessary logic, atleast for my usecase.

Wouldn't it be better to create a standard C++ class disconnected from the UE4 framework, just a static singleton which I can access from anywhere, and which exists between levels since it's not even connected to the UE4 framework? This solution would work for more patterns as well, also probably OP's usecase.

Again, I'm not super experienced in Unreal, but that's my first thought concerning this issue.

avatar image TheSniperFan Jan 20 '19 at 10:41 PM

If you were able to create multiple GameInstances, it would completely defeat its point, since it's meant as a singleton. You don't implement everything inside your GameInstance. You do it as I pointed out. You create a normal (probably UObject derived) class that is your singleton. After that you add a getter to your GameInstance. So your logic is split up in its own singleton classes and you access the singleton instances through the GameInstance. The only difference between this and the classical singleton pattern is who handles the singleton class's life cycle.

The classical singleton consists of a private static member variable to hold the instance, a public static getter and a private constructor. The singleton class manages its life cycle itself. It creates itself. In UE4, you have the exact same singleton class, but use the GameInstance to handle its life cycle. So you have a private member variable and a public (static or not) getter. In UE4, the GameInstance manages the singleton's life cycle. The GameInstance creates it. Everything else is the same.

Of course you can create a classical singleton class that is completely separate. However, you won't be able to access it from Blueprints and it won't be GC managed, which opens you up to a whole world of problems, if it handles ANY object that is. So OP's use-case wouldn't play nicely with that, since he's working with an UObject derived class.

Imagine it weren't called "GameInstance", but "SingletonManager". That's essentially what that class is for most use-cases anyway.

To close this out, I will repeat what I told the other guy: Don't try to force general programming patterns into a framework with its own workflow. Lots of people talk about how you shouldn't use macros. And there are good reasons not to. That doesn't mean that you should desperately try to find hacks so you don't have to use UPROPERTY().

avatar image SmokersCough May 31 '19 at 04:38 PM

Hi guys sorry to bump the post again but i have a few questions about this.

I am basically making a music manager, this will play audio and can change the audio being played during the game so for example, it would play during a menu screen and then when the player makes it into game it will change the music to play for background music for in game action.

So i understand the concept of using the GameMode or GameInstance to control the lifetime of the singleton you create and the code above appears to demonstrate how to only make a singleton of this class and control it via the GameInstance which is perfect. (although should there be code in the shutdown function to null the singleton as i assume this i run when the game exits).

My big question is this (and please bear with me i'm new to C++ having only worked in Objective C where i made great use of singletons). Do i even need to make a singleton class specifically in this way: https://gist.github.com/pazdera/1098119 for the class i wish to create, or is the code at the very top of this post all that is required to create a singleton.

Many Thanks

avatar image TheSniperFan Jun 02 '19 at 11:41 AM

The code I showed is one clean way of doing it. If you look closely, you should notice that they do pretty much the same thing. There are only two differences, really.

  1. you use NewObject to create the instance, as opposed to the new operator

  2. the instance variable and getter are inside the GameInstance, as opposed to the singleton class itself

avatar image SmokersCough Jun 03 '19 at 05:28 PM

Hi Sniper Fan,

I was thinking more about the code in the singleton class.. am i correct in thinking the code you posted was dealing with the singleton in the game instance. But i was hoping for a code example of an actual singleton class.

avatar image TheSniperFan Jul 29 '18 at 11:12 AM

So about PIE. In a standalone build, your GameInstance gets instantiated once when your game launches, and is destroyed just before it shuts down. So usually we would drop the singleton-like getter, because it wastes performance on a validity check that will always return true. In that case, you'd use NewObject() once when the GameInstance itself is created (e.g. in OnStart()). In PIE this check can return false some times, which is a pain. So I use this more complex getter to make sure it's always valid, if I need to access the SaveGameManager. (In my GameMode, that is not necessary, because its lifetime doesn't have this different behavior in PIE.)

Technically, you can solve this problem even more elegant by using the preprocessor. You could use the above code purely inside the editor, and use a single-time instantiation and direct access without redundant validity checks by using conditional compilation (#if UE_EDITOR). In my case, the SaveGameManager is accessed so extremely rarely, that I don't care whether I do unneeded validity checks. For something that is accessed each frame, that may be worth considering (it's only a handful lines of code).

You can still find the old threads where people asked about how to deal with singletons/global objects cleanly without getting GC problems. The GameInstance was added (relatively) recently by popular demand. The way Epic built it into the engine, it makes two guarantees as far as your game's logic is concerned. The engine guarantees that the GameInstance is 1. always valid and 2. unique (PIE notwithstanding). So, by extension, everything you put in there is 1. always available and 2. exists only once.

avatar image TheSniperFan Jul 29 '18 at 11:27 AM

One more thing since you have a Unity background. There are two big differences between Unity and Unreal 4 from a programmer's perspective:

  1. Unity is very much a blank slate, Unreal has a much tighter framework

  2. Unity GameObjects/(MonoBehaviour-)Components are not the same as Unreal 4 Actors/ActorComponents

First one is clear. Unreal has stuff like GameMode, GameState, GameInstance, Pawn, Controller and so forth classes already in place. They're what's called the Gameplay Framework. Unity doesn't have such a thing (at least it didn't when I switched from Unity 5 to UE4). Unity gives you an empty scene with nothing going on, and you have to do everything yourself. Unreal already puts a framework in place in some places and expects you to fill in the blanks. Admittedly, you don't have to, but it saves you a lot of work.

Second one is more subtle. Unity operates with a clean Entity-Component-System. GameObjects are the sum of their components, Actors are not. In Unity, all the functionality of a GameObject resides within its components. In Unreal 4, Actors have their own functionality and are only extended by ActorComponents. So some code goes inside Actors and some inside ActorComponents. For a Unity developer, that might be confusing at first, but it's really simple: You define WHAT the thing is inside the Actor and use ActorComponents to give Actors functionality and properties that multiple different Actors share. Here are some examples:

  • PlayerCharacter: Actor, because it's a thing. (You would never use a PlayerCharacterComponent MonoBehaviour on a GameObject that isn't a player character)

  • Health (including damage handling, destruction): Component, because it's functionality that can be reused on NPCs, destructible objects, etc.

  • Item: Actor, because it's a thing

  • Inventory: Component, because it can be reused on NPCs, treasure chests, etc.

avatar image iProspartan117 Jul 29 '18 at 02:29 PM

Thank you so much for the clarification! It's all a lot more clear to me now. Thank you for your time and effort to bring up such a complete answer to my question.

I already knew (most) of the differences between Unity and Unreal. But because I am used to doing everything myself, from a Unity developer standpoint. Working in UE4 is quite difficult since there is indeed already such a big framework in place. So it's kind of hard to figure out what goes where.

But I'm sure that I'll learn it step by step.

Again, thanks a lot!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Hi Sniper Fan,

I was thinking more about the code in the singleton class.. am i correct in thinking the code you posted was dealing with the singleton in the game instance. But i was hoping for a code example of an actual singleton class.

more ▼

answered Jun 03 '19 at 05:28 PM

avatar image

SmokersCough
5 1 1

avatar image TheSniperFan Jun 04 '19 at 09:08 AM

Yes, the code I posted shows the singleton instance being created by the GameInstance. As for the singleton class itself, I don't know what to say. It's just a UObject derived class.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question