From 3446dcd6f1bee2db158b68e523ecabe4c1d676d1 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Mon, 6 Apr 2026 12:13:39 +0800 Subject: [PATCH] cleanup unused script --- .../Scripts/Network/Defines/SystemMessage.cs | 11 - .../Network/Defines/SystemMessage.cs.meta | 11 - .../Network/NetworkTransport/ClientSession.cs | 64 ---- .../NetworkTransport/ClientSession.cs.meta | 11 - .../Network/NetworkTransport/Packet.cs | 58 ---- .../Network/NetworkTransport/Packet.cs.meta | 11 - .../NetworkTransport/ReliableUdpTransport.cs | 312 ------------------ .../ReliableUdpTransport.cs.meta | 11 - TODO.md | 22 +- 9 files changed, 11 insertions(+), 500 deletions(-) delete mode 100644 Assets/Scripts/Network/Defines/SystemMessage.cs delete mode 100644 Assets/Scripts/Network/Defines/SystemMessage.cs.meta delete mode 100644 Assets/Scripts/Network/NetworkTransport/ClientSession.cs delete mode 100644 Assets/Scripts/Network/NetworkTransport/ClientSession.cs.meta delete mode 100644 Assets/Scripts/Network/NetworkTransport/Packet.cs delete mode 100644 Assets/Scripts/Network/NetworkTransport/Packet.cs.meta delete mode 100644 Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs delete mode 100644 Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs.meta diff --git a/Assets/Scripts/Network/Defines/SystemMessage.cs b/Assets/Scripts/Network/Defines/SystemMessage.cs deleted file mode 100644 index 38456d3..0000000 --- a/Assets/Scripts/Network/Defines/SystemMessage.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Network.Defines -{ - public class SystemMessage - { - public string Content { get; set; } - public DateTime Timestamp { get; set; } = DateTime.Now; - public string Level { get; set; } = "info"; // "info", "warning", "error" - } -} \ No newline at end of file diff --git a/Assets/Scripts/Network/Defines/SystemMessage.cs.meta b/Assets/Scripts/Network/Defines/SystemMessage.cs.meta deleted file mode 100644 index 58ba8da..0000000 --- a/Assets/Scripts/Network/Defines/SystemMessage.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9a9d4f06e72ce954598ae990364ac8ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Network/NetworkTransport/ClientSession.cs b/Assets/Scripts/Network/NetworkTransport/ClientSession.cs deleted file mode 100644 index 8375d81..0000000 --- a/Assets/Scripts/Network/NetworkTransport/ClientSession.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Net; - -namespace Network.NetworkTransport -{ - public class ClientSession - { - public IPEndPoint EndPoint { get; } - public DateTime LastActivity { get; private set; } - - public uint SendSequenceNumber { get; private set; } = 0; - - //TODO: 数据结构——ConcurrentDictionary - public ConcurrentDictionary PendingAcks { get; } = - new ConcurrentDictionary(); - - public uint ExpectedReceiveSequence { get; private set; } = 0; - private HashSet _receivedSequences { get; } = new HashSet(); - - private readonly object _lockObj = new object(); - - public ClientSession(IPEndPoint endPoint) - { - EndPoint = endPoint; - LastActivity = DateTime.Now; - } - - public uint GetNextSendSequence() - { - lock (_lockObj) - { - return SendSequenceNumber++; - } - } - - public bool TryProcessReceiveSequence(uint sequenceNumber, out bool shouldDeliver) - { - lock (_lockObj) - { - LastActivity = DateTime.Now; - - if (sequenceNumber == ExpectedReceiveSequence) - { - ExpectedReceiveSequence++; - _receivedSequences.Add(sequenceNumber); - shouldDeliver = true; - return true; - } - else if (sequenceNumber < ExpectedReceiveSequence) - { - shouldDeliver = false; - return _receivedSequences.Contains(sequenceNumber); - } - else - { - shouldDeliver = false; - return false; - } - } - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Network/NetworkTransport/ClientSession.cs.meta b/Assets/Scripts/Network/NetworkTransport/ClientSession.cs.meta deleted file mode 100644 index 38fb162..0000000 --- a/Assets/Scripts/Network/NetworkTransport/ClientSession.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c007e0986e972b14cb4b4ab2151459c3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Network/NetworkTransport/Packet.cs b/Assets/Scripts/Network/NetworkTransport/Packet.cs deleted file mode 100644 index f7bc8f8..0000000 --- a/Assets/Scripts/Network/NetworkTransport/Packet.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Linq; - -namespace Network.NetworkTransport -{ - public enum PacketType : byte - { - Data = 1, - Ack = 2, - } - - public struct Packet - { - public PacketType Type; - public uint SequenceNumber; - public byte[] Data; - - public byte[] ToBytes() - { - var result = new byte[1 + 4 + Data.Length]; - result[0] = (byte)Type; - BitConverter.GetBytes(SequenceNumber).CopyTo(result, 1); - Data.CopyTo(result, 5); - return result; - } - - public static Packet FromBytes(byte[] data) - { - return new Packet - { - Type = (PacketType)data[0], - SequenceNumber = BitConverter.ToUInt32(data, 1), - //TODO: 结构体——ArraySegment - Data = new ArraySegment(data, 5, data.Length - 5).ToArray() - }; - } - - public static Packet CreateDataPacket(uint seqNum, byte[] data) - { - return new Packet - { - Type = PacketType.Data, - SequenceNumber = seqNum, - Data = data - }; - } - - public static Packet CreateAckPacket(uint seqNum) - { - return new Packet - { - Type = PacketType.Ack, - SequenceNumber = seqNum, - Data = Array.Empty() - }; - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Network/NetworkTransport/Packet.cs.meta b/Assets/Scripts/Network/NetworkTransport/Packet.cs.meta deleted file mode 100644 index e25a990..0000000 --- a/Assets/Scripts/Network/NetworkTransport/Packet.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a16c0628d84e6274bbe164e0e57533e4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs b/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs deleted file mode 100644 index bcd9a3a..0000000 --- a/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace Network.NetworkTransport -{ - internal sealed class LegacyUdpTransportAdapter : ITransport, IPeerSessionTransport - { - private readonly UdpClient _client; - private readonly IPEndPoint? _defaultRemoteEndPoint; - private readonly bool _isServer; - - private readonly ConcurrentDictionary _sessions = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _resentPacketTimes = new ConcurrentDictionary(); - private readonly Timer _retransmitTimer; - private readonly Timer _cleanupTimer; - - //TODO: volatile 关键字 - private volatile bool _isRunning; - - // 配置参数 - private const int RetransmitTimeoutMs = 1000; - private const int SessionTimeoutMs = 30000; - private const int MaxRetransmitAttempts = 5; - - public event Action? OnReceive; - - // 构造函数——服务端模式 - public LegacyUdpTransportAdapter(int listenPort) - { - _client = new UdpClient(listenPort); - _isServer = true; - _retransmitTimer = new Timer(CheckRetransmit, null, 100, 100); - _cleanupTimer = new Timer(CleanupSessions, null, 5000, 5000); - Console.WriteLine($"[Transport] 服务端模式,监听端口: {listenPort}"); - } - - // 构造函数——客户端模式 - public LegacyUdpTransportAdapter(string serverIP, int serverPort) - { - _client = new UdpClient(0); - _defaultRemoteEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), serverPort); - - _isServer = false; - _retransmitTimer = new Timer(CheckRetransmit, null, 100, 100); - _cleanupTimer = new Timer(CleanupSessions, null, 5000, 5000); - Console.WriteLine($"[Transport] 客户端模式,目标: {_defaultRemoteEndPoint}"); - } - - public async Task StartAsync() - { - _sessions.Clear(); - - _isRunning = true; - Console.WriteLine("[Transport] 传输层启动"); - - // 开始接收数据 - _ = Task.Run(ReceiveLoop); - await Task.Delay(100); // 给接收循环一点启动时间 - } - - public void Stop() - { - _isRunning = false; - _retransmitTimer.Dispose(); - _cleanupTimer.Dispose(); - _client.Close(); - _sessions.Clear(); - Console.WriteLine("[Transport] 传输层停止"); - } - - public void Send(byte[] data) - { - if (!_isServer && _defaultRemoteEndPoint != null) - { - SendTo(data, _defaultRemoteEndPoint); - } - else - { - throw new InvalidOperationException("服务端模式必须使用 SendTo 指定目标"); - } - } - - public void SendTo(byte[] data, IPEndPoint target) - { - if (!_isRunning) - { - return; - } - - var session = GetOrCreateSession(target); - uint seqNum = session.GetNextSendSequence(); - var packet = Packet.CreateDataPacket(seqNum, data); - - session.PendingAcks[seqNum] = (packet, DateTime.Now); - - SendPacketTo(packet, target); - Console.WriteLine($"[Transport] 发送数据包到 {target} SeqNum={seqNum}, DataLen={data.Length}"); - } - - public void SendToAll(byte[] data) - { - foreach (var session in _sessions.Values) - { - SendTo(data, session.EndPoint); - } - } - - public bool RemovePeerSession(IPEndPoint remoteEndPoint) - { - if (remoteEndPoint == null) - { - throw new ArgumentNullException(nameof(remoteEndPoint)); - } - - return _sessions.TryRemove(remoteEndPoint.ToString(), out _); - } - - private async void ReceiveLoop() - { - while (_isRunning) - { - try - { - var result = await _client.ReceiveAsync(); - var packet = Packet.FromBytes(result.Buffer); - - if (packet.Type == PacketType.Data) - { - HandleDataPacket(packet, result.RemoteEndPoint); - } - else if (packet.Type == PacketType.Ack) - { - HandleAckPacket(packet, result.RemoteEndPoint); - } - } - catch (ObjectDisposedException) - { - return; // 正常关闭 - } - catch (Exception e) - { - Console.WriteLine($"[Transport] 接收错误:{e.Message}"); - } - } - } - - private void HandleDataPacket(Packet packet, IPEndPoint senderEndPoint) - { - var session = GetOrCreateSession(senderEndPoint); - - Console.WriteLine( - $"[Transport] 收到数据包从{senderEndPoint} SeqNum={packet.SequenceNumber}, DataLen={packet.Data.Length}"); - - // 发送ACK - var ackPacket = Packet.CreateAckPacket(packet.SequenceNumber); - SendPacketTo(ackPacket, senderEndPoint); - Console.WriteLine($"[Transport] 发送ACK 到 {senderEndPoint} SeqNum={packet.SequenceNumber}"); - - // 检查是否应该交付 - if (session.TryProcessReceiveSequence(packet.SequenceNumber, out bool shouldDeliver)) - { - if (shouldDeliver) - { - OnReceive?.Invoke(packet.Data, senderEndPoint); - Console.WriteLine($"[Transport] 交付数据包从 {senderEndPoint} SeqNum={packet.SequenceNumber}"); - } - else - { - Console.WriteLine($"[Transport] 重复包从 {senderEndPoint} SeqNum={packet.SequenceNumber},忽略"); - } - } - else - { - // 乱序到达,暂存(简化处理:直接丢弃,依赖重传) - Console.WriteLine($"[Transport] 乱序包从 {senderEndPoint} SeqNum={packet.SequenceNumber},丢弃"); - } - } - - private void HandleAckPacket(Packet packet, IPEndPoint senderEndPoint) - { - var session = GetOrCreateSession(senderEndPoint); - Console.WriteLine($"[Transport] 收到ACK从 {senderEndPoint} SeqNum={packet.SequenceNumber}"); - - if (session.PendingAcks.TryRemove(packet.SequenceNumber, out _)) - { - Console.WriteLine($"[Transport] 确认包到 {senderEndPoint} SeqNum={packet.SequenceNumber}"); - } - } - - private ClientSession GetOrCreateSession(IPEndPoint endPoint) - { - string key = endPoint.ToString(); - return _sessions.GetOrAdd(key, _ => - { - var session = new ClientSession(endPoint); - Console.WriteLine($"创建新会话:{endPoint}"); - return session; - }); - } - - private void CheckRetransmit(object? state) - { - if (!_isRunning) - { - return; - } - - var now = DateTime.Now; - var toRetransmit = new List<(IPEndPoint target, uint seqNum, Packet packet)>(); - - foreach (var sessionKvp in _sessions) - { - var session = sessionKvp.Value; - foreach (var ackKvp in session.PendingAcks) - { - var timeSinceLastSend = now - ackKvp.Value.sendTime; - if (timeSinceLastSend.TotalMilliseconds > RetransmitTimeoutMs) - { - toRetransmit.Add((session.EndPoint, ackKvp.Key, ackKvp.Value.packet)); - _resentPacketTimes.TryAdd(ackKvp.Value.packet, 0); - } - } - } - - - foreach (var (target, seqNum, packet) in toRetransmit) - { - var session = GetOrCreateSession(target); - if (session.PendingAcks.ContainsKey(seqNum)) - { - // 更新发送时间 - session.PendingAcks[seqNum] = (packet, now); - SendPacketTo(packet, target); - Console.WriteLine($"[Transport] 重传包到 {target} SeqNum={seqNum}"); - - _resentPacketTimes[packet]++; - if (_resentPacketTimes[packet] >= MaxRetransmitAttempts) - { - // 达到最大重传次数,放弃该会话 - Console.WriteLine($"[Transport] 达到最大重传次数,放弃会话 {target}"); - _sessions.TryRemove(target.ToString(), out _); - } - } - } - } - - private void CleanupSessions(object? state) - { - if (!_isRunning) - { - return; - } - - var now = DateTime.Now; - var toRemove = new List(); - - foreach (var sessionKvp in _sessions) - { - var session = sessionKvp.Value; - var timeSinceLastActivity = now - session.LastActivity; - - if (timeSinceLastActivity.TotalMilliseconds > SessionTimeoutMs) - { - toRemove.Add(sessionKvp.Key); - } - } - - foreach (string key in toRemove) - { - //TODO: 清理会话的同时清理PlayerManager中的玩家数据 - if (_sessions.TryRemove(key, out var session)) - { - Console.WriteLine($"[Transport] 清理超时会话:{session.EndPoint}"); - } - } - - if (_isServer) - { - PrintSessionInfo(); - } - } - - private async void SendPacketTo(Packet packet, IPEndPoint? endPoint) - { - try - { - var data = packet.ToBytes(); - await _client.SendAsync(data, data.Length, endPoint); - } - catch (Exception e) - { - Console.WriteLine($"[Transport] 发送错误:{e.Message}"); - } - } - - private void PrintSessionInfo() - { - Console.WriteLine($"当前活跃会话数:{_sessions.Count}"); - foreach (var sessionKvp in _sessions) - { - var session = sessionKvp.Value; - Console.WriteLine( - $" 会话:{session.EndPoint},发送SeqNum:{session.SendSequenceNumber},期望接收:{session.ExpectedReceiveSequence},待确认: {session.PendingAcks.Count}"); - } - } - } -} diff --git a/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs.meta b/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs.meta deleted file mode 100644 index 23516e2..0000000 --- a/Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e740e71ab20f62d40bf5f56c2142bf02 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/TODO.md b/TODO.md index a3df42c..20472bb 100644 --- a/TODO.md +++ b/TODO.md @@ -8,25 +8,25 @@ Current assessment: Step-by-step plan: 1. Align replay integration granularity with live prediction -- Replace one-shot replay of an accumulated input duration with fixed substeps. -- Ensure replay uses the same movement integration shape as the normal `FixedUpdate` prediction path, especially for turn-and-move input. + - Replace one-shot replay of an accumulated input duration with fixed substeps. + - Ensure replay uses the same movement integration shape as the normal `FixedUpdate` prediction path, especially for turn-and-move input. 2. Align client prediction cadence with server authoritative cadence -- Introduce an explicit local prediction/replay cadence derived from the authoritative movement cadence. -- Avoid mixing client-side `Time.fixedDeltaTime` prediction with server-side fixed-cadence authoritative integration in reconciliation-sensitive paths. + - Introduce an explicit local prediction/replay cadence derived from the authoritative movement cadence. + - Avoid mixing client-side `Time.fixedDeltaTime` prediction with server-side fixed-cadence authoritative integration in reconciliation-sensitive paths. 3. Stabilize or remove send-rate oscillation driven by server tick offset -- Revisit `MovementComponent.SetServerTick(...)` and stop toggling `_sendInterval` directly between nearby values when the offset crosses zero. -- If clock correction is still needed, add hysteresis or filtering so the send cadence does not bounce frame-to-frame. + - Revisit `MovementComponent.SetServerTick(...)` and stop toggling `_sendInterval` directly between nearby values when the offset crosses zero. + - If clock correction is still needed, add hysteresis or filtering so the send cadence does not bounce frame-to-frame. 4. Re-measure controlled-player correction after timing fixes -- Keep remote-player interpolation as-is; do not treat local-player jitter as a remote interpolation problem. -- Only refine local visual correction further if meaningful residual error remains after steps 1-3. + - Keep remote-player interpolation as-is; do not treat local-player jitter as a remote interpolation problem. + - Only refine local visual correction further if meaningful residual error remains after steps 1-3. 5. Add regression coverage and diagnostics for the remaining jitter path -- Add tests that compare live prediction and replayed prediction under the same turn/throttle sequence. -- Add tests for server tick offset calibration so small offset sign changes do not continuously retarget send cadence. -- Add or expose diagnostics for acknowledged move tick, predicted pose, authoritative pose, and correction magnitude per snapshot. + - Add tests that compare live prediction and replayed prediction under the same turn/throttle sequence. + - Add tests for server tick offset calibration so small offset sign changes do not continuously retarget send cadence. + - Add or expose diagnostics for acknowledged move tick, predicted pose, authoritative pose, and correction magnitude per snapshot. Acceptance: