Unity NTPComponent应用, 实现一个无后端高效获取网络时间的组件

无后端高效获取网络时间的组件

  • 废话不多说,直接上源码
  • m_NowSerivceTime 一个基于你发行游戏地区的时间偏移, 比如北京时区就是 8, 巴西就是-3,美国就是-5
  • using Newtonsoft.Json; 如果这里报错, 就说明项目没有 NewtonsoftJson插件, 没关系,这里你改成Unity内置的就行
  • 总之就一句, 没有必要就直接使用NTPComponent.m_NowUtc, 有时区要求就用 NTPComponent.m_NowSerivceTime, 总之,优势在我!
  • 原理, 这块没必要看,如果有同学有兴趣,可以继续看看

废话不多说,直接上源码

直接新建一个脚本 NTPComponent.cs
将脚本Copy到你的项目,拖入场景节点上
获取UTC时间 NTPComponent.m_NowUtc


using UnityEngine;
using System;
using System.Collections;
using UnityEngine.Networking;
using Newtonsoft.Json;
using System.Globalization;namespace GameContent
{/// <summary>/// 启动游戏后,将所有地址列表遍历/// </summary>[DisallowMultipleComponent]public class NTPComponent : MonoBehaviour{/// <summary>/// 网络时间是否生效中/// </summary>public static bool m_IsValid { get; private set; } = true;/// <summary>/// 当前Utc时间/// </summary>public static DateTime m_NowUtc{get{return m_NowUtcServerDate.AddSeconds( ( int ) ( Time.unscaledTime - m_ServerTimePoint ) );}private set{m_NowUtcServerDate = value;}}/// <summary>/// 当前服务器时间/// </summary>public static DateTime m_NowSerivceTime{get{return m_NowUtc.AddHours( GlobalConfig.TIME_ZONE_OFFSET );}}/// <summary>/// 服务器标记时间对象/// </summary>private static DateTime m_NowUtcServerDate;/// <summary>/// 拉取服务器的标记时间尺/// </summary>private static float m_ServerTimePoint = 0f;/// <summary>/// 是否已经成功拉取到服务器时间/// </summary>private bool m_Inited = false;private void Awake( ){m_NowUtc = DateTime.UtcNow;m_ServerTimePoint = Time.unscaledTime;DontDestroyOnLoad( gameObject );}private void Start( ){
#if !SANDBOX_MODEStartCoroutine( GetNetTimeFromWorldTimeApi() );StartCoroutine( GetNetTimeFromTimeIOApi() );StartCoroutine( GetNetTimeFromGoogleApi() );#elseLog.Green( $"当前是沙盒环境,你可以更改时间 {DateTime.Now}" );
#endif}#region WebApiIEnumerator GetApi( string api, Action<string> callback ){using ( var request = UnityWebRequest.Get( "https://worldtimeapi.org/api/timezone/Etc/UTC" ) ){yield return request.SendWebRequest();try{if ( request.result == UnityWebRequest.Result.Success ){callback( request.downloadHandler.text );}//else//{//    Debug.LogError( $"Failed to fetch server time: {request.error}" );//}}catch ( Exception e ){//不处理}}}struct WorldTimeData{public string datetime;public string timezone;public string utc_offset;}struct TimeIOData{public int year;public int month;public int day;public int hour;public int minute;public int seconds;public string dateTime;public string timeZone;public string dayOfWeek;public bool dstActive;}IEnumerator GetNetTimeFromWorldTimeApi( ){string result = string.Empty;yield return GetApi( "https://worldtimeapi.org/api/timezone/Etc/UTC", _ => result = _ );if ( !string.IsNullOrEmpty( result ) ){var data = JsonConvert.DeserializeObject<WorldTimeData>( result );Debug.Log( $"World Time: {data.datetime}" );if ( TryParseUTCString( data.datetime, out var utcNow ) && utcNow != DateTime.MinValue ){OnPullServerTimeOK( utcNow );}}}IEnumerator GetNetTimeFromTimeIOApi( ){string result = string.Empty;yield return GetApi( "https://timeapi.io/api/Time/current/zone?timeZone=UTC", _ => result = _ );if ( !string.IsNullOrEmpty( result ) ){var data = JsonConvert.DeserializeObject<TimeIOData>( result );Debug.Log( $"Time IO API: {data.dateTime}" );if ( TryParseUTCString( data.dateTime, out var utcNow ) && utcNow != DateTime.MinValue ){OnPullServerTimeOK( utcNow );}}}IEnumerator GetNetTimeFromGoogleApi( ){using ( var request = UnityWebRequest.Get( "https://www.google.com" ) ){yield return request.SendWebRequest();try{if ( request.result == UnityWebRequest.Result.Success ){if ( request.GetResponseHeader( "Date" ) != null ){string serverDate = request.GetResponseHeader( "Date" );Debug.Log( $"Google Server Time: {serverDate}" );var utcDate = ParseServerDateToUTC( serverDate );if ( utcDate != DateTime.MinValue ){OnPullServerTimeOK( utcDate );}}}}catch ( Exception e ){//不处理}}}#endregion#region Common/// <summary>/// Parses a UTC time string into a DateTime object./// </summary>/// <param name="utcString">The UTC time string.</param>/// <returns>A DateTime object in UTC, or DateTime.MinValue if parsing fails.</returns>public static bool TryParseUTCString( string utcString, out DateTime utcNow ){try{// Attempt to parse the string with DateTime.ParseDateTime parsedDate = DateTime.Parse( utcString, null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal );utcNow = parsedDate;return true;}catch ( FormatException ){Debug.Log( "Failed to parse UTC time string." );utcNow = DateTime.MinValue;return false;}}/// <summary>/// Parses a server date string (from HTTP header) into a UTC DateTime object./// </summary>/// <param name="serverDate">The server date string in RFC1123 format.</param>/// <returns>A DateTime object in UTC.</returns>public static DateTime ParseServerDateToUTC( string serverDate ){try{// Use DateTime.ParseExact to parse RFC1123 formatDateTime parsedDate = DateTime.ParseExact(serverDate,"r", // "r" or "R" stands for RFC1123 patternCultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);return parsedDate;}catch ( FormatException ex ){Debug.Log( $"Error parsing server date: {ex.Message}" );return DateTime.MinValue; // Return MinValue to indicate failure}}/// <summary>/// 当服务器拉取到时间后调用, 锁定一次/// </summary>/// <param name="utcTime"></param>private void OnPullServerTimeOK( DateTime utcTime ){if ( m_Inited ) return;m_Inited = true;StopAllCoroutines();m_ServerTimePoint = Time.unscaledTime;m_NowUtc = utcTime;Log.Green( $"获取服务器时间成功: {utcTime}" );}#endregion}
}

m_NowSerivceTime 一个基于你发行游戏地区的时间偏移, 比如北京时区就是 8, 巴西就是-3,美国就是-5

具体根项目运营确认

//这个就是一个全局的定义,自己写一个类或者 写死一个也行
GlobalConfig.TIME_ZONE_OFFSET = 8;

using Newtonsoft.Json; 如果这里报错, 就说明项目没有 NewtonsoftJson插件, 没关系,这里你改成Unity内置的就行

改成 JsonUtility.FromJson( result ); //Unity 内置的Json库
在这里插入图片描述

总之就一句, 没有必要就直接使用NTPComponent.m_NowUtc, 有时区要求就用 NTPComponent.m_NowSerivceTime, 总之,优势在我!

在这里插入图片描述

原理, 这块没必要看,如果有同学有兴趣,可以继续看看

真实时间由两个部分组成, 一个是请求一次得到的 真实云UTC时间, 另外一个是当前游戏的秒数TimePoint
通过 基数 + 秒数偏移。 能在游戏内断网的时候有效获取到真实的云时间
需要注意的是,在游戏启动的时候,你得确保用户是联网的
当然,如果你的游戏是纯单机的,也不会报错,因为在Awake的时候默认用的是本地的TimePoint,如果你用纯单机也就不需要考虑真实的时间, 这里是能保证你的项目能在任何条件下安全的跑起来

在游戏启动的时候获取一个 UTC时间 基数
然后记录当前的游戏运行时间 Time.unscaledTime
获取当前真实的UTC时间时 => UTC时间 基数 + ( 当前游戏运行时间 - 记录时间 ) 秒数偏移

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/64234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为ensp中nat server 公网访问内网服务器

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月15日17点30分 &#x1f4af;趣站推荐&#x1f4af; 前些天发现了一个巨牛的&#x1f916;人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

R语言学习笔记-1

1. 基础操作和函数 清空环境&#xff1a;rm(list ls()) 用于清空当前的R环境。 打印输出&#xff1a;print("Hello, world") 用于输出文本到控制台。 查看已安装包和加载包&#xff1a; search()&#xff1a;查看当前加载的包。install.packages("package_na…

二、FIFO缓存

FIFO缓存 1.FIFO缓存介绍2.FIFO缓存实现3.FIFO缓存总结 1.FIFO缓存介绍 FIFO&#xff08;First-In-First-Out&#xff09;缓存 是一种简单的缓存淘汰策略&#xff0c;它基于先进先出的原则来管理数据。当缓存达到容量限制并需要淘汰元素时&#xff0c;最先进入缓存的元素会被移…

Spring Cloud与Spring Cloud Alibaba:全面解析与核心要点

Spring Cloud与Spring Cloud Alibaba&#xff1a;全面解析与核心要点 一、引言 在当今的分布式系统开发领域&#xff0c;Spring Cloud和Spring Cloud Alibaba都是极为重要的框架。它们为构建大规模、高可用、分布式的应用系统提供了丰富的工具和组件。本文将深入探讨Spring C…

账号下的用户列表表格分析

好的&#xff0c;这是您提供的 el-table 组件中所有列的字段信息&#xff0c;以表格形式展示&#xff1a; 列标题 (label)字段属性 (prop)对齐方式 (align)宽度 (width)是否可排序 (sortable)说明IDidcenter100否管理员的唯一标识符头像avatarcenter90否管理员的头像 URL 或路…

GPT-SoVITS语音合成模型部署及使用

1、概述 GPT-SoVITS是一款开源的语音合成模型&#xff0c;结合了深度学习和声学技术&#xff0c;能够实现高质量的语音生成。其独特之处在于支持使用参考音频进行零样本语音合成&#xff0c;即使没有直接的训练数据&#xff0c;模型仍能生成相似风格的语音。用户可以通过微调模…

TongWe7.0-东方通TongWeb控制台无法访问 排查

问题描述&#xff1a;无法访问TongWeb的控制台 逐项排查&#xff1a; 1、控制台访问地址是否正确&#xff1a;http://IP:9060/console #IP是服务器的实际IP地址 2、确认TongWeb进程是否存在&#xff0c;执行命令&#xff1a;ps -ef|grep tongweb 3、确认TongWeb服务启动…

研发文档管理系统:国内外9大选择比较

文章主要对比了9款国内外研发文档管理系统&#xff1a;1.PingCode&#xff1b; 2. Worktile&#xff1b; 3. 飞书&#xff1b; 4. 石墨文档&#xff1b; 5. 腾讯文档&#xff1b; 6. 蓝湖&#xff1b; 7. Confluence&#xff1b; 8. Notion&#xff1b; 9. Slab。 在企业研发过…

【ABAP SAP】开发-BUG修补记录_采购申请打印时品名规格品牌为空

项目场景&#xff1a; TCODE:自开发程序ZMMF004 采购申请打印 问题描述 ZMMF004打印的时候&#xff0c;有的采购申请的品名、规格、品牌为空 原因分析&#xff1a; 1、首先我通过写SQL语句查底表来看这几条采购申请本身有无品名、规格、品牌 SQL语句如下&#xff0c;只需修…

Ubuntu 20.04 24.04 双网卡 Bond 配置指南

前言&#xff1a;在现代服务器管理中&#xff0c;网络的稳定性和可靠性至关重要。为了提高网络的冗余性和负载能力&#xff0c;我们经常需要配置多个网络接口以实现链路聚合或故障转移。Ubuntu系统自17.10版本起&#xff0c;引入了Netplan作为新的网络配置抽象化工具&#xff0…

OCR实践—PaddleOCR

有个项目需求&#xff0c;对拍摄的问卷图片&#xff0c;进行自动得分统计【得分是在相应的分数下面打对号】&#xff0c;输出到excel文件 原始问卷文件见下图&#xff0c;真实的图片因使用手机拍摄的图片&#xff0c;存在一定的畸变&#xff0c; 技术调研 传统方法 传统方法…

ubuntu+ros新手笔记(五):初探anaconda+cuda+pytorch

深度学习三件套&#xff1a;初探anacondacudapytorch 系统ubuntu22.04 ros2 humble 1.初探anaconda 1.1 安装 安装过程参照【详细】Ubuntu 下安装 Anaconda 1.2 创建和删除环境 创建新环境 conda create -n your_env_name pythonx.x比如我创建了一个名为“py312“的环境…

【测试】Pytest

建议关注、收藏&#xff01; 目录 功能pytest 自动化测试工具。 功能 单元测试&#xff1a;用于验证代码的最小功能单元&#xff08;如函数、方法&#xff09;的正确性。 简单的语法&#xff1a;不需要继承特定类或使用复杂的结构。断言语句简化。 自动发现测试&#xff1a;P…

Unity性能优化---使用SpriteAtlas创建图集进行批次优化

在日常游戏开发中&#xff0c;UI是不可缺少的模块&#xff0c;而在UI中又使用着大量的图片&#xff0c;特别是2D游戏还有很多精灵图片存在&#xff0c;如果不加以处理&#xff0c;会导致很高的Batches&#xff0c;影响性能。 比如如下的例子&#xff1a; Batches是9&#xff0…

环境和工程搭建

1.案例介绍 1.1 需求 实现⼀个电商平台 该如何实现呢? 如果把这些功能全部写在⼀个服务⾥, 这个服务将是巨⼤的. 巨多的会员, 巨⼤的流量, 微服务架构是最好的选择. 微服务应⽤开发的第⼀步, 就是服务拆分. 拆分后才能进⾏"各⾃开发" 1.2 服务拆分 拆分原则 …

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

操作系统课后习题2.2节

操作系统课后习题2.2节 第1题 CPU的效率指的是CPU的执行速度&#xff0c;这个是由CPU的设计和它的硬件来决定的&#xff0c;具体的调度算法是不能提高CPU的效率的&#xff1b; 第3题 互斥性&#xff1a; 指的是进程之间的同步互斥关系&#xff0c;进程是一个动态的过程&#…

二叉搜索树 平衡树(c嘎嘎版)

定义: 二叉搜索树是一种二叉树的树形数据结构,其定义如下: 空树是二叉搜索树。 若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。 若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。 二叉搜索树的左右子树均为…

Everything搜索实现

最近编写NTFS文件实时搜索工具, 类似 Everything 这样, 速度快还小巧, 于是花了约3周进行研究, 总结下学习过程中一些经验 实现分3部分完成 一. 解析NTFS 主文件表(MFT) 这一步是获取文件数据的唯一迅速且可靠的来源 NTFS_MFT_Parse.h #pragma once #include "NTFS_Bas…

23.DDD与微服务

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与微服务的关系1. DDD可以用微服务实现&#xff0c;也可以不用微服务实现2. DDD是微服务拆分的必须参考项之一3. 微服务架构…