UE4实现断线重连功能

断线重连的整体逻辑是 设备离线后,根据需要决定是否保留pawn,还是设备重连后再重新生成一个,然后是断线重连时的验证方式,最后是playerstate重连后的属性保留

  1. 重载Playercontroller的PawnLeavingGame,这里是设备断线后,不会删除pawn,根据自己的需求决定是否需要修改,如果不需要保存pawn,没有必要重载该函数。

    void AMVNControllerBase::PawnLeavingGame()
    {
    if (GetPawn() != NULL)
    {
    //GetPawn()->Destroy();
    //SetPawn(NULL);
    }
    }

2.如果要保留pawn的话,可以重载GameMode的AddInactivePlayer,这个函数原本是保留断线的playerstate的,如果也要保留pawn的话,可以在这个函数里参照保留PlayerState的方式,保存pawn,如果不需要保存pawn,没有必要重载该函数。

复制代码
void AVTTSGameModeBase::AddInactivePlayer(APlayerState* PlayerState, APlayerController* PC)
{
	check(PlayerState)
		UWorld* LocalWorld = GetWorld();
	// don't store if it's an old PlayerState from the previous level or if it's a spectator... or if we are shutting down
	if (!PlayerState->IsFromPreviousLevel() && !MustSpectate(PC) && !LocalWorld->bIsTearingDown)
	{
		APlayerState* const NewPlayerState = PlayerState->Duplicate();
		APawn* PolicePawn = PC->GetPawn();
		if (NewPlayerState && PolicePawn)
		{
			// Side effect of Duplicate() adding PlayerState to PlayerArray (see APlayerState::PostInitializeComponents)
			GameState->RemovePlayerState(NewPlayerState);

			// make PlayerState inactive
			NewPlayerState->SetReplicates(false);

			// delete after some time
			NewPlayerState->SetLifeSpan(InactivePlayerStateLifeSpan);
			//设置自动删除的时间
			PolicePawn->SetLifeSpan(InactivePlayerStateLifeSpan);
			// On console, we have to check the unique net id as network address isn't valid
			const bool bIsConsole = !PLATFORM_DESKTOP;
			// Assume valid unique ids means comparison should be via this method
			const bool bHasValidUniqueId = NewPlayerState->GetUniqueId().IsValid();
			// Don't accidentally compare empty network addresses (already issue with two clients on same machine during development)
			const bool bHasValidNetworkAddress = !NewPlayerState->SavedNetworkAddress.IsEmpty();
			const bool bUseUniqueIdCheck = bIsConsole || bHasValidUniqueId;

			// make sure no duplicates
			for (int32 Idx = 0; Idx < InactivePlayerArray.Num(); ++Idx)
			{
				APlayerState* const CurrentPlayerState = InactivePlayerArray[Idx];
				if ((CurrentPlayerState == nullptr) || CurrentPlayerState->IsPendingKill())
				{
					// already destroyed, just remove it
					InactivePlayerArray.RemoveAt(Idx, 1);
					InactivePawnArray.RemoveAt(Idx, 1);
					Idx--;
				}
				else if ((!bUseUniqueIdCheck && bHasValidNetworkAddress && (CurrentPlayerState->SavedNetworkAddress == NewPlayerState->SavedNetworkAddress))
					|| (bUseUniqueIdCheck && (CurrentPlayerState->GetUniqueId() == NewPlayerState->GetUniqueId())))
				{
					// destroy the playerstate, then remove it from the tracking
					CurrentPlayerState->Destroy();
					InactivePlayerArray.RemoveAt(Idx, 1);
					InactivePawnArray.RemoveAt(Idx, 1);  //保存角色
					Idx--;
				}
			}
			InactivePlayerArray.Add(NewPlayerState);
			InactivePawnArray.Add(PolicePawn);
			// make sure we dont go over the maximum number of inactive players allowed
			if (InactivePlayerArray.Num() > MaxInactivePlayers)
			{
				int32 const NumToRemove = InactivePlayerArray.Num() - MaxInactivePlayers;

				// destroy the extra inactive players
				for (int Idx = 0; Idx < NumToRemove; ++Idx)
				{
					APlayerState* const PS = InactivePlayerArray[Idx];
					if (PS != nullptr)
					{
						PS->Destroy();
					}
				}

				// and then remove them from the tracking array
				InactivePlayerArray.RemoveAt(0, NumToRemove);
				InactivePawnArray.RemoveAt(0, NumToRemove);
			}
		}
	}
}
  1. 同理如果需要重新获得之前保留的pawn的话,重载gamemode的restartPlayerAtPlayerStart,默认的话是直接生成新的pawn,如果你想直接使用就的pawn修改响应的逻辑
  2. 重载时设备的验证,GameMode的FindInactivePlayer函数,默认设备重连时会比较网络的UniqueId,如果一致那么会复制原本的设备的playerstate数据,但是如果你的客户端设备经过重启的话,是会识别成新的客户端,所以根据需要自己去决定是否修改验证方式。
  3. 重载PlayerState的CopyProperties,将你自定义的变量进行重新复制

以上就是断线重连基本的涉及的函数了,这一切的前提是gamemode必须继承自AGameMode,然后如果你没有保留pawn,或者自己验证重新登录逻辑的话,只需要修改第5条对应的内容就可以实现断线重连了

相关推荐
Days20505 小时前
全网去水印1.0.0源码发布
php
一技安身5 小时前
VMware Workstation 25H2 创建兼容ESXi8.0虚拟机教程
服务器
硅基手札5 小时前
【Linux 内核专栏 13】快IO层
linux·服务器·嵌入式硬件
刘胡子大叔5 小时前
repo 与 index:站点目录该怎么切
ubuntu·php
Pointer Pursuit5 小时前
Linux调试器 ——gdb/cgdb
linux·运维·服务器
IanSkunk5 小时前
从检查设备到训练方案:眼科与视光中心设备联动的数据通路、字段口径与校验规则
服务器·数据库·负载均衡
chenlance5 小时前
PADS灌铜、覆铜过程和技巧小汇总
linux·服务器·网络
xixiaoyunya5 小时前
服务器自动备份怎么做:十几分钟搭建一套稳定可监控的方案
运维·服务器
2601_962885726 小时前
批量取数比循环单取快多少?用 AlphaFeed klines.batch给多股票取数提速
开发语言·php·batch
翼龙云_cloud7 小时前
阿里云国际代理商:ECS部署DeepSeek大模型指南
服务器·阿里云·大模型·云计算