I’ve got a custom class that derives from GameState. I have a function to advance the game to the next “phase”, which should spawn a new controller and switch the player to this controller.
When I try and create a new controller via the NewObject function, the game instantly crashes and this is printed to the output:
Fatal error: [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.6\Engine\Source\Runtime\CoreUObject\Private\Templates\Casts.cpp] [Line: 11]
Cast of Class /Script/FantasyStrategy.PlayerUnitController to Level failed
UE4Editor.exe has triggered a breakpoint.
And the code in question…
auto instance = (UCustomGameInstance*)GetGameInstance();
APlayerUnitController* newController = NewObject<APlayerUnitController>(APlayerUnitController::StaticClass());
instance->GetLocalPlayerByIndex(0)->SwitchController(newController);
Currently a little rough around the edges as I have been attempting to get some sort of solution.
Is there any reason I cannot instantiate a new controller? I have tried in my GameMode derivative too, with the same error.
I think you’re calling NewObject() incorrectly.
The type is already specified by the template parameter, so you don’t need to call StaticClass(). The first argument is taken to be the Outer (owning) object. If you’re not bothered about that, just call NewObject< APlayerUnitController >(), no arguments.
In that case I don’t know. Do you have the engine source? If not it’s very hard to know.
If you do, where precisely is the crash occurring? The error says it is trying to cast your controller to a level, which is rather bizarre. Maybe the bit of code you posted is not the real problem and it just leads to some other bit of code crashing?
Hmm, I’ve never tried to create a controller dynamically, and I don’t have time to look into the engine code right now. However you can see that the error message has changed regarding the cast. A wild guess would be that AController makes the assumption that it’s outer class is a level object and attempts to cast inside its constructor. Try calling GetWorld() on some object you have to hand, and passing the world pointer into NewObject() as the first parameter.
Okay I somehow completely overlooked the obvious issue. You shouldn’t be using NewObject() in the first place, since a controller is an actor.
You always need to create new actors using UWorld::SpawnActor().
UWorld* world = Something->GetWorld();
APlayerUnitController* cont = world->SpawnActor< APlayerUnitController >();