UGameInstance::HandleNetworkError

当网络链接出现错误时,会调用该函数 (服务端拒绝玩家加入时也会调用)。
调用栈为(可以继承 UEngine 来替换 Engine 实现):

1
UEngine::HandleNetworkError -> UEngine::HandleNetworkFailure_NotifyGameInstance -> GameInstance->HandleNetworkError(FailureType, bIsServer);

VS 断点调用栈:

UEngine::HandleNetworkFailure实现为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Runtime\Source\Runtime\Engine\Private\UnrealEngine.cpp
void UEngine::HandleNetworkFailure(UWorld *World, UNetDriver *NetDriver, ENetworkFailure::Type FailureType, const FString& ErrorString)
{
UE_LOG(LogNet, Log, TEXT("NetworkFailure: %s, Error: '%s'"), ENetworkFailure::ToString(FailureType), *ErrorString);

if (!NetDriver)
{
return;
}

// Only handle failure at this level for game or pending net drivers.
FName NetDriverName = NetDriver->NetDriverName;
if (NetDriverName == NAME_GameNetDriver || NetDriverName == NAME_PendingNetDriver)
{
// If this net driver has already been unregistered with this world, then don't handle it.
if (World)
{
if (!FindNamedNetDriver(World, NetDriverName))
{
// This netdriver has already been destroyed (probably waiting for GC)
return;
}
}

// Give the GameInstance a chance to handle the failure.
HandleNetworkFailure_NotifyGameInstance(World, NetDriver, FailureType);

ENetMode FailureNetMode = NetDriver->GetNetMode(); // NetMode of the driver that failed
bool bShouldTravel = true;

switch (FailureType)
{
case ENetworkFailure::FailureReceived:
break;
case ENetworkFailure::PendingConnectionFailure:
// TODO stop the connecting movie
break;
case ENetworkFailure::ConnectionLost:
// Hosts don't travel when clients disconnect
bShouldTravel = (FailureNetMode == NM_Client);
break;
case ENetworkFailure::ConnectionTimeout:
// Hosts don't travel when clients disconnect
bShouldTravel = (FailureNetMode == NM_Client);
break;
case ENetworkFailure::NetGuidMismatch:
case ENetworkFailure::NetChecksumMismatch:
// Hosts don't travel when clients have actor issues
bShouldTravel = (FailureNetMode == NM_Client);
break;
case ENetworkFailure::NetDriverAlreadyExists:
case ENetworkFailure::NetDriverCreateFailure:
case ENetworkFailure::OutdatedClient:
case ENetworkFailure::OutdatedServer:
default:
break;
}

if (bShouldTravel)
{
CallHandleDisconnectForFailure(World, NetDriver);
}
}
}

void UEngine::HandleNetworkFailure_NotifyGameInstance(UWorld *World, UNetDriver *NetDriver, ENetworkFailure::Type FailureType)
{
bool bIsServer = true;

if (NetDriver != nullptr)
{
bIsServer = NetDriver->GetNetMode() != NM_Client;
}

if (World != nullptr && World->GetGameInstance() != nullptr)
{
World->GetGameInstance()->HandleNetworkError(FailureType, bIsServer);
}
else
{
// Since the UWorld passed in might be null, as well as the NetDriver's UWorld,
// go through the world contexts until we find the one with this net driver.
for (auto& Context : WorldList)
{
if (Context.PendingNetGame != nullptr &&
Context.PendingNetGame->NetDriver == NetDriver &&
Context.OwningGameInstance != nullptr)
{
// Use the GameInstance from the current context.
Context.OwningGameInstance->HandleNetworkError(FailureType, bIsServer);
}
}
}
}

ENetworkFailure 的声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Runtime\Engine\Classes\Engine\EngineBaseType.h
/** Types of network failures broadcast from the engine */
UENUM(BlueprintType)
namespace ENetworkFailure
{
enum Type
{
/** A relevant net driver has already been created for this service */
NetDriverAlreadyExists,
/** The net driver creation failed */
NetDriverCreateFailure,
/** The net driver failed its Listen() call */
NetDriverListenFailure,
/** A connection to the net driver has been lost */
ConnectionLost,
/** A connection to the net driver has timed out */
ConnectionTimeout,
/** The net driver received an NMT_Failure message */
FailureReceived,
/** The client needs to upgrade their game */
OutdatedClient,
/** The server needs to upgrade their game */
OutdatedServer,
/** There was an error during connection to the game */
PendingConnectionFailure,
/** NetGuid mismatch */
NetGuidMismatch,
/** Network checksum mismatch */
NetChecksumMismatch
};
}