• UE4实现断线重连功能


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

    1. 重载Playercontroller的PawnLeavingGame,这里是设备断线后,不会删除pawn,根据自己的需求决定是否需要修改,如果不需要保存pawn,没有必要重载该函数。
    void AMVNControllerBase::PawnLeavingGame()
    {
    	if (GetPawn() != NULL)
    	{
    		//GetPawn()->Destroy();
    		//SetPawn(NULL);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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
    • 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
    1. 同理如果需要重新获得之前保留的pawn的话,重载gamemode的restartPlayerAtPlayerStart,默认的话是直接生成新的pawn,如果你想直接使用就的pawn修改响应的逻辑
    2. 重载时设备的验证,GameMode的FindInactivePlayer函数,默认设备重连时会比较网络的UniqueId,如果一致那么会复制原本的设备的playerstate数据,但是如果你的客户端设备经过重启的话,是会识别成新的客户端,所以根据需要自己去决定是否修改验证方式。
    3. 重载PlayerState的CopyProperties,将你自定义的变量进行重新复制

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

  • 相关阅读:
    有一个整形数组, a[3] = {7,2,5}, 要求使用指针实现数组成员由小到大的顺序排列,即结果为:a[3] = {2,5,7};(C++指针练习2)
    在Mac M1笔记本上跑大语言模型llama3的4个步骤?(install、pull、run、ask)
    SpringCloud微服务实战——搭建企业级开发框架(三十七):微服务日志系统设计与实现
    YoloV5和YoloV8的魔力成为你在CS:GO2中的秘密武器。四步完成,CSGO2人物图像识别
    零犀科技携手集智俱乐部:“因果派”论坛成功举办,“因果革命”带来下一代可信AI
    操作系统学习笔记13 | 目录与文件系统
    Vulnhub:Os-Bytesec靶机渗透
    SQL 朝花夕拾 [保持更新]
    【爬坑之路一】windows系统下更新升级node版本【亲测有效】
    2022年认证杯SPSSPRO杯数学建模A题(第二阶段)人员的紧急疏散求解全过程文档及程序
  • 原文地址:https://blog.csdn.net/maxiaosheng521/article/details/132735892