当前位置: 首页 > news >正文

UE5学习笔记25-游戏中时间同步

一、原因

        1.由于网络问题会导致服务器上的时间和客户端上获得的时间不一致

二、解决方法

        在程序启动时向服务器请求服务器的时间返回给客户端并获得客户端发送消息的往返的时间,在获得客户端上的时间,用服务器上获得的时间加上往返时间减去客户端上的时间获得差值,在通过获得客户端上的时间加上差值获得当前服务器上的时间

三、实现

        1.在界面添加显示时间的文本框用来显示时间(MatchCountDownText)

        2.添加设置界面的函数

         2.1界面类中添加

	UPROPERTY(meta = (Bindwidget))UTextBlock* MatchCountDownText;

        2.2.在PlayerController类中添加设置界面函数

void SetHUDMatchCountDowntime(float CountdownTime);void ABlasterPlayerController::SetHUDMatchCountDowntime(float CountdownTime)
{BlasterHUD = BlasterHUD == nullptr ? Cast<AABasterHUD>(GetHUD()) : BlasterHUD;bool bHUDValid = BlasterHUD &&BlasterHUD->CharacterOverlay &&BlasterHUD->CharacterOverlay->MatchCountDownText;if (bHUDValid){int32 Minutes = FMath::FloorToInt(CountdownTime / 60.f);int32 Seconds = CountdownTime - Minutes * 60;FString CarriedDownText = FString::Printf(TEXT("%02d:%02d"), Minutes, Seconds); BlasterHUD->CharacterOverlay->MatchCountDownText->SetText(FText::FromString(CarriedDownText));}
}

四、 同步

        4.1代码流程

        ReceivedPlayer()函数会在客户端启动时最开始调用,通过if判断当前是否是客户端通过GetWorld()->GetTimeSeconds();获得当前的客户端上的时间TClientTime1,调用服务器的RPC请求服务器的时间,在服务器上通过GetWorld()->GetTimeSeconds()获得当前服务器上的时间TServerTime1,在将TClientTime1,TServerTime1作为参数调用客户端的RPC将当前服务器时间TServerTime1和客户端请求同步的时间TClientTime1在给会客户端,在通过GetWorld()->GetTimeSeconds()获得当前客户端时间TClientTime2,通过TClientTime2-TClientTime1获得从请求到收到回复一共用了多长时间,在通过TServerTime1 + (TClientTime2-TClientTime1)/2 在客户端上获得当前服务器上的时间,再通过GetWorld()->GetTimeSeconds();获得客户端现在的时间,用当前服务器上的时间将去当前客户端的时间获得时间的差值。在游戏进行时通过Tick函数进行相同过程的判断。

        4.2代码实现,添加服务端RPC函数,客户端RPC函数等

	/***	同步客户端和服务器上的时间*/virtual void Tick(float DeltaTime) override;//请求当前的服务器上的时间,在发送请求时传入 Client 端时间,参数是客户端请求需要的时间UFUNCTION(Server , Reliable)void ServerRequestServerTime(float TimeOfClientRequest);// 给客户端报告当前的服务器的时间响应服务器请求服务器的时间UFUNCTION(Client, Reliable)void ClientRequestServerTime(float TimeOfClientRequest,float TimeServerReceivedClientRequest);float ClientServerDelta = 0.f; // 客户端和服务器端的时间的差值UPROPERTY(EditAnywhere , Category = Time)float TimeSyncFrequency = 5.f;//同步频率float TimeSyncRunningTime = 0.f; // 距离上一次同步过去的时间void CheckTimeSync(float DeltaTime);virtual float GetServerTime(); // 获得服务器上的时间virtual void ReceivedPlayer() override; // 尽快同步服务器时间void SetHUDTime();float MatchTime = 120.f; // 匹配时间uint32 CountdownInt;
void ABlasterPlayerController::ServerRequestServerTime_Implementation(float TimeOfClientRequest)
{float ServerTimeOfReceipt = GetWorld()->GetTimeSeconds(); // 服务器上的时间//UE_LOG(LogTemp, Warning, TEXT("My variable: %f"), ServerTimeOfReceipt);ClientRequestServerTime(TimeOfClientRequest, ServerTimeOfReceipt);
}void ABlasterPlayerController::ClientRequestServerTime_Implementation(float TimeOfClientRequest, float TimeServerReceivedClientRequest)
{float RoundTripTime = GetWorld()->GetTimeSeconds() - TimeOfClientRequest; // 获得往返时间float CurrentServerTime = TimeServerReceivedClientRequest + (0.5f * RoundTripTime); // 当前服务器时间ClientServerDelta = CurrentServerTime - GetWorld()->GetTimeSeconds();//UE_LOG(LogTemp, Warning, TEXT("My variable: %f"), ClientServerDelta);
}float ABlasterPlayerController::GetServerTime()
{float time = GetWorld()->GetTimeSeconds() + ClientServerDelta;//UE_LOG(LogTemp, Warning, TEXT("My variable: %f"), time);return time;
}void ABlasterPlayerController::ReceivedPlayer()
{Super::ReceivedPlayer();if (IsLocalController()){float Time = GetWorld()->GetTimeSeconds();//UE_LOG(LogTemp, Warning, TEXT("My variable: %f"), Time);ServerRequestServerTime(Time);}
}void ABlasterPlayerController::SetHUDTime()
{uint32 SecondsLeft = FMath::CeilToInt(MatchTime - GetServerTime());if (CountdownInt != SecondsLeft){//UE_LOG(LogTemp, Warning, TEXT("My variable: %f"), MatchTime - GetServerTime());SetHUDMatchCountDowntime(MatchTime - GetServerTime());}CountdownInt = SecondsLeft;
}void ABlasterPlayerController::Tick(float DeltaTime)
{Super::Tick(DeltaTime);SetHUDTime();CheckTimeSync(DeltaTime);
}void ABlasterPlayerController::CheckTimeSync(float DeltaTime)
{TimeSyncRunningTime += DeltaTime;if (IsLocalController() && TimeSyncRunningTime > TimeSyncFrequency){ServerRequestServerTime(GetWorld()->GetTimeSeconds());TimeSyncRunningTime = 0.f;}
}


http://www.mrgr.cn/news/50878.html

相关文章:

  • 解决关于使用dynamic_cast而导致的程序崩溃的现象
  • ES-入门-javaApi-文档-新增-删除
  • 当代社恐青年的社交解药:跟AI唠嗑上瘾
  • Crawl4AI:用几行代码打造强大的网页爬虫
  • C++运算出现整型溢出
  • ros service不走是为什么
  • “我们为什么缺少科学精神”演讲内容拆解
  • live2d 实时虚拟数字人形象页面显示,对接大模型
  • 机器学习:知识蒸馏(Knowledge Distillation,KD)
  • HTTP状态码
  • java代码编译javac
  • 如何让c盘不是那么快速的红
  • 信创服务器下连接kingbase并执行SQL的脚本
  • 数据可视化-使用python制作词云图(附代码)
  • 植物大战僵尸杂交版之后新作:植物大战僵尸射击版(可在安卓手机上玩,文末附下载链接)
  • 活动报名丨实时互动AI 开发者年度聚会!RTE Open Day@RTE2024,10.25/26北京
  • IOS APP初体验-第1课:如何在Mac中真机调试
  • |动漫爬取|001_djangodjango基于Spark的国漫推荐系统的设计与实现2024_tpd6q1o4
  • onnx和tensorrt使用过程中的一些代码梯子
  • 单链表算法题(一)(超详细版)