Game crashes when using Seamless Travel to transition from LobbyMap to GameMap

Ok, so I made a minimal failing example, so you know exactly what I’m doing and can try to repdroduce the issue.

The goal is to transition from a “LobbyMap” to the “GameMap” using seamless travel, while at least one client is connected to the server.

I start a new project, the default FirstPersonShooter example.

First, I create a “LobbyMap”. Nothing special here, it’s just a default empty map.

Next comes the LobbyGameMode. For the sake of convenience, let’s just define a timer of 15 seconds after which the map get’s started:

The last thing I did is selecting the LobbyGameMode in the LobbyMap as the preferred GameMode.

Now I load the LobbyMap in the editor, select “2 Players” and start the game.

I join the lobby, as expected, after 15 seconds the map loads, as expected, but then the game and the editor crash, not quite as expected.

This is the crash report:

MachineId:B9583C1144759F5D15A7E09AC92499E0
EpicAccountId:a1ccd53fa2be4c999c0e53801a92194d

Access violation - code c0000005 (first/second chance not available)

UE4Editor_Engine!UActorChannel::CleanUp() + 1252 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\datachannel.cpp:1443]
UE4Editor_Engine!UChannel::ReceivedSequencedBunch() + 335 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\datachannel.cpp:279]
UE4Editor_Engine!UChannel::ReceivedNextBunch() + 2851 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\datachannel.cpp:588]
UE4Editor_Engine!UChannel::ReceivedRawBunch() + 675 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\datachannel.cpp:344]
UE4Editor_Engine!UNetConnection::ReceivedPacket() + 3880 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\netconnection.cpp:979]
UE4Editor_Engine!UNetConnection::ReceivedRawPacket() + 266 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\netconnection.cpp:457]
UE4Editor_OnlineSubsystemUtils!UIpNetDriver::TickDispatch() + 1367 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\online\onlinesubsystemutils\private\ipnetdriver.cpp:174]
UE4Editor_Engine!TBaseUObjectMethodDelegateInstance<0,UNetDriver,void __cdecl(float)>::ExecuteIfSafe() + 231 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\public\delegates\delegateinstancesimpl_variadics.inl:772]
UE4Editor_Engine!TBaseMulticastDelegate<void,float>::Broadcast() + 165 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\public\delegates\delegatesignatureimpl_variadics.inl:1030]
UE4Editor_Engine!UWorld::Tick() + 1024 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\leveltick.cpp:1027]
UE4Editor_UnrealEd!UEditorEngine::Tick() + 5618 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\editor\unrealed\private\editor.cpp:1329]
UE4Editor_UnrealEd!UUnrealEdEngine::Tick() + 22 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\editor\unrealed\private\unrealedengine.cpp:347]
UE4Editor!FEngineLoop::Tick() + 4179 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\launch\private\launchengineloop.cpp:2257]
UE4Editor!GuardedMain() + 1404 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\launch\private\launch.cpp:142]
UE4Editor!GuardedMainWrapper() + 26 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
UE4Editor!WinMain() + 249 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\launch\private\windows\launchwindows.cpp:202]
UE4Editor!__tmainCRTStartup() + 329 bytes [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c:618]

Did I do something wrong? Is this not how to use seamless travel?

I’m not afraid to use C++, but I want to know what I’m doing. I thought this should work that way…

Looking at the source code, this is the place where the error occurs (in DataChannel.cpp, line 1443):

				// Destroy any sub-objects we created
				for ( int32 i = 0; i < CreateSubObjects.Num(); i++ )
				{
					if ( CreateSubObjects[i].IsValid() )
					{
						Actor->OnSubobjectDestroyFromReplication( CreateSubObjects[i].Get() );

// Next line doesn't work
						CreateSubObjects[i]->MarkPendingKill();
					}
				}

I don’t know why it fails, but it looks like it shouldn’t fail. I only have limited knowledge of Unreal C++, but if CreateSubOjects[i].IsValid() returns true, but CreateSubObjects[i]->MarkPendingKill() crashes the engine through access violation, maybe Actor->OnSubobjectDestroyFromReplication( CreateSubObjects[i].Get() ) makes the pointer invalid?

Opinions?
(Or did I do something fundamentally wrong with the way I used servertravel? I don’t know!)

Ok, so Actor->OnSubobjectDestroyFromReplication( CreateSubObjects[i].Get() ) is defined in ActorReplication.cpp.

There, it’s cast to UActorComponent and Component->DestroyComponent(); get’s called.

