mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交Unity 联机Pro
This commit is contained in:
268
JNFrame2/Assets/JNGame/Sync/App/Frame/JNSyncFrameService.cs
Normal file
268
JNFrame2/Assets/JNGame/Sync/App/Frame/JNSyncFrameService.cs
Normal file
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using JNGame.Sync.Frame.Service;
|
||||
using JNGame.Sync.System.View;
|
||||
using UnityEngine;
|
||||
|
||||
namespace JNGame.Sync.Frame
|
||||
{
|
||||
public abstract class JNSyncFrameService : JNSyncDefaultService
|
||||
{
|
||||
|
||||
public override int DeltaTime => _nSyncTime / _nDivideFrame;
|
||||
|
||||
//同步时间 (和服务器保持一致)
|
||||
private int _nSyncTime = 67;
|
||||
public int NSyncTime => _nSyncTime;
|
||||
//大于多少帧进行追帧
|
||||
private int _nMaxFrameBan = 4;
|
||||
public int NMaxFrameBan => _nMaxFrameBan;
|
||||
//大于多少帧进行快速追帧
|
||||
private int _nMaxFrameLoopBan = 20;
|
||||
public int NMaxFrameLoopBan => _nMaxFrameLoopBan;
|
||||
//将服务器帧数进行平分
|
||||
private int _nDivideFrame = 2;
|
||||
public int NDivideFrame => _nDivideFrame;
|
||||
|
||||
//本地帧数
|
||||
private int _nLocalFrame = -1;
|
||||
public int NLocalFrame => _nLocalFrame;
|
||||
|
||||
|
||||
//帧队列
|
||||
private Queue<JNFrameInfo> _nFrameQueue = new();
|
||||
public Queue<JNFrameInfo> NFrameQueue => _nFrameQueue;
|
||||
//暂存帧列表
|
||||
private Dictionary<int,JNFrameInfo> _nFrameTempQueue = new();
|
||||
|
||||
//是否请求后台数据
|
||||
private bool _isRequestServerData = false;
|
||||
|
||||
//帧更新
|
||||
int dtTotal = 0;
|
||||
//输入更新
|
||||
int dtInputTotal = 0;
|
||||
|
||||
//是否开始同步
|
||||
private bool _isStart = false;
|
||||
public bool IsStart => _isStart;
|
||||
|
||||
//是否在追帧
|
||||
private bool _isLoop = false;
|
||||
public bool IsLoop => _isLoop;
|
||||
|
||||
protected JNSyncFrameService() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_isStart = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视图帧更新
|
||||
/// </summary>
|
||||
public override void Execute()
|
||||
{
|
||||
#if (!ENTITAS_DISABLE_VISUAL_DEBUGGING && UNITY_EDITOR)
|
||||
if (paused) return;
|
||||
#endif
|
||||
if (!IsStart) return;
|
||||
base.Execute();
|
||||
int deltaTime = (int)(Time.deltaTime * 1000f);
|
||||
dtTotal += deltaTime;
|
||||
dtInputTotal += deltaTime;
|
||||
|
||||
try
|
||||
{
|
||||
int nSyncTime = this.DyTime();
|
||||
|
||||
|
||||
if (nSyncTime > 0)
|
||||
{
|
||||
|
||||
this._isLoop = false;
|
||||
|
||||
if (dtTotal > nSyncTime && _nFrameQueue.Count > 0)
|
||||
{
|
||||
this.OnRunSimulate();
|
||||
dtTotal -= nSyncTime;
|
||||
}
|
||||
|
||||
if (_nFrameQueue.Count <= 0)
|
||||
{
|
||||
dtTotal = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._isLoop = true;
|
||||
//追帧运行 保持前端 15 帧 刷新
|
||||
long endTime = (new DateTimeOffset(DateTime.UtcNow)).ToUnixTimeMilliseconds() + 100;
|
||||
while (this.DyTime() == 0 && ((new DateTimeOffset(DateTime.UtcNow)).ToUnixTimeMilliseconds()) < endTime)
|
||||
{
|
||||
this.OnRunSimulate();
|
||||
}
|
||||
dtTotal = 0;
|
||||
}
|
||||
|
||||
|
||||
//更新输入
|
||||
if (dtInputTotal > (_nSyncTime / _nDivideFrame))
|
||||
{
|
||||
dtInputTotal = 0;
|
||||
OnRunInput();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e.Message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行输入
|
||||
/// </summary>
|
||||
public void OnRunInput()
|
||||
{
|
||||
var inputs = GetInputs();
|
||||
if (inputs.Inputs.Count > 0)
|
||||
{
|
||||
OnSendInput(inputs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自适应间隔时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int DyTime(){
|
||||
int dt = this._nSyncTime / this._nDivideFrame;
|
||||
int loop = dt;
|
||||
// return dt;
|
||||
|
||||
//大于nMaxFrameBan 进行 追帧
|
||||
if(this._nFrameQueue.Count > this._nMaxFrameBan) {
|
||||
|
||||
//计算超过的帧数
|
||||
int exceed = this._nFrameQueue.Count - this._nMaxFrameBan;
|
||||
int most = this._nMaxFrameLoopBan - this._nMaxFrameBan;
|
||||
int ldt = ((most - exceed) / most) * dt;
|
||||
|
||||
//自适应追帧算法
|
||||
if(exceed <= this._nMaxFrameLoopBan){
|
||||
loop = ldt;
|
||||
}else{
|
||||
loop = 0;
|
||||
}
|
||||
}else{
|
||||
loop = dt;
|
||||
}
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接受帧数
|
||||
/// </summary>
|
||||
public void AddFrame(JNFrameInfo frame,bool isLatestData = true)
|
||||
{
|
||||
|
||||
//我需要的下一帧
|
||||
int index = _nLocalFrame + 1;
|
||||
|
||||
//判断接受的帧是否下一帧 如果不是则加入未列入
|
||||
if (frame.Index != index){
|
||||
|
||||
_nFrameTempQueue.TryAdd(frame.Index,frame);
|
||||
|
||||
//在未列入中拿到需要的帧
|
||||
JNFrameInfo tamp = null;
|
||||
|
||||
if ((tamp = _nFrameTempQueue.GetValueOrDefault(index,null)) == null)
|
||||
{
|
||||
|
||||
var that = this;
|
||||
|
||||
//如果没有则向服务器请求我需要的帧数
|
||||
if (!that._isRequestServerData)
|
||||
{
|
||||
|
||||
that._isRequestServerData = true;
|
||||
|
||||
//请求
|
||||
that.OnServerData(this._nLocalFrame, 0).ContinueWith(infos =>
|
||||
{
|
||||
foreach (var frameInfo in infos.Frames)
|
||||
{
|
||||
if(frameInfo.Index >= this._nLocalFrame)
|
||||
that.AddFrame(frameInfo,false);
|
||||
}
|
||||
that._isRequestServerData = false;
|
||||
}).Forget();
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果有则覆盖
|
||||
frame = tamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//删除临时帧
|
||||
_nFrameTempQueue.Remove(frame.Index);
|
||||
|
||||
_nLocalFrame = index;
|
||||
|
||||
//分帧插入
|
||||
_nFrameQueue.Enqueue(frame);
|
||||
for (var i = 0; i < _nDivideFrame - 1; i++) {
|
||||
_nFrameQueue.Enqueue(new JNFrameInfo());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取输入
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected abstract JNFrameInputs GetInputs();
|
||||
|
||||
/// <summary>
|
||||
/// 运行帧
|
||||
/// </summary>
|
||||
protected virtual void OnRunSimulate()
|
||||
{
|
||||
Debug.Log("Run OnRunSimulate");
|
||||
if (!(NFrameQueue.TryDequeue(out var frame))) return;
|
||||
Simulate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送帧数据
|
||||
/// </summary>
|
||||
/// <param name="inputs"></param>
|
||||
protected abstract void OnSendInput(JNFrameInputs inputs);
|
||||
|
||||
/// <summary>
|
||||
/// 获取帧数据
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract UniTask<JNFrameInfos> OnServerData(int start,int end);
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d71e08d3cee3430f9d66f639dde67f0e
|
||||
timeCreated: 1721613418
|
Reference in New Issue
Block a user