Store in circular buffer & gizmo for local and server rope on client

This commit is contained in:
Sveske_Juice 2024-03-17 18:53:53 +01:00
parent c9b874667e
commit 0e9b82ca43
2 changed files with 39 additions and 43 deletions

View File

@ -6,6 +6,17 @@ public struct GameState : INetworkSerializable
public int tick; public int tick;
public NetworkRope nrope; public NetworkRope nrope;
public override int GetHashCode()
{
return tick;
}
public override bool Equals(object obj)
{
GameState other = (GameState) obj;
return this.GetHashCode() == obj.GetHashCode();
}
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{ {
serializer.SerializeValue(ref tick); serializer.SerializeValue(ref tick);

View File

@ -68,12 +68,11 @@ public class RopeSimulator : NetworkBehaviour
[Header("Netcode")] [Header("Netcode")]
private const float k_serverTickRate = 60f; private const float k_serverTickRate = 60f;
private const int k_rngSeed = 6969; private const int k_rngSeed = 6969;
private const float k_sendRopeDataDelay = 8f;
public float k_ropeReconciliateThreshold = 10f; public float k_ropeReconciliateThreshold = 10f;
private System.Random rng = new System.Random(k_rngSeed); private System.Random rng = new System.Random(k_rngSeed);
private CountdownTimer ropeSendTimer;
private int currentTick => NetworkManager.Singleton.NetworkTickSystem.LocalTime.Tick; private int currentTick => NetworkManager.Singleton.NetworkTickSystem.LocalTime.Tick;
[SerializeField] private CircularBuffer<GameState> stateBuffer; [SerializeField] private CircularBuffer<GameState> stateBuffer;
private GameState lastReceivedServerGameState;
private const int k_bufferSize = 512; private const int k_bufferSize = 512;
private int[] order; private int[] order;
@ -101,12 +100,6 @@ public class RopeSimulator : NetworkBehaviour
} }
stateBuffer = new(k_bufferSize); stateBuffer = new(k_bufferSize);
ropeSendTimer = new(k_sendRopeDataDelay);
// ropeSendTimer.OnTimerStop += SendRopeData;
ropeSendTimer.Start();
} }
private void OnEnable() private void OnEnable()
@ -288,25 +281,25 @@ public class RopeSimulator : NetworkBehaviour
lineRenderer.SetPositions(positions.ToArray()); lineRenderer.SetPositions(positions.ToArray());
} }
[Rpc(SendTo.NotServer)]
private void ServerRopeDataReceivedRpc(NetworkRope nrope)
{
Debug.Log($"Received rope data from server: {nrope}");
Rope serverRope = Rope.FromNetworkRope(nrope, distBetweenRopePoints);
float diff = Rope.CalcDiff(this.rope, serverRope);
Debug.Log($"server client rope diff: {diff}");
// if (diff > k_ropeReconciliateThreshold)
// {
// Debug.LogWarning("Reconciliating rope!");
// this.rope = serverRope;
// }
}
[Rpc(SendTo.NotServer)] [Rpc(SendTo.NotServer)]
private void ServerToClientGameStateRpc(GameState serverState) private void ServerToClientGameStateRpc(GameState serverState)
{ {
this.lastReceivedServerGameState = serverState;
Debug.Log($"Received server state. Server tick: {serverState.tick}, client: {currentTick}"); Debug.Log($"Received server state. Server tick: {serverState.tick}, client: {currentTick}");
// Not enough information
if (stateBuffer.Get(serverState.tick).Equals(default(GameState))) return;
// TODO: investigate why this is zero at start of game sometimes
if (stateBuffer.Get(serverState.tick).nrope.positions.Length == 0) return;
Debug.Log($"client len: {stateBuffer.Get(serverState.tick).nrope.positions.Length}, server len {serverState.nrope.positions.Length}");
Rope serverRope = Rope.FromNetworkRope(serverState.nrope, distBetweenRopePoints);
Rope oldLocalRope = Rope.FromNetworkRope(stateBuffer.Get(serverState.tick).nrope, distBetweenRopePoints);
float serverLocalRopeDiff = Rope.CalcDiff(serverRope, oldLocalRope);
Debug.Log($"Server to client sync error: {serverLocalRopeDiff}");
} }
private void NetworkTick() private void NetworkTick()
@ -328,20 +321,6 @@ public class RopeSimulator : NetworkBehaviour
return localState; return localState;
} }
private void SendRopeData()
{
if (!IsServer) return;
Debug.Log($"Sending rope to client");
NetworkRope nrope = Rope.ToNetworkRope(this.rope);
// Send server rope to client for reconciliation
ServerRopeDataReceivedRpc(nrope);
ropeSendTimer.Reset();
ropeSendTimer.Start();
}
private void Update() private void Update()
{ {
if (!IsInitialized) if (!IsInitialized)
@ -353,7 +332,6 @@ public class RopeSimulator : NetworkBehaviour
rope.points.Last().position = end.position; rope.points.Last().position = end.position;
float ropeDiff = Simulate(Time.fixedDeltaTime); float ropeDiff = Simulate(Time.fixedDeltaTime);
ropeSendTimer.Tick(Time.deltaTime);
// Update the rope collider positions // Update the rope collider positions
for (int i = 0; i < rope.points.Length; i++) for (int i = 0; i < rope.points.Length; i++)
@ -397,7 +375,6 @@ public class RopeSimulator : NetworkBehaviour
} }
DrawRope(); DrawRope();
// SendRopeData();
} }
private void PlayerPullAnimation(float overshoot) private void PlayerPullAnimation(float overshoot)
@ -456,14 +433,22 @@ public class RopeSimulator : NetworkBehaviour
private void OnDrawGizmos() private void OnDrawGizmos()
{ {
return; if (!IsInitialized) return;
if (IsInitialized) return;
if (!Application.isPlaying) return; if (!Application.isPlaying) return;
// Local rope
Gizmos.color = Color.green;
foreach (var point in rope.points) foreach (var point in rope.points)
{ {
//Debug.Log($"pos: {point.position}"); Gizmos.DrawSphere(point.position, ropeRadius);
}
// Last received server rope
if (lastReceivedServerGameState.Equals(default(GameState))) return;
Gizmos.color = Color.red;
foreach (var point in Rope.FromNetworkRope(lastReceivedServerGameState.nrope, distBetweenRopePoints).points)
{
Gizmos.DrawSphere(point.position, ropeRadius); Gizmos.DrawSphere(point.position, ropeRadius);
} }
} }