Hi,
I’m having a problem with UE5: the game always crash whenever I use the Quick Launch button or try to play a packaged build, but it works perfectly fine if I play the level from inside the editor.
Basically, I spawn an actor of class ACameraManager at the start of the game using the Init function from the GameInstance class, as shown below:
The game crashes when I try to access this CameraManager object, but for some reason the object is being destroyed if I play the game outside the editor (I know that because I’ve added a UE_LOG inside the BeginDestroy function and it only triggers when using the Quick Launch/Packaged game).
Any clues? Is the object being Garbage Collected for some reason? Do I need to change any variables so the Actor doesn’t get destroyed for no reason?
Try adding spawn parameters to spawnactor function, to have it always spawn and try to adjust position.
It could be that in the default version of the function the engine tries to spawn the manager in a place that is inaccessible or obstructed and so it fails and returns a nullptr.
GameInstance is persistent, actors are bound to the current world (ie. level). Storing an actor in game instance is never a good idea.
I believe it would make more sense to spawn and use your camera manager from PlayerController class instead.
But I’m not changing levels or anything like that, the Actor shouldn’t be destroyed at the start of the game unless I’m missing something. And why does it work when I play the game from within the editor and not as a packaged game?
In my game the CameraManager is not attached to any controller, it’s an object that is going to have multiple camera functions and will be able to track other actors as well, I don’t need to spawn a new CameraManager for each actor/player.
Is there a way to make an Actor persistent?
In Game Maker you have a bPersistent flag that you can switch ON/OFF.
Since the GameInstance is only spawned once, it wouldn’t be a problem to make the CameraManager also persistent.
GameInstance might be initialized at engine initialization with a stub temporary world, before the real level is loaded.
PIE works different, there are multiple worlds running simultaneously, and you could be spawning the camera manager in one of the editor worlds erroneously (instead of the PIE world) but it still works because it keeps the reference alive.
If your object only has functions, consider making a BlueprintFunctionLibrary.
If your object needs to store variables, extend UObject instead of AActor. Then you can create it in GameInstance and it will be persistent.
If you are referencing actors, make sure you mark them as UPROPERTY so they are tied to garbage collector. Considering these variables will be nulled with every level change, always check that they are valid before using them.
All actor references will be nulled when changing levels. So if you need them you’ll have to somehow fill them again after loading any new level. At this point using a persistent UObject kinda loses its purpose so you might just make it an Actor ans spawn it automatically on each level start.
I suggested PlayerController because that’s generally where camera stuff is handled. Note that there is generally only one playercontroller for the entire game, unless you plan to implement split screen. Spawning your camera manager from PlayerController->BeginPlay should be a good way to ensure it’s readily available whenever the player has something to show on screen.
Alternatively if you plan to have multiple playercontrollers you can spawn your manager from GameState which is also a good place to hold singletons.