GEngine* is null when actors instantiate during editor startup?

I need access to my global data singleton (GEngine->GameSingleton) in the constructors for several of my actor types.

However, while the editor is loading, it appears that the actors are running their constructors (For their content browser versions I assume? This happens for actors who have no instances placed in the default level), and they’re doing it at a point at which the GEngine pointer is returning null.

As a result, my actors are self-destructing when the editor opens, but are fine if I recompile them (they have BP derived versions) from the editor after startup, and at runtime it’s fine (I think.) It’s just the editor that’s breaking everything whenever I open it.

Is there any way to ensure that the UEngine has actually initialized before actors try to instantiate? I tried setting the primary game module to load PostEngineInit, but it just caused a crash.

Hi Teiwaz,

Whenever you need to access GEngine in your code, it is typically a good idea to check and make sure it is valid first. In my case, I always place code that requires GEngine inside an if statement.

if (GEngine)
{
    // Your code here.
}

This will prevent problems when starting the Editor, as well as avoid crashes during runtime if you try to access GEngine at a moment when it may not be available.

2 Likes

Hi, the problem isn’t the crash. (I avoid it by checking for Validity as you say.) The problem is that I need access to GEngine to get the GameSingleton to pull some data I need to instantiate my actors.

This works fine in most cases, except that when I first open my project, whereupon the actors’ constructors all run before GEngine has a valid value. This causes the creation of some of my actors’ components to fail. The editor then proceeds to save the actors without the components they need, causing data loss and my having to go through and recompile every actor.

I was under the impression that for components to function properly in the editor, they had to be created using CreateDefaultSubobject, which only works in constructors. That rules out using BeginPlay for this.

I’m uneasy about changing basic things about how actors construct themselves. I’ll give it a look, but my assumption would have been that the editor is recompiling all of the blueprints in my project for a reason, and not just for ■■■■■ and giggles, so disabling that is worrying. I just don’t understand why it’s happening so early in the startup process.

Is there any accepted way to pass data about blueprints / blueprint classes back to code? Specifically, I’m trying to instantiate blueprint-based components in C++ constructors, but my attempts have been foiled everywhere due to UE4 not seeming to have any place, at all, which I can use to store data and be sure that it’ll be there when things start trying to construct themselves at editor startup.

Ah, that does make things a little bit trickier. Generally speaking, it is not a good idea to depend on anything being available when a constructor is run, whether that is GEngine, another class in your game, or something else. We do not guarantee that things will always be available in the same order every time the Editor or game starts.

Having said that, there may be a few options available to you. They may not be particularly ideal, but I believe they should accomplish what you need for the most part.

What may work best for you would be to override the OnConstruction function in AActor. This function is run whenever an Actor is placed in the level (in the Editor) or spawned. This should resolve the problem for Actors that are already in the level, but Actors that are not placed may not be fully constructed until they are placed or spawned in the level. This should resolve any issues when starting the Editor, while still fully creating the Actor when it is needed in the game.

Another option would be to use the BeginPlay function. This would provide functionality similar to what you would see from OnConstruction, except it wouldn’t run when you place the Actor into the level.

Lastly, you could try using the PostInitProperties function. I am not sure this one would actually be helpful though, since I believe it runs immediately after the Constructor finishes, which may still be too early and GEngine may not be available yet. I could be wrong on the specific timing for when it runs though, and it may wait until all Constructors have finished, at which point GEngine may actually be available to use. Again, try not to rely on anything being available in a specific order or at a specific time.

Hi Teiwaz,

The reason the constructors are running is because the Editor is making the CDO’s for all of your classes when it starts. Would it be possible to see some sample code showing how you are trying to add your components in the constructor? Are your components pure BP classes, or are they Blueprints derived from custom code classes?

(Note: had to break this into 4 parts due to character limits)

The BPs in question are components which are derived from a custom C++ class.

The idea was that any actor or component in the project would have a native, abstract base class, and a blueprint class which inherits from that. That way, prototyping and experimentation could be done in the blueprint class, and then moved down into native code once the design stabilizes / it’s needed for performance / there’s just something which is too complex to do in blueprint.

The problem arises when you’re trying to construct blueprint components in a C++ actor’s constructor. While it’s not that hard to do in a lot of places, and works fine, the CDOs being generated super-early during editor startup means that I haven’t been able to find a place to set a UCLASS variable in order to provide the blueprint class which the actors need to create their components early enough for them to be used in the constructor.

