Use singleton for BP & C++ @designtime?

This ‘tutorial’

cannot (always) be used by C++ because when pressing F5 in Visual Studio this will throw the error:

UDataSingleton* dataInstance = Cast<UDataSingleton>(GEngine->GameSingleton); // Error: __imp_GEngine-> was nullptr.

which makes sense because it’s called during designtime instead of during runtime.

Now I could just make a whole different singleton just for the C++ one but they will be sharing a lot of code so that wouldn’t be proper. How is this done? I have an array of character names that I need to store somewhere and both C++ & Blueprints need to retrieve it during both runtime & designtime.

There is the GameInstance where you can store a lot of things accessible as long as the game is running.
Why not put that there ? You can even make your own C++ GameInstance class and have things exposed in BP and things accessible in C++. You just need to inherit a BP from this class.

That already is my GameSingleton class (Project settings>Engine>General Settings>Game Singleton Class) as the tutorial showed me:

But it only works during runtime. Because it crashes as soon as my C++ code attempts to access it from a constructor.

FText APlayerCharacter::CreateName()
{
   bool isValid;
	UDataSingleton* dataSingleton = UDataSingletonLibrary::GetSingletonData(isValid); // <<< crash here because GEngine is nullptr.
	if (isValid)
	{
		return dataSingleton->GetRndMaleSurname();
	}
	return FText::FromString("Error: FText APlayerCharacter::CreateName() dataSingleton was NULL.");
}

I also tried this in the data class (So that C++ can access it during designtime):

// header
public
    static UDataSingleton* Instance();
private:
	static UDataSingleton* _Instance;
// cpp
UDataSingleton* UDataSingleton::Instance()
{
	if (_Instance == nullptr)
	{
		_Instance = new UDataSingleton(); // erm how do I initialize this?
	}
}

But it looks dirty and even if I know how to construct a new class, it may cause other problems? But it would circumvent the GEngine problem.

I would have said something in the likes of :

222640-2017-12-05-13-25-43-magesbattle-unreal-editor.png

And the C++ class is like :

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MessageManager.h"
#include "MYGAMEGameInstance.generated.h"

/**
 * 
 */
UCLASS()
class MYGAME_API UMYGAMEGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:

	virtual void Init() override;

	UPROPERTY(BlueprintReadOnly, Category = "MessageManager")
	UMessageManager *messageManager;


};

Thanks to this I can get to my message manager anywhere.

Oh you literally put it in the GameInstance (or GameState or even GameMode for SP). Yes well that will work because that’s what I have now as well.

But if you need to access this global data from inside a constructor (which is called when just opening the UE4 editor for example), then there is no UWorld and no GEngine yet and it will crash while trying to access this data from GameInstance or GameState (or even that singleton). It will only work during runtime and will crash when used during designtime.

I can make it work for C++ but not while maintaining blueprint compatibility. And I’m slowly starting to feel that this was never implemented by Epic (missing feature) because it’s rarely needed.

Yeah the Editor can be a but weird bit if you have a class that inherits a UObject or UActor you should do a lot of things not in the constructor but in the PostLoad or BeginDestroy etc. So you are sure what you need is present.
You will probably encounter some issue in the editor, for example things not getting destroyed because the instance is still alive even after you “stopped” running the game but you can mitigate that with time.

Yep that is my current ‘workaround’. I moved stuff to the BeginPlay() to ensure that the World and Engine exist and that it is only called during runtime and dumping all that data into the GameState.

However this approach will mean that the load order of actors in the level may matter. Because if they only initialize critical parts inside the BeginPlay(), then another entity may already have fired it’s own BeginPlay() and may have used that actor which is not fully initialized yet.

So far I found these options at our disposal:

GameSingleton (custom singleton, runtime only)
GameState (runtime only, replicates)
GameMode (runtime only, no replication)
GameInstance (same as GameState but persists between levels)
C++ Singleton (works @designtime, not sure about replication)
C++ Static class (works @designtime, not sure about replication)

Mmm perhaps the solution is to make a static class with only static functions and retrieve everything through those functions. Because UPROPERTY still does not work for static properties it seems. So I would then have static properties without UPROPERTY and use UFUNCTION getters and setters instead. That should work for both C++ and blueprints at designtime and runtime (I think). But sadly this code inside a static class:

// No UPROPERTY here
static int32 test;

// Inline it because it's static
UFUNCTION(BlueprintPure)
static FORCEINLINE int32 gettest() { return test; }

gives errors LNK2001 and LNK1120 unresolved external. My C++ knowledge limits me there.

I do something about that too :
When my game instance is ready it initialize a class that will handle a lot of network stuff and everything depends on it. As you can guess it can take time to connect and retrieve data or it can fail at it.
To mitigate that I implemented blueprint events in my class (started, finished(bool success)). Other c++ class can handle the events and also can connect it in your blueprints.