From 34fccd457a47bab88bf3eda411140d184e2e0913 Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Sun, 26 Jan 2025 14:12:49 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9120=E5=9B=9E=E5=88=B060?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs index a1932fbd..04c8764b 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs @@ -47,7 +47,7 @@ public class UMAME : MonoBehaviour, IEmuCore //设为60帧 - Application.targetFrameRate = 120; + Application.targetFrameRate = 60; // 强制横屏 Screen.orientation = ScreenOrientation.LandscapeLeft; instance = this; From 7ed40210fdf37cea0364290727f039385dbb04c8 Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Sun, 26 Jan 2025 14:50:33 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=94=B6=E5=88=B0=E6=88=BF=E9=97=B4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=90=8E=E4=B8=8D=E5=86=8D=E5=88=A4=E6=96=AD?= =?UTF-8?q?slot=E4=BF=A1=E6=81=AF=E6=98=AF=E5=90=A6=E6=94=B9=E5=8F=98,?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Script/AppMain/Manager/AppRoom.cs | 112 +++++++++--------- 1 file changed, 54 insertions(+), 58 deletions(-) diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs index c06d86f6..043a14d6 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs @@ -331,7 +331,6 @@ namespace AxibugEmuOnline.Client.Manager Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, newJoin); } - bool bChangeSlot = false; for (int i = 0; i < 4; i++) { var oldSlot = oldslotArr[i]; @@ -344,68 +343,65 @@ namespace AxibugEmuOnline.Client.Manager oldSlot.PlayerLocalJoyIdx != newSlot.PlayerLocalJoyIdx ) { - bChangeSlot = true; if (newSlot.PlayerUID > 0) { OverlayManager.PopTip($"[{newSlot.PlayerNickName}]使用:P{i}"); } } - } - - if (bChangeSlot) - { - Eventer.Instance.PostEvent(EEvent.OnRoomSlotDataChanged); - } - - //for (int i = 0; i < 4; i++) - //{ - // long OldPlayer = oldRoomPlayer[i]; - // long NewPlayer = newRoomPlayer[i]; - // if (OldPlayer == NewPlayer) - // continue; - - // //位置之前有人,但是离开了 - // if (OldPlayer > 0) - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); - // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); - // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; - // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); - // if (NewPlayer > 0)//而且害换了一个玩家 - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); - // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); - // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); - // } - // } - // else //之前没人 - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); - // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); - // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); - // } - - // //位置之前有人,但是离开了 - // if (OldPlayer > 0) - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); - // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); - // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; - // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); - // if (NewPlayer > 0)//而且害换了一个玩家 - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); - // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); - // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); - // } - // } - // else //之前没人 - // { - // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); - // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); - // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); - // } - //} + } + + Eventer.Instance.PostEvent(EEvent.OnRoomSlotDataChanged); + + + //for (int i = 0; i < 4; i++) + //{ + // long OldPlayer = oldRoomPlayer[i]; + // long NewPlayer = newRoomPlayer[i]; + // if (OldPlayer == NewPlayer) + // continue; + + // //位置之前有人,但是离开了 + // if (OldPlayer > 0) + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); + // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); + // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; + // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); + // if (NewPlayer > 0)//而且害换了一个玩家 + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); + // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); + // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); + // } + // } + // else //之前没人 + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); + // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); + // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); + // } + + // //位置之前有人,但是离开了 + // if (OldPlayer > 0) + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer); + // UserDataBase oldplayer = App.user.GetUserByUid(OldPlayer); + // string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; + // OverlayManager.PopTip($"[{oldPlayName}]离开房间,手柄位:P{i}"); + // if (NewPlayer > 0)//而且害换了一个玩家 + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); + // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); + // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); + // } + // } + // else //之前没人 + // { + // Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer); + // mineRoomMiniInfo.GetPlayerNameByPlayerIdx((uint)i, out string PlayerName); + // OverlayManager.PopTip($"[{PlayerName}]进入房间,手柄位:P{i}"); + // } + //} } /// From 70fb6154eccf8e95fc8f0e963fdab4563ba43449 Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Sun, 26 Jan 2025 15:04:26 +0800 Subject: [PATCH 3/3] =?UTF-8?q?NetReplay=E5=A2=9E=E5=8A=A0FrameProfiler(?= =?UTF-8?q?=E6=9C=AA=E5=AE=9E=E8=A3=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Plugins/AxiReplay/FrameProfiler.cs | 55 +++++++++++++ .../Plugins/AxiReplay/FrameProfiler.cs.meta | 2 + .../Plugins/AxiReplay/InternalRingbuffer.cs | 78 +++++++++++++++++++ .../AxiReplay/InternalRingbuffer.cs.meta | 2 + .../Assets/Plugins/AxiReplay/NetReplay.cs | 13 +++- 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs create mode 100644 AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs.meta create mode 100644 AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs create mode 100644 AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs new file mode 100644 index 00000000..df242e06 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs @@ -0,0 +1,55 @@ +using System; +using System.Diagnostics; + +namespace AxiReplay +{ + public partial class FrameProfiler + { + private int m_headFrame; + private int m_cacheCount; + private int m_targetFrameRate; + private RingBuffer m_timePoints; + private double m_lastTime; + + private Stopwatch sw; + + public void InputHead(int headFrame) + { + m_headFrame = headFrame; + var currentTimeMs = GetCurrTime(); + + if (m_timePoints.Available() == 60) + CalcCacheCount(); + m_timePoints.Write(currentTimeMs - m_lastTime); + + m_lastTime = currentTimeMs; + } + public void Reset(int targetFrameRate = 60) + { + if (sw != null) sw.Stop(); + + sw = Stopwatch.StartNew(); + m_timePoints = new RingBuffer(targetFrameRate); + m_lastTime = 0; + m_targetFrameRate = targetFrameRate; + } + + void CalcCacheCount() + { + double deltaMax = 0; + while (m_timePoints.TryRead(out double delta)) + { + deltaMax = Math.Max(deltaMax, delta); + } + + int minCacheCount = (int)Math.Ceiling(deltaMax * m_targetFrameRate); + m_cacheCount = minCacheCount; + } + + double GetCurrTime() + { + if (sw == null) return 0; + return sw.Elapsed.TotalMilliseconds; + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs.meta new file mode 100644 index 00000000..9fc08cbb --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/FrameProfiler.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cfd4511a83ff0bf4ea7615b87e7d09aa \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs new file mode 100644 index 00000000..3e00b092 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs @@ -0,0 +1,78 @@ +using System.Threading; + +namespace AxiReplay +{ + public partial class FrameProfiler + { + internal class RingBuffer + { + private readonly T[] buffer; + private readonly int capacity; + private int writePos; + private int readPos; + private int count; + + public RingBuffer(int capacity) + { + this.capacity = capacity; + this.buffer = new T[capacity]; + this.writePos = 0; + this.readPos = 0; + this.count = 0; + } + + public void Write(T item) + { + int localWritePos; + int localReadPos; + + do + { + localWritePos = Volatile.Read(ref writePos); + localReadPos = Volatile.Read(ref readPos); + + int nextWritePos = (localWritePos + 1) % capacity; + + if (nextWritePos == localReadPos) + { + // 缓冲区已满,覆盖最旧的未读数据 + Interlocked.CompareExchange(ref readPos, (localReadPos + 1) % capacity, localReadPos); + } + } + while (Interlocked.CompareExchange(ref writePos, (localWritePos + 1) % capacity, localWritePos) != localWritePos); + + buffer[localWritePos] = item; + Interlocked.Increment(ref count); + } + + public bool TryRead(out T item) + { + item = default(T); + + int localReadPos; + int localWritePos; + + do + { + localReadPos = Volatile.Read(ref readPos); + localWritePos = Volatile.Read(ref writePos); + + if (localReadPos == localWritePos) + { + return false; // 缓冲区为空 + } + } + while (Interlocked.CompareExchange(ref readPos, (localReadPos + 1) % capacity, localReadPos) != localReadPos); + + item = buffer[localReadPos]; + Interlocked.Decrement(ref count); + return true; + } + + public int Available() + { + return Volatile.Read(ref count); + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs.meta new file mode 100644 index 00000000..a4c26ff5 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/InternalRingbuffer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b17d83b69bd47094594c32fcff9715f4 \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs index 6076318f..cdba7015 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs @@ -34,6 +34,8 @@ namespace AxiReplay /// ReplayStep mNextReplay; + FrameProfiler frameProfiler = new FrameProfiler(); + bool bNetInit = false; public NetReplay() { @@ -45,6 +47,8 @@ namespace AxiReplay mCurrReplay = default(ReplayStep); mCurrReplay.FrameStartID = int.MinValue; bNetInit = false; + + frameProfiler.Reset(); } public void InData(ReplayStep inputData, int ServerFrameIdx, uint ServerForwardCount) { @@ -57,7 +61,10 @@ namespace AxiReplay bNetInit = true; mNextReplay = mNetReplayQueue.Dequeue(); } + + frameProfiler.InputHead(inputData.FrameStartID); } + public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff) { if (!bNetInit) @@ -93,13 +100,15 @@ namespace AxiReplay { bool result; inputDiff = false; + + //if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0) if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= mRemoteForwardCount) - { + { //当前帧追加 mCurrClientFrameIdx = targetFrame; ulong oldInput = mCurrReplay.InPut; - mCurrReplay = mNextReplay; + mCurrReplay = mNextReplay; if (oldInput != mCurrReplay.InPut) inputDiff = true; mNextReplay = mNetReplayQueue.Dequeue();