AActor* UWorld::SpawnActor( UClass* Class, FVector const* Location, FRotator const* Rotation, const FActorSpawnParameters& SpawnParameters ) { ... AActor* const Actor = NewObject<AActor>(LevelToSpawnIn, Class, NewActorName, ActorFlags, Template, false/*bCopyTransientsFromClassDefaults*/, nullptr/*InInstanceGraph*/, ExternalPackage); // Add this newly spawned actor to the network actor list. Do this after PostSpawnInitialize so that actor has "finished" spawning. AddNetworkActor( Actor ); return Actor; }
voidUPendingNetGame::BeginHandshake() { // Kick off the connection handshake UNetConnection* ServerConn = NetDriver->ServerConnection; if (ServerConn->Handler.IsValid()) { ServerConn->Handler->BeginHandshaking( FPacketHandlerHandshakeComplete::CreateUObject(this, &UPendingNetGame::SendInitialJoin)); } else { SendInitialJoin(); } }
在继续分析之前,先来看官方的注释,描述了登录的流程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Most of the work for handling these control messages are done either in UWorld::NotifyControlMessage, and UPendingNetGame::NotifyControlMessage. Briefly, the flow looks like this:
Client's UPendingNetGame::NotifyControlMessage receives NMT_Challenge, and sends back data in NMT_Login. Server's UWorld::NotifyControlMessage receives NMT_Login, verifies challenge data, and then calls AGameModeBase::PreLogin. If PreLogin doesn't report any errors, Server calls UWorld::WelcomePlayer, which call AGameModeBase::GameWelcomePlayer, and send NMT_Welcome with map information. Client's UPendingNetGame::NotifyControlMessage receives NMT_Welcome, reads the map info(so it can start loading later), and sends an NMT_NetSpeed message with the configured Net Speed of the client. Server's UWorld::NotifyControlMessage receives NMT_NetSpeed, and adjusts the connections Net Speed appropriately.
template <SIZE_T NumBits, typename SequenceType> classTSequenceNumber { static_assert(TIsSigned<SequenceType>::Value == false, "The base type for sequence numbers must be unsigned");
public: using SequenceT = SequenceType; using DifferenceT = int32;