So I look at this definition and at the end of DestroyComponent, this is called: MarkPendingKill();.

As far as I know, MarkPendingKill() marks the object to be ready for garbage collection, so every reference could be invalid now. After all those functions are finished, CreateSubObjects[i]->MarkPendingKill(); is called.

If I understood everything correctly, CreateSubObjects[i] might be an invalid pointer at the time. Is this correct?

Just tried it with 4.7.2. No change, still fails, same error message.

Ok, so now I forked the UE4 repo, cloned it to my pc and changed CreateSubObjects[i]->MarkPendingKill() to

if (CreateSubObjects[i].IsValid())
{
	CreateSubObjects[i]->MarkPendingKill();
}

After that I compiled engine and editor, tried to change the map with the ServerTravel command and…

the error message vanished!
In my eyes, this validity check makes sense since only valid objects can be killed. I don’t know that much about ue4 internals, so correct me if I’m wrong!

However, now there’s a new error message, see my attachment.

A quick peek in the Source showed it’s crashing on that line:

check( Actor->NeedsLoadForClient() );			// We have no business sending this unless the client can load

Apparently some actor is prepared for being sent to the client even tough it shouldn’t…

Also, I’d be nice to know, if I’m even doing the right thing.

I don’t even know if just setting bUseSeamlessTravel=true and calling ServerTravel mapname is the right way of doing this. It seems like it is in tutorials and documentation but maybe I missed a small step or configuration somewhere.

ANY feedback is welcome!

Hey Deventico,

Did you try just passing it the map name without the full path? i.e.: ServerTravel FirstPersonExampleMap

If you open up your game and bring up the console with ~ when you type in ServerTravel you will notice the command auto-populates with all the maps you have created in your project, so all you would have to do is call the name, without the need of the full path.

Hope this helps :slight_smile:

Thanks for your suggestion, but sadly it didn’t help.

I also tried ServerTravel MapName?listen (you can never be too sure) but it didn’t work either.

I should add that loading the map works fine if just the server loads it. As soon as other clients are connected, the game and editor crash.

Hey Justin,

would you be so kind and test this on a small example project? The one I described in the first post?

Then I’d know if it’s just failing on my pc (maybe firewall or something? I don’t know) or if it’s an issue for everyone.

Thank you!

EDIT: no longer needed.

Ok, I tried something else. Instead of checking CreateSubobjects[i].isValid(), I now check for CreateSubobjects[i].Get() != nullptr.

Funnily enough this gives me a different error! An access violation when dereferencing a LightMap (Log in attachments). See:

FLightMapInteraction FStaticMeshSceneProxy::FLODInfo::GetLightMapInteraction(ERHIFeatureLevel::Type InFeatureLevel) const
{
	return LightMap ? LightMap->GetInteraction(InFeatureLevel) : FLightMapInteraction();
}

What do LightMaps have to do with this? I can’t believe me checking for nullptr introduced this bug so, there are 2 possiblities:

  1. You can’t use ServerTravel and SeamlessTravel the way I did (just calling it).
  2. This is broken as well.

If some developer from Epic could PLEASE tell me if this is suppossed to work or not, I’d much appreciate it.

Another note on this:

The behavior now has changed. The server loads the map without problems. The player spawns and can even play for a bit. The client screen however stays black. Until of course engine and editor crash.

So it appears that this bug - if it is a bug - occurs on client side rendering.

ok, I don’t know much (nothing at all) about LightMaps in the C++ source code, but when I turn off every light and don’t build lightmaps, it still crashes, still same error.

Reddit got it right

After 2 days of analyzing this bug I decided to ask on /r/unrealengine.

Within 3 hours someone told me that this was a known bug and it only fails in preview mode in the editor. It does not appear when I build the game.

Man, this probably saved me a couple hours.

Sadly i have the exact same crash on 4.7.5 inside the editor :frowning:

Yeah, apparently the bug has been around for a while when I first encountered it and hasn’t beeen addressed since.

I also suspect that there are a couple more bugs related to multiplayer that make the engine crash, but I haven’t been able to narrow them down to specific situations/actions.

Hey there, I experienced the same “Assertion failed: Actor->NeedsLoadForClient()” error today when trying to perform a seamless travel in PIE multiplayer. Is there a possible workaround for this bug or even better maybe a fix? I mean its version 4.8.1 now…

I too would like to use seamless travel to allow my player states to persist. Has there been any progress on this issue?