307 lines
9.6 KiB
C#
Raw Normal View History

2024-01-26 19:15:07 +08:00
using System;
using System.Collections.Generic;
2024-01-29 19:07:52 +08:00
using System.Reflection;
2024-01-26 19:15:07 +08:00
using System.Threading.Tasks;
2024-01-29 02:28:42 +08:00
using Cysharp.Threading.Tasks;
using Plugins.JNGame.Sync.Frame.game;
2024-01-26 19:15:07 +08:00
using Plugins.JNGame.System;
using Plugins.JNGame.Util;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Plugins.JNGame.Sync.Frame
{
2024-01-29 19:07:52 +08:00
//帧同步 通知
public interface JNSyncFrameEvent
{
static string CLEAR = "JNSyncFrameEvent_CLEAR";
static string CREATE = "JNSyncFrameEvent_CREATE";
static string FRAME = "JNSyncFrameEvent_FRAME";
}
2024-01-26 19:15:07 +08:00
public abstract class JNSyncFrame : SystemBase
{
//同步时间 (和服务器保持一致)
private int _nSyncTime = 67;
//大于多少帧进行追帧
2024-01-30 19:22:27 +08:00
private int _nMaxFrameBan = 4;
2024-01-26 19:15:07 +08:00
//大于多少帧进行快速追帧
private int _nMaxFrameLoopBan = 18;
//将服务器帧数进行平分
private int _nDivideFrame = 3;
//帧队列
2024-01-29 02:28:42 +08:00
private Queue<JNFrameInfo> _nFrameQueue = new();
2024-01-26 19:15:07 +08:00
2024-01-30 19:22:27 +08:00
//本地已执行帧数
private int _nLocalRunFrame = 0;
2024-01-26 19:15:07 +08:00
//本地帧数
private int _nLocalFrame = 0;
2024-01-30 19:22:27 +08:00
//服务器的帧
private int _nServerFrame = 0;
public int NLocalRunFrame => _nLocalRunFrame;
public int NLocalFrame => _nLocalFrame;
public int NServerFrame => _nServerFrame;
2024-01-26 19:15:07 +08:00
//暂存帧列表
private Dictionary<int,JNFrameInfo> _nFrameTempQueue = new();
2024-01-29 02:28:42 +08:00
//需要同步的Actor
2024-01-29 19:07:52 +08:00
private List<IJNSyncFrameComponent> _nSyncActors = new();
2024-01-29 02:28:42 +08:00
2024-01-26 19:15:07 +08:00
//ID 每添加 JNSyncFrameComponent + 1
public Func<int> nSyncID = RandomUtil.Next(0);
//随机数
2024-01-30 19:22:27 +08:00
public Func<float> nRandom = RandomUtil.SyncRandom();
//随机数double
public Func<float,float,float> nRandomFloat = RandomUtil.SyncRandomFloat();
2024-01-26 19:15:07 +08:00
//随机数整数
2024-01-30 19:22:27 +08:00
public Func<int, int, int> nRandomInt = RandomUtil.SyncRandomInt();
2024-01-26 19:15:07 +08:00
//是否开始同步
Boolean _isStart = false;
2024-01-29 02:28:42 +08:00
//是否请求后台数据
private Boolean _isRequestServerData = false;
2024-01-30 19:22:27 +08:00
public bool IsRequestServerData => _isRequestServerData;
2024-01-26 19:15:07 +08:00
//帧更新
int dtTotal = 0;
//输入更新
int dtInputTotal = 0;
public override Task OnInit()
{
Physics.autoSimulation = false;
Physics.autoSyncTransforms = false;
2024-01-29 19:07:52 +08:00
this.OnReset();
2024-01-26 19:15:07 +08:00
return Task.CompletedTask;
}
2024-01-29 02:28:42 +08:00
//开始
2024-01-29 19:07:52 +08:00
public void OnStart(){
2024-01-29 02:28:42 +08:00
this._isStart = true;
}
2024-01-29 19:07:52 +08:00
2024-01-26 19:15:07 +08:00
//重置数据
2024-01-29 19:07:52 +08:00
public void OnReset()
2024-01-26 19:15:07 +08:00
{
2024-01-29 19:07:52 +08:00
EventDispatcher.Event.Dispatch(JNSyncFrameEvent.CLEAR);
2024-01-29 02:28:42 +08:00
this._isStart = false;
2024-01-26 19:15:07 +08:00
this.nSyncID = RandomUtil.Next(0);
2024-01-30 19:22:27 +08:00
this.nRandom = RandomUtil.SyncRandom();
this.nRandomFloat = RandomUtil.SyncRandomFloat();
this.nRandomInt = RandomUtil.SyncRandomInt();
2024-01-29 19:07:52 +08:00
this._nSyncActors = new();
this._nFrameQueue = new();
this._nFrameTempQueue = new();
this._nLocalFrame = 0;
2024-01-30 19:22:27 +08:00
this._nServerFrame = 0;
this._nLocalRunFrame = 0;
2024-01-29 19:07:52 +08:00
Physics.SyncTransforms();
EventDispatcher.Event.Dispatch(JNSyncFrameEvent.CREATE);
2024-01-26 19:15:07 +08:00
}
//更新同步
public void Update(int dt)
{
if(!_isStart) return;
dtTotal += dt;
dtInputTotal += dt;
int nSyncTime = this.DyTime();
if(nSyncTime > 0){
while(nSyncTime != 0 && this.dtTotal > nSyncTime){
this.onUpdate();
this.dtTotal -= nSyncTime;
nSyncTime = this.DyTime();
}
}else{
//追帧运行 保持前端 15 帧 刷新
2024-01-30 19:22:27 +08:00
long endTime = (new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds()) + 66;
while(this.DyTime() == 0 && (new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds()) < endTime){
2024-01-26 19:15:07 +08:00
this.onUpdate();
}
2024-01-30 19:22:27 +08:00
dtTotal = 0;
2024-01-26 19:15:07 +08:00
}
}
//运行帧
public void onUpdate()
{
2024-01-29 02:28:42 +08:00
if(!(_nFrameQueue.TryDequeue(out var frame))) return;
2024-01-30 19:22:27 +08:00
if(frame.Index != 0)
this._nLocalRunFrame = frame.Index;
2024-01-29 02:28:42 +08:00
int dt = this._nSyncTime / this._nDivideFrame;
2024-01-26 19:15:07 +08:00
2024-01-29 02:28:42 +08:00
//拆出输入
Dictionary<int, JNFrameInput> inputs = new();
foreach (var message in frame.Messages)
{
inputs.Add(message.NId,message);
}
//更新帧
this._nSyncActors.ForEach(child =>
{
2024-01-29 19:07:52 +08:00
MethodInfo OnSyncUpdate = child.GetType().GetMethod("OnSyncUpdate");
MethodInfo Decoder = child.GetType().GetMethod("Decoder");
2024-01-29 02:28:42 +08:00
if (inputs.ContainsKey(child.NID))
{
2024-01-29 19:07:52 +08:00
OnSyncUpdate.Invoke(child,new []{dt,frame,Decoder.Invoke(child,new object[]{ inputs[child.NID].Input.ToByteArray() })});
2024-01-29 02:28:42 +08:00
}
else
{
2024-01-29 19:07:52 +08:00
OnSyncUpdate.Invoke(child,new []{ dt,frame,(object)null });
2024-01-29 02:28:42 +08:00
}
});
//执行下一帧物理
Physics.Simulate((float)dt / 1000);
Physics.SyncTransforms();
2024-01-26 19:15:07 +08:00
}
//自适应间隔时间
2024-01-30 19:22:27 +08:00
public int DyTime(){
2024-01-26 19:15:07 +08:00
int dt = this._nSyncTime / this._nDivideFrame;
int loop = 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;
}
2024-01-30 19:22:27 +08:00
2024-01-26 19:15:07 +08:00
return loop;
}
/**
*
* @param frame
* @param isLatestData
*/
2024-01-29 02:28:42 +08:00
public void AddInput(JNFrameInfo frame,Boolean isLatestData = true)
{
if (!_isStart) return;
2024-01-26 19:15:07 +08:00
2024-01-30 19:22:27 +08:00
if(isLatestData)
{
this._nServerFrame = frame.Index;
// //如果推的帧小于本地帧 则 重开
// if(frame.Index < _nLocalFrame){
// OnReset();
// OnStart();
// return;
// }
2024-01-26 19:15:07 +08:00
}
//我需要的下一帧
int index = _nLocalFrame + 1;
//判断接受的帧是否下一帧 如果不是则加入未列入
if (frame.Index != index){
2024-01-29 02:28:42 +08:00
_nFrameTempQueue.TryAdd(frame.Index,frame);
2024-01-26 19:15:07 +08:00
//在未列入中拿到需要的帧
JNFrameInfo tamp = null;
2024-01-30 19:22:27 +08:00
if ((tamp = _nFrameTempQueue.GetValueOrDefault(index,null)) == null)
{
var that = this;
2024-01-26 19:15:07 +08:00
//如果没有则向服务器请求我需要的帧数
2024-01-30 19:22:27 +08:00
if (!that._isRequestServerData)
2024-01-29 02:28:42 +08:00
{
2024-01-30 19:22:27 +08:00
that._isRequestServerData = true;
2024-01-29 02:28:42 +08:00
//请求
2024-01-30 19:22:27 +08:00
that.OnServerData(this._nLocalFrame, 0).ContinueWith(infos =>
2024-01-29 02:28:42 +08:00
{
foreach (var frameInfo in infos.Frames)
{
2024-01-30 19:22:27 +08:00
if(frameInfo.Index >= this._nLocalFrame)
that.AddInput(frameInfo,false);
2024-01-29 02:28:42 +08:00
}
2024-01-30 19:22:27 +08:00
that._isRequestServerData = false;
2024-01-29 02:28:42 +08:00
}).Forget();
2024-01-30 19:22:27 +08:00
2024-01-29 02:28:42 +08:00
}
return;
2024-01-26 19:15:07 +08:00
}
else
{
//如果有则覆盖
frame = tamp;
}
}
//删除临时帧
_nFrameTempQueue.Remove(frame.Index);
_nLocalFrame = index;
//分帧插入
2024-01-29 02:28:42 +08:00
_nFrameQueue.Enqueue(frame);
for (var i = 0; i < this._nDivideFrame - 1; i++) {
_nFrameQueue.Enqueue(new JNFrameInfo());
2024-01-26 19:15:07 +08:00
}
}
2024-01-29 19:07:52 +08:00
//添加同步组件
public void AddSyncActor(IJNSyncFrameComponent sync){
if(!this._nSyncActors.Contains(sync)){
this._nSyncActors.Add(sync);
}
}
//销毁同步组件
public void DelSyncActor(IJNSyncFrameComponent sync){
this._nSyncActors.Remove(sync);
}
2024-01-26 19:15:07 +08:00
//发送帧数据
protected abstract void OnSendInput(JNFrameInputs inputs);
2024-01-29 02:28:42 +08:00
//获取帧数据
protected abstract UniTask<JNFrameInfos> OnServerData(int start,int end);
2024-01-26 19:15:07 +08:00
}
}