rope maybe working pls??
This commit is contained in:
parent
0a521b51c8
commit
acca896c7b
|
@ -473,7 +473,7 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
GlobalObjectIdHash: 2899378164
|
||||
GlobalObjectIdHash: 4009941625
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
AlwaysReplicateAsRoot: 0
|
||||
SynchronizeTransform: 1
|
||||
|
|
|
@ -48,7 +48,7 @@ MonoBehaviour:
|
|||
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
GlobalObjectIdHash: 15502151
|
||||
GlobalObjectIdHash: 168437488
|
||||
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||
AlwaysReplicateAsRoot: 0
|
||||
SynchronizeTransform: 1
|
||||
|
@ -118,6 +118,11 @@ MonoBehaviour:
|
|||
ropeCollidersParent: {fileID: 144529238244638330}
|
||||
lineRenderer: {fileID: 901761791259710742}
|
||||
pullAnimationOvershootThreshold: 0.2
|
||||
k_ropeReconciliateThreshold: 2
|
||||
stateBuffer:
|
||||
buffer: []
|
||||
bufferSize: 0
|
||||
reconciliateDuration: 0.3
|
||||
rope:
|
||||
points: []
|
||||
sticks: []
|
||||
|
|
|
@ -133,7 +133,6 @@ public class EnemySpawner : NetworkBehaviour
|
|||
void SpawnEnemy(GameObject enemyPrefab)
|
||||
{
|
||||
GameObject enemy = Instantiate(enemyPrefab, GetRandomPointOnCircle(SpawnRadius), Quaternion.identity, SpawnedEnenmyHolder.transform);
|
||||
enemy.GetComponent<NetworkID>().InitialID = idCounter++;
|
||||
enemy.GetComponent<NetworkObject>().Spawn();
|
||||
|
||||
enemy.GetComponent<EnemyPathFinding>().targets = players.Select(x => x.transform).ToArray();
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
// FIXME: NetworkObject.NetworkObjectId are ulong but we're sending them as int. potential problem
|
||||
|
||||
[System.Serializable]
|
||||
public struct GameState : INetworkSerializable
|
||||
{
|
||||
public int tick;
|
||||
public NetworkRope nrope;
|
||||
public Vector2[] enemyPositions;
|
||||
|
||||
/// <summary>
|
||||
/// x & y are location coords. z component is the <see cref="NetworkID.ID"/>
|
||||
/// of the enemy.
|
||||
/// </summary>
|
||||
public Vector3[] enemyPositions;
|
||||
|
||||
/// <summary>
|
||||
/// x & y are location coords. z component is the <see cref="NetworkID.ID"/>
|
||||
/// of the player.
|
||||
/// </summary>
|
||||
public Vector3[] playerPositions;
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
|
@ -23,6 +36,7 @@ public struct GameState : INetworkSerializable
|
|||
{
|
||||
serializer.SerializeValue(ref tick);
|
||||
serializer.SerializeValue(ref enemyPositions);
|
||||
serializer.SerializeValue(ref playerPositions);
|
||||
nrope.NetworkSerialize(serializer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,12 +67,16 @@ public class RopeSimulator : NetworkBehaviour
|
|||
[Header("Netcode")]
|
||||
private const float k_serverTickRate = 60f;
|
||||
private const int k_rngSeed = 6969;
|
||||
public float k_ropeReconciliateThreshold = 10f;
|
||||
public float k_ropeReconciliateThreshold = 1f;
|
||||
private System.Random rng = new System.Random(k_rngSeed);
|
||||
private int currentTick => NetworkManager.Singleton.NetworkTickSystem.LocalTime.Tick;
|
||||
[SerializeField] private CircularBuffer<GameState> stateBuffer;
|
||||
private GameState lastReceivedServerGameState;
|
||||
private const int k_bufferSize = 512;
|
||||
private bool isReconciliating = false;
|
||||
private GameState currentRewindingState;
|
||||
[SerializeField] private float reconciliateDuration = 0.1f;
|
||||
private float rewindCounter = 0f;
|
||||
|
||||
private int[] order;
|
||||
|
||||
|
@ -271,10 +275,10 @@ public class RopeSimulator : NetworkBehaviour
|
|||
private void DrawRope()
|
||||
{
|
||||
// Update line renderer
|
||||
List<Vector3> positions = new List<Vector3>(ropeCollidersParent.childCount);
|
||||
for (int i = 0; i < ropeCollidersParent.childCount; i++)
|
||||
List<Vector3> positions = new List<Vector3>(this.rope.points.Length);
|
||||
for (int i = 0; i < this.rope.points.Length; i++)
|
||||
{
|
||||
positions.Add(ropeCollidersParent.GetChild(i).position);
|
||||
positions.Add(this.rope.points[i].position);
|
||||
}
|
||||
lineRenderer.positionCount = positions.Count;
|
||||
lineRenderer.SetPositions(positions.ToArray());
|
||||
|
@ -297,8 +301,76 @@ public class RopeSimulator : NetworkBehaviour
|
|||
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}");
|
||||
float serverLocalRopeError = Rope.CalcDiff(serverRope, oldLocalRope);
|
||||
|
||||
if (serverLocalRopeError >= k_ropeReconciliateThreshold)
|
||||
{
|
||||
SimpleReconcile(serverState);
|
||||
}
|
||||
Debug.Log($"Server to client sync error: {serverLocalRopeError}");
|
||||
}
|
||||
|
||||
private void SimpleReconcile(GameState rewindState)
|
||||
{
|
||||
Debug.LogWarning("Reconciliate");
|
||||
this.rewindCounter = 0f;
|
||||
this.isReconciliating = true;
|
||||
this.currentRewindingState = rewindState;
|
||||
}
|
||||
|
||||
private void Reconciliate()
|
||||
{
|
||||
Physics2D.simulationMode = SimulationMode2D.Script;
|
||||
|
||||
Debug.LogWarning("Reconciliate");
|
||||
Debug.Break();
|
||||
// Reset client to server state
|
||||
GameState serverState = this.lastReceivedServerGameState;
|
||||
this.rope = Rope.FromNetworkRope(serverState.nrope, distBetweenRopePoints);
|
||||
Dictionary<ulong, GameObject> enemyByIds = new();
|
||||
Dictionary<ulong, GameObject> playerByIds = new();
|
||||
IEnumerable<EnemyPathFinding> enemies = GameObject.FindObjectsByType<EnemyPathFinding>(FindObjectsSortMode.None);
|
||||
IEnumerable<PlayerMovement> players = GameObject.FindObjectsByType<PlayerMovement>(FindObjectsSortMode.None);
|
||||
|
||||
foreach (var enemy in enemies)
|
||||
enemyByIds.Add(enemy.GetComponent<NetworkObject>().NetworkObjectId, enemy.gameObject);
|
||||
|
||||
foreach (var player in players)
|
||||
playerByIds.Add(player.GetComponent<NetworkObject>().NetworkObjectId, player.gameObject);
|
||||
|
||||
|
||||
// Re-simulate up to this client's tick
|
||||
Debug.Log($"Needs to re-sim {currentTick - serverState.tick} steps");
|
||||
for (int tick = serverState.tick; tick <= currentTick; tick++)
|
||||
{
|
||||
GameState intermediateState = tick == serverState.tick ? serverState : stateBuffer.Get(tick);
|
||||
|
||||
foreach (var enemyPos in intermediateState.enemyPositions)
|
||||
{
|
||||
// Find corresponding client enemy with id (z-component)
|
||||
ulong enemyID = (ulong) enemyPos.z;
|
||||
GameObject enemy = enemyByIds.GetValueOrDefault(enemyID);
|
||||
Assert.IsNotNull(enemy, $"Server enemy with id: {enemyID} could not be found on client!");
|
||||
|
||||
enemy.transform.position = new Vector2(enemyPos.x, enemyPos.y);
|
||||
}
|
||||
|
||||
foreach (var playerPos in intermediateState.playerPositions)
|
||||
{
|
||||
// Find corresponding client player with id (z-component)
|
||||
ulong playerID = (ulong) playerPos.z;
|
||||
GameObject player = playerByIds.GetValueOrDefault(playerID);
|
||||
Assert.IsNotNull(player, $"Server player with id: {playerID} could not be found on client!");
|
||||
|
||||
player.transform.position = new Vector2(playerPos.x, playerPos.y);
|
||||
}
|
||||
|
||||
this.Simulate(Time.fixedDeltaTime);
|
||||
|
||||
Physics2D.Simulate(Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
Physics2D.simulationMode = SimulationMode2D.FixedUpdate;
|
||||
}
|
||||
|
||||
private void NetworkTick()
|
||||
|
@ -315,7 +387,8 @@ public class RopeSimulator : NetworkBehaviour
|
|||
GameState localState = new() {
|
||||
tick = currentTick,
|
||||
nrope = Rope.ToNetworkRope(this.rope),
|
||||
enemyPositions = GameObject.FindObjectsByType<EnemyPathFinding>(FindObjectsSortMode.None).Select(e => new Vector2(e.transform.position.x, e.transform.position.y)).ToArray()
|
||||
enemyPositions = GameObject.FindObjectsByType<EnemyPathFinding>(FindObjectsSortMode.None).Select(e => new Vector3(e.transform.position.x, e.transform.position.y, e.GetComponent<NetworkObject>().NetworkObjectId)).ToArray(),
|
||||
playerPositions = GameObject.FindObjectsByType<PlayerMovement>(FindObjectsSortMode.None).Select(p => new Vector3(p.transform.position.x, p.transform.position.y, p.GetComponent<NetworkObject>().NetworkObjectId)).ToArray()
|
||||
};
|
||||
|
||||
return localState;
|
||||
|
@ -326,6 +399,42 @@ public class RopeSimulator : NetworkBehaviour
|
|||
if (!IsInitialized)
|
||||
return;
|
||||
|
||||
if (isReconciliating)
|
||||
{
|
||||
this.rope.points.First().position = start.position;
|
||||
this.rope.points.First().prevPosition = start.position;
|
||||
|
||||
this.rope.points.Last().position = end.position;
|
||||
this.rope.points.Last().prevPosition = end.position;
|
||||
|
||||
Rope rewindRope = Rope.FromNetworkRope(currentRewindingState.nrope, distBetweenRopePoints);
|
||||
rewindCounter += Time.deltaTime;
|
||||
float t = rewindCounter / reconciliateDuration;
|
||||
for (int point = 1; point < rope.points.Length - 1; point++)
|
||||
{
|
||||
Vector3 newPos = Vector3.Slerp(this.rope.points[point].position, rewindRope.points[point].position, t);
|
||||
|
||||
this.rope.points[point].position = newPos;
|
||||
this.rope.points[point].prevPosition = newPos;
|
||||
}
|
||||
|
||||
Simulate(Time.deltaTime);
|
||||
foreach (var point in rope.points)
|
||||
{
|
||||
// point.prevPosition = point.position;
|
||||
}
|
||||
|
||||
DrawRope();
|
||||
|
||||
if (t >= 1f)
|
||||
{
|
||||
rewindCounter = 0f;
|
||||
isReconciliating = false;
|
||||
currentRewindingState = default(GameState);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
colliderToSquezeForce.Clear();
|
||||
|
||||
rope.points.First().position = start.position;
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
|
||||
public class NetworkID : NetworkBehaviour
|
||||
{
|
||||
// Set from enemy spawner
|
||||
public int InitialID = -1;
|
||||
|
||||
private NetworkVariable<int> nID = new();
|
||||
|
||||
public int ID => nID.Value;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
nID.Value = InitialID;
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e071dd818c5a905209e31c2d66ea6390
|
|
@ -1,16 +0,0 @@
|
|||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(NetworkID))]
|
||||
public class NetworkID_Inspector : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
EditorGUILayout.LabelField($"ID: {(target as NetworkID).ID}");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e70a0a80d88c1620c955d7bdc1efe3ee
|
Loading…
Reference in New Issue