Unity에서 Host에 연결된 Client는 Host가 연결끊길 경우에 Client들에게 RPC를 통해 알려줄 수 있습니다.
하지만, 예기치 못한 상황에 강제종료를 하게되면 제대로 RPC가 호출되지 않고 Client들은 호스트가 없는 상태에서 게임이 멈추게 됩니다.
따라서 Host가 끊길 때 RPC를 보내는 것이 아니라, 계속 보내다가 RPC를 안보내면 Host의 연결이 끊긴 것으로 판단해야 하며 이를 Heartbeat Lobby 라 합니다.
이번에는 해당 Heartbeat Lobby 를 구현하고, 하는 김에 Ping 까지 측정할 수 있도록 해보겠습니다.
public float pingInterval = 2.0f;
public float timeoutThreshold = 10.0f;
private float lastPongTime; // 가장 최근 받은 pong응답 시간
private float pingTimer; // ping 보내기 까지 남은 시간
private float pingSentTime; // 가장 최근 ping 보낸 시간
private bool isDisconnected = true;
public float LastPingMs { get; private set; } = -1;
우선 변수 선언입니다.
2초마다 핑을 보내고, 10초간 응답이 없으면 끊겼다고 판단하겠습니다.
private void Update()
{
if (!isHeartbeating) return;
if (!IsClient || IsHost) return;
pingTimer -= Time.deltaTime;
if (pingTimer <= 0f)
{
if (NetworkManager.Singleton.IsConnectedClient)
{
SendPingServerRpc();
pingSentTime = Time.time;
}
pingTimer = pingInterval;
}
if (!isDisconnected && (Time.time - lastPongTime) > timeoutThreshold)
{
isDisconnected = true;
Debug.LogWarning("[HeartbeatChecker] : Host Disconnected");
// TODO - Disconnected
}
}
public void StartHeartbeat()
{
if (IsClient && !IsHost)
{
lastPongTime = Time.time;
pingTimer = pingInterval;
isHeartbeating = true;
}
}
public void EndHeartbeat()
{
isHeartbeating = false;
}
우선 Host는 항상 핑이 0ms 이기 때문에 제외해주도록 합니다.
우선, SendPingServerRPC 함수를 통해 서버와 핑을 주고받아 가장 최근 응답받은 pong 시간을 기록합니다.
그 후에 최근에 받은 pong 응답 시간과 현재 시간의 차이를 통해 연결이 끊겼는지 판단하였습니다.
[ServerRpc(RequireOwnership = false)]
private void SendPingServerRpc(ServerRpcParams rpcParams = default)
{
if (!NetworkManager.Singleton.IsHost)
return;
ReceivePongClientRpc(rpcParams.Receive.SenderClientId);
}
[ClientRpc]
private void ReceivePongClientRpc(ulong clientId)
{
if (clientId != NetworkManager.Singleton.LocalClientId)
return;
lastPongTime = Time.time;
if (isDisconnected)
{
Debug.Log("[HeartbeatChecker] 서버 응답 복구됨!");
isDisconnected = false;
}
LastPingMs = (Time.time - pingSentTime) * 1000.0f;
Debug.Log($"[HeartbeatChecker] Ping: {LastPingMs:F0} ms");
}
이렇게 하면 호스트가 예기치 않게 끊긴 경우에도 클라이언트 측에서 정상적으로 로비씬을 나와서 게임을 진행할 수 있게 됩니다.
추가적으로 Start와 End함수로 HeartBeating을 On/Off 가능하도록 해야 불필요한 ping 측정을 방지할 수 있습니다.


이런식으로 Heartbeat Lobby를 사용하면 Ping을 통해 현재 네트워크 상황을 알 수 있고, 오랫동안 응답이 오지 않으면 Client의 연결을 끊어 계속 안정적으로 게임을 플레이할 수 있습니다.
특히 Host의 연결이 갑자기 끊기는 경우에는 서버에서 연결을 끊는 함수를 호출할 수가 없기 때문에 이러한 방식을 사용해서 각 Client가 연결을 끊어야 합니다.
다음에는 이를 활용하여 네트워크 환경에서 씬을 관리하는 방법에 대해 알아보겠습니다.