I am having an issue when a player joins my game there is a quick flash of a camera sitting at what looks like 0,0,0. The Server player doesn’t not have the issue, I am guessing because the server is actually loading the world. However when a client joins the servers session, they get a quick flicker of a camera sitting at (0,0,0), before I manually spawn them to their correct PlayerStart. I manually spawn them in my GameMode right after OnPostLogin.
I have tried adding a UMG loading screen immediately after OnPostLogin, but the screen doesn’t show until after the camera flicker. I have tried slowing it down the events after OnPostLogin with delays to figure out what order everything is being loaded. It seems that right after OnPostLogin a spectator is spawned and that is what the player is looking through before their actual Character is spawned. I do not have “Start Players as Spectators” checked in the GameMode defaults, so it confuses me that any spectator is being spawned at all.
I have tried other loading screen solutions such as https://wiki.unrealengine.com/Loading_Screen but even with that solution, I see the loading screen and as soon as it closes I get the same camera flicker before the player is spawned to their designated PlayerStart.
What camera does that PlayerController use if it isn’t possessing a pawn? Does it default to a spectator pawn? How can I start a level completely black and fade in after everything is loaded? I did try CamerManager fade, but I get the same flicker with that too.
I’m still at a loss on this, I stripped everything down to just a playercontroller that creates a black UMG screen on BeginPlay, and disappears after 2 seconds. It works fine on the server, but on the client there is a flicker of the map before the UMG is loaded. I also did this on an empty map, empty GameMode (except changing to my TestPlayercontroller). I also tried not using UMG and having a level sequence auto play that just fades out, there is still a flicker of the map before the level sequence starts.
Any thoughts? How do I get a UMG to load before any camera shows the map after a client connects through Join Session? I’m willing to try any ideas right now
Nobody else seems to be having this issue, so I’ll just keep writing updates here in case someone ever hits it.
I created a c++ base gameinstance class and started displaying the playercontroller names during OnPreLoadMap and OnPostLoadMap events. It looks like for a normal “Open Level” the GameMode defined playercontroller is created right away for the player. However on a “Join Session” the OnPostLoad shows a default PlayerController for the client, then sometime after that it must replicate the server GameMode defined playercontroller. That brief creation of the default PlayerController while joining a session is what I appear to be seeing.
Knowing when this is happening might now give me some ideas for some workarounds, but no real solution yet. Of course, all this could just be something in my project that is messed up, I haven’t tried reproducing this in a fully empty project yet.
Doing this however will change your layout a little bit. You will have your persistent level and then your current main level with be a sublevel of that persistent one. With this setup you can load the level when you want to, which means you shouldn’t get that flicker and you can add a UMG loading screen.
Check out the Content Examples - Level Streaming to learn more.
That happens cause you Player spawns with only his PlayerController, sitting at 0,0,0. Camera at this point is set to the Manager which is probably also sitting at the PlayerController position.
Then your Server spawns the Client’s pawn and posses it, which takes a few milliseconds to replicate down to the client.
If think you can really only stop that by adding UI on the client. OnPostLogin is still server side, so that’s too late. Try BeginPlay of the PlayerController.
When a player joins the server, his data has to be loaded from MySQL through a socket server to determine character type. We do this in GameMode on PostLogin. This, of course, takes a second or two and, as the OP said, the 0,0,0 location is displayed briefly until the character is spawned at its logout location.
If I understood your post correctly, you were suggesting filling the screen on controller BeginPlay with a widget? I just tried this and while the widget will display, there is still a brief but noticeable flash of the origin.
@ToxinGaming Thanks for the idea, I did think about using Streaming levels. I’m not sure how that works when joining a multiplayer session, but definitely something I can look into. @eXi Yep OnPostLogin and BeginPlayer are both too late, but thanks for confirming the issue. I think maybe my managing the creation of a loading screen during PreLoadMap and PostLoadMap to cover the flicker may be the best solution for now. I also need to somehow mute audio too, if there is something near 0,0,0 that makes noise then there is also a brief sound before the Client pawn is spawned.
I have level streaming working for multiplayer - dedicated server. I would assume this would also work for listen servers.
Here is how I did my loading screen using streaming.
I have 3 levels, CityLvlPers (persistent), City, and LoadingScreen. City and Loading Screen are sublevels of CityLvlPers. I also made sure that the streaming method was blueprint and not always loaded.
Loading Screen is a completely blank level while City contains my city.
In my CityLvlPers Level Blueprint, off of Event BeginPlay, I call Load Stream Level with my Loading Screen, and off of the completed pin I call Remote Event with the Event name LoadLoadingScreen.
In my Loading Screen level blueprint, I have a custom event called LoadLoadingScreen (like the previous line). Here I check if it is a dedicated server running this, or a client, and branch off to either immediately calling Load Stream Level for City and Unload LoadingScreen for the dedicated server. Or for the client, I add a UMG widget to the viewport and then call Load Stream Level for City with Should Block on Load checked. When that is completed, I removed the UI Widget, Unload the LoadingScreen stream level, and set the Should Be Visible of the Get Streaming Level function with City to true.
There is a youtube of where I learned to do this. Level Streaming. You will probably find that easier to follow than my description.
I don’t know why he would use LevelStreaming to avoid the small “bug” of being in 0,0,0.
As long as he doesn’t actually need levels to be streamed it’s not necessary.
The earliest entry point, in Blueprints, is probably the BeginPlay of the LevelBlueprint.
You can try showing a Widget there. If that’s still showing the 0,0,0 Camera location for a milisecond, then you would need to actually use C++ and implement a proper loading screen. Instead of removing that on “PostLoadMap” you can delay it to remove it when ever you want.
I think the reason why I implemented level streaming is because I was having the same issue. I think I remember even trying using the begin play of the level blueprint like you said but the rest of the objects down the line aren’t loaded yet, therefore I didn’t have access to cast anything to my child blueprints in order to move the pawn, or hide anything, or anything like that. Even on the BeginPlay of the level blueprint, I tried adding a widget but I would always get a frame of the level loading in before the widget would load in.
I also found it much easier to implement Level Streaming to get everything to fade in from a loading screen and it requires zero C++ and works in multiplayer. I know that the OP wants to fix the 0,0,0 bug but they also wanted to implement fading and a loading screen, which level streaming can handle. Unless there is some crazy downside to level streaming, I don’t see any reason for the OP not to implement it.
Create C++ base game instance with BlueprintImplementableEvent that gets called PreLoadMap and PostLoadMap
In Blueprints PreLoadMap creates UMG loading widget and adds to viewport.
In Blueprints PostLoadMap loading widget is added to viewport again. (needs to be added again as this is now the default playercontroller created on joining a session)
UMG added to viewport during PostLoadMap will now persist until I decide to close it, or fade out.
I wanted a more global solution, not something per level, so I did not try and handle any of this on the LevelBlueprint.
I am sure streaming would work for this, but I think streaming will serve other purposes for me and I like the separation of certain items in their own persistent map. @Rhynedahll I think a solution like this would also resolve your issue. Or as eXi said BeginPlay of the LevelBlueprint could work too, but I never tried that. The PlayerController also has a ReceivedPlayer event that appears to get called very early, that might be something to look into too.
I’m still having this issue on 4.26. There is still no easy fix known.
There is always a 1-3 second delay of players joining where they are stuck frozen at (0,0,0).
I can’t figure out any good workaround yet besides putting a black cube at 0,0,0 in the map, and having it set to not visible when people load.
I’m having this issue right now as well. I’m not exactly sure why the camera appears on 0, 0, 0 and then eventually fixes itself (usually takes about one second). I’m even hiding the loading screen on the APlayerController::BeginPlay function so I really at a loss as to why this could be happening.
The only thing I can think of is that the camera has not replicated correctly to the client fast enough, and the client eventually decides to make a correction.
Spawn your character out of bounds on your map. Just drag a player start actor to the out of bounds on your map. It will spawn there and not the middle of the map. After this you can move the character where you want with code. You can even set up Tags in the spawn actor places so you can tell the character what ones to spawn on.
If you look at the world outliner following a client player test in PIE you’ll see that two additional camera actors are created outside of the playercharacter cameramanager. Usually Camera Actor_0 and CameraActor_1 these cameras are at 0,0,0 and I believe have the viewport for a brief time before any controller or camera manager logic is called. When testing on server or listen server you’ll see this behavior still occurs but doesn’t flash due to not needing to wait for the actor rep to complete. I’m not sure why this is even happening? i also do not have spawn spectators in my gamemode and am calling playerspawn from gamemode with none as my default pawn class in my gamemode settings. This behavior persist in 4.27.2
It looks to be part of the playercameramanager - PlayerCameraManager.cpp (Line 754)
The thing that confuses me is that setting a constructor on a player camera manager to set manual fade to 1 for black should construct the camera manager for the “selected local playercontroller” so that the viewport is black … even if this dummy camera actor is loaded. What I’m assuming is that the dummy camera gains viewport but is never given a manager for a frame meaning the construction for the manager doesn’t get called until controller init or very close to it.