Putting the variable on the native base class, and setting it in the blueprint class’ default properties doesn’t work, because it appears that the defaults from the CDO are copied over to the instance in the constructor, but the first thing the BP’s constructor appears to do is run the base class’ constructor, so components are created before default properties are set.

In this case, I’m trying to do it using a game data singleton. Since this lives in engine, I (incorrectly) thought that it would be available, because why would you ever start creating instances of game objects before the engine is initialized? (Right?)

(Continued below…)

(…continued)

My singleton contained TSubclassOf variables for each of my components:

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "BlueprintClasses")
	TSubclassOf<UHandControllerComponent_Base> HandControllerComponent_BPC;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "BlueprintClasses")
	TSubclassOf<UPickupableComponent_Base> PickupableComponent_BPC;

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "BlueprintClasses")
	TSubclassOf<AVRPlayerController_Base> VRPlayerController_BPC;

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "BlueprintClasses")
	TSubclassOf<UPhysicalDamageComponent_Base> PhysicalDamageComponent_BPC;

	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "BlueprintClasses")
	TSubclassOf<UGripComponent_Base> GripComponent_BPC;

I access the singleton using a blueprint library:

UVRArenaGlobalData* UVRArenaGlobalDataAccessLibrary::GetVRArenaGlobalData()
{
	if (!GEngine)
	{
		UE_LOG(VRArenaGeneral, Error, TEXT("Global data could not be found due to GEngine being null."));
		return NULL;
	}
	UVRArenaGlobalData* DataInstance = Cast<UVRArenaGlobalData>(GEngine->GameSingleton);

	if (!DataInstance || !DataInstance->IsValidLowLevel())
	{
		UE_LOG(VRArenaGeneral, Error, TEXT("Global data could not be found due to there being no GameSingleton set."));
		return NULL;
	}

	return DataInstance;
}

(Continued below…)

Then, in the native base class constructor of my pawn, I create the components I need using CreateDefaultSubobject:

AVRArenaPawn_Base::AVRArenaPawn_Base()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	Root = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
	RootComponent = Root;

	PlayerCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("VRPlayerCamera"));
	PlayerCamera->SetupAttachment(RootComponent);

	Chaperone = CreateDefaultSubobject<USteamVRChaperoneComponent>(TEXT("Chaperone"));
	AddOwnedComponent(Chaperone);

	
	UVRArenaGlobalData* GlobalData = UVRArenaGlobalDataAccessLibrary::GetVRArenaGlobalData();
	if (GlobalData)
	{
		
		TSubclassOf<UHandControllerComponent_Base> HandControllerComponentClass = GlobalData->HandControllerComponent_BPC;
		
		if (HandControllerComponentClass)
		{
			
			UE_LOG(VRArenaGeneral, Log, TEXT("Generating hand components"));
			
			//Hand_Left = Cast<UHandControllerComponent_Base>(CreateDefaultSubobject<HandControllerComponentClass>(TEXT("Hand_Left")));
			//<HandControllerComponentClass>(TEXT("Hand_Left"));
						
			Hand_Left = (UHandControllerComponent_Base*)CreateDefaultSubobject(TEXT("Hand_Left"), UHandControllerComponent_Base::StaticClass(), HandControllerComponentClass, false, false, false);
			if (IsValid(Hand_Left))
			{
				Hand_Left->SetupAttachment(RootComponent);
				Hand_Left->Hand = EControllerHand::Left;
			}
			else
			{
				UE_LOG(VRArenaGeneral, Error, TEXT("Left hand component creation failed"));
			}

			Hand_Right = (UHandControllerComponent_Base*)CreateDefaultSubobject(TEXT("Hand_Right"), UHandControllerComponent_Base::StaticClass(), HandControllerComponentClass, false, false, false);
			if (IsValid(Hand_Right))
			{
				Hand_Right->SetupAttachment(RootComponent);
				Hand_Right->Hand = EControllerHand::Right;
			}
		} 		
	}    
}

(…Continued)

But really, none of the constructor matters. Everything fails during editor startup, where trying to retrieve the Gamedata Singleton always aborts with the “Global data could not be found due to GEngine being null.” error. (The one that is just checking to see if the GEngine pointer is valid.) So most of my code never runs. The constructor fires, it tries to get the UEngine object, but the pointer is null so I can’t get the GameData Singleton, so I can’t get the class type of the component, so I can’t create the component.

If I open up the blueprint class from the content explorer, and hit the “compile” button, everything works fine, because GEngine is valid at that point, and my code works. If I drag an instance of the object into the level, it creates itself with the correct components. It’s just during editor startup that everything breaks due to the GEngine pointer not being set.

In the meantime I’ve just given up on being able to have actors create their own components in code. That seemed like the least critical part of the workflow. But it seems like a major hole in native->blueprint compatibility in the engine.

Yeah, I think that’ll do it. Thanks!

I was avoiding using explicit references to blueprint classes by path because of the maintainability issues, but this method means I only have to do this with a single class, in one location (I’d build that into a blueprint function library) which seems entirely acceptable to me.

If you know offhand, do you think this will cause issues with cooking content? (Due to hidden references.) Or should it be OK, since the CDOs will reference the BP classes (and so their assets) directly as soon as their constructors run?

Hi Teiwaz,

Sorry for the delay in getting back to you. I don’t typically use Singletons in my test projects, so I wanted to take the time to try to copy your setup as closely as possible, and then see if I could find any possible alternative methods to accomplish what you are doing. The good news is that I think I have managed to accomplish both of those goals.

For my test, I created four different custom component classes derived from UActorComponent. I added a UPROPERTY to each of these classes, then created a Blueprint for each one and set a default value for each property. I created a Singleton class containing a UPROPERTY of each of the four components and made a Blueprint of the Singleton, setting the properties there to use the Blueprints I had created of each component. Then I created a custom UBlueprintFunctionLibrary containing a function to access the Singleton class. In my character class, I called the library function to access the Singleton and set up a component I had added to the character class in the same way that you did in your pawn sample code. This provided me with the results that you described, where that component was not visible within the character class when the Editor was first opened, but after opening and compiling the character Blueprint, the component was suddenly there.

So the question I wanted to answer became how could I access the Singleton without needing to use GEngine, because there is no way to be certain that GEngine will be available when the class CDO’s are being created. I found out that I could access the CDO for the Singleton Blueprint directly, and that allowed the components to set up correctly when the Editor starts. This is what that portion of code in my character’s constructor looks like:

static ConstructorHelpers::FObjectFinder<UClass> DataObjectAsset(TEXT("Class'/Game/FirstPersonCPP/Blueprints/DataSingleton_BP.DataSingleton_BP_C'"));

	if (DataObjectAsset.Succeeded())
	{
		TheData = Cast<UDataSingleton>(DataObjectAsset.Object->GetDefaultObject());

		UE_LOG(LogTemp, Warning, TEXT("Object: %s"), *TheData->GetName());

		TSubclassOf<UHandControllerComponent> HandControllerClass = TheData->HandControllerComponent_BPC;

		if (HandControllerClass)
		{
			UE_LOG(LogTemp, Warning, TEXT("Hand Controller Class creation successful."));
			TheHand = (UHandControllerComponent*)CreateDefaultSubobject(TEXT("The Hand"), UHandControllerComponent::StaticClass(), HandControllerClass, false, false, false);
			UE_LOG(LogTemp, Warning, TEXT("%f"), TheHand->TheFloat);
			if (IsValid(TheHand))
			{
				UE_LOG(LogTemp, Warning, TEXT("%s created successfully."), *TheHand->GetName());
			}
			else
			{
				UE_LOG(LogTemp, Warning, TEXT("TheHand creation failed."));
			}
		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Hand Controller Class creation failed."));
		}
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Data Object Asset not available."));
	}

In this instance, TheData is a pointer to my UDataSingleton class, TheHand is a UHandControllerComponent property that I added to my Character class, and TheFloat is the property I added to UHandControllerComponent to make sure the component was being set up correctly. With this code, all of the messages in the log indicate success, and opening my character Blueprint immediately after the Editor opens shows the TheHand component is present as expected.

Is this something that would work in your project to allow your Blueprints to be set up correctly when the Editor opens? The function in the Blueprint Function Library would still work fine after the Editor is open, so this method would only be necessary for instances where GEngine is not available.

I did some real quick tests with cooking and packaging the project I was using to test this and both cooking and packaging appeared to work fine (note: I didn’t do any extensive testing, but I don’t expect any problems).