149 lines
4.7 KiB
C#
149 lines
4.7 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
/// <summary>
|
|
/// 北京时间管理器 - 获取一次后持续自增
|
|
/// </summary>
|
|
public class BeijingTimeManager : MonoSingleton<BeijingTimeManager>
|
|
{
|
|
[Header("时间状态")]
|
|
[SerializeField] private bool _isTimeSynced = false; // 是否已同步
|
|
[SerializeField] private DateTime _currentBeijingTime; // 当前北京时间
|
|
[SerializeField] private float _timeSinceLastSync; // 距离上次同步的秒数
|
|
|
|
// 公开属性供其他脚本访问
|
|
public DateTime CurrentBeijingTime
|
|
{
|
|
get
|
|
{
|
|
if (_isTimeSynced)
|
|
{
|
|
// 基准时间 + 流逝的时间
|
|
return _currentBeijingTime.AddSeconds(_timeSinceLastSync);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("时间尚未同步,返回本地时间");
|
|
return DateTime.Now.AddHours(8); // 降级为本地时间+8小时
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsTimeSynced => _isTimeSynced;
|
|
|
|
// 事件:当时间成功同步时触发
|
|
public event Action<DateTime> OnTimeSynced;
|
|
private void Start()
|
|
{
|
|
SyncBeijingTime();
|
|
}
|
|
private void Update()
|
|
{
|
|
if (_isTimeSynced)
|
|
{
|
|
// 持续累计时间
|
|
_timeSinceLastSync += Time.deltaTime;
|
|
|
|
// 可选:每隔一段时间(如5分钟)自动校准
|
|
if (_timeSinceLastSync > 300f) // 5分钟
|
|
{
|
|
StartCoroutine(AutoCalibrateTime());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 手动触发时间同步
|
|
/// </summary>
|
|
public void SyncBeijingTime()
|
|
{
|
|
StartCoroutine(FetchBeijingTime());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取北京时间(协程)
|
|
/// </summary>
|
|
private IEnumerator FetchBeijingTime()
|
|
{
|
|
string[] timeServers = new string[]
|
|
{
|
|
"http://www.beijing-time.org/time.asp",
|
|
"https://www.baidu.com",
|
|
"https://www.taobao.com",
|
|
|
|
};
|
|
|
|
DateTime beijingTime = DateTime.MinValue;
|
|
bool success = false;
|
|
|
|
foreach (string url in timeServers)
|
|
{
|
|
using (UnityEngine.Networking.UnityWebRequest request =
|
|
UnityEngine.Networking.UnityWebRequest.Get(url))
|
|
{
|
|
yield return request.SendWebRequest();
|
|
|
|
if (request.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
|
|
{
|
|
string dateHeader = request.GetResponseHeader("Date");
|
|
if (!string.IsNullOrEmpty(dateHeader))
|
|
{
|
|
try
|
|
{
|
|
// 解析GMT时间
|
|
DateTime gmtTime = DateTime.ParseExact(dateHeader,
|
|
"ddd, dd MMM yyyy HH:mm:ss 'GMT'",
|
|
System.Globalization.CultureInfo.InvariantCulture,
|
|
System.Globalization.DateTimeStyles.AssumeUniversal);
|
|
|
|
beijingTime = gmtTime.AddHours(8);
|
|
|
|
// 更新基准时间和计时器
|
|
_currentBeijingTime = beijingTime;
|
|
_timeSinceLastSync = 0f;
|
|
_isTimeSynced = true;
|
|
|
|
Debug.Log($"时间同步成功!北京时间:{beijingTime:yyyy-MM-dd HH:mm:ss}");
|
|
|
|
// 触发事件
|
|
OnTimeSynced?.Invoke(beijingTime);
|
|
|
|
success = true;
|
|
break;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogWarning($"解析失败:{e.Message}");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
Debug.LogError("所有时间服务器都失败了,使用本地时间作为备用");
|
|
_currentBeijingTime = DateTime.Now.AddHours(8);
|
|
_timeSinceLastSync = 0f;
|
|
_isTimeSynced = false; // 标记为未同步
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 自动校准(后台静默同步)
|
|
/// </summary>
|
|
private IEnumerator AutoCalibrateTime()
|
|
{
|
|
Debug.Log("开始自动校准时间...");
|
|
|
|
// 保存当前累计时间,用于计算校准时的差距
|
|
float oldElapsed = _timeSinceLastSync;
|
|
|
|
yield return StartCoroutine(FetchBeijingTime());
|
|
|
|
// 校准后可以计算误差
|
|
Debug.Log($"时间校准完成,误差:{_timeSinceLastSync - oldElapsed:F2}秒");
|
|
}
|
|
} |