Compare commits

..

No commits in common. "2a9000b1204371bd1b4bb7e461c70852e7512f88" and "f4ba2d210c85af0eded2f4fa711cf4777222f931" have entirely different histories.

8 changed files with 154 additions and 318 deletions

View File

@ -11,6 +11,8 @@ GameObject:
- component: {fileID: 3817028170077760731} - component: {fileID: 3817028170077760731}
- component: {fileID: 4590407122831754579} - component: {fileID: 4590407122831754579}
- component: {fileID: 8963967235500975272} - component: {fileID: 8963967235500975272}
- component: {fileID: -5174249022758144916}
- component: {fileID: -7862229988660046446}
m_Layer: 0 m_Layer: 0
m_Name: RopePoint m_Name: RopePoint
m_TagString: Untagged m_TagString: Untagged
@ -96,3 +98,55 @@ Rigidbody2D:
m_SleepingMode: 1 m_SleepingMode: 1
m_CollisionDetection: 0 m_CollisionDetection: 0
m_Constraints: 0 m_Constraints: 0
--- !u!114 &-5174249022758144916
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4736158799711156794}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 1634323294
InScenePlacedSourceGlobalObjectIdHash: 0
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
--- !u!114 &-7862229988660046446
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4736158799711156794}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
UseUnreliableDeltas: 0
SyncPositionX: 1
SyncPositionY: 1
SyncPositionZ: 1
SyncRotAngleX: 0
SyncRotAngleY: 0
SyncRotAngleZ: 0
SyncScaleX: 0
SyncScaleY: 0
SyncScaleZ: 0
PositionThreshold: 0.001
RotAngleThreshold: 0.01
ScaleThreshold: 0.01
UseQuaternionSynchronization: 0
UseQuaternionCompression: 0
UseHalfFloatPrecision: 0
InLocalSpace: 0
Interpolate: 1
SlerpPosition: 0

View File

@ -9,11 +9,12 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 144529238244638330} - component: {fileID: 144529238244638330}
- component: {fileID: 6056950010778645813} - component: {fileID: 2894273998966960381}
- component: {fileID: 7717684785049474632} - component: {fileID: 7717684785049474632}
- component: {fileID: 901761791259710742} - component: {fileID: 901761791259710742}
- component: {fileID: 4976294692568481572} - component: {fileID: 4976294692568481572}
- component: {fileID: 2066655509941542230} - component: {fileID: 2066655509941542230}
- component: {fileID: 7670104141912458081}
m_Layer: 0 m_Layer: 0
m_Name: Rope m_Name: Rope
m_TagString: Untagged m_TagString: Untagged
@ -36,7 +37,7 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &6056950010778645813 --- !u!114 &2894273998966960381
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@ -48,15 +49,15 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
GlobalObjectIdHash: 15502151 GlobalObjectIdHash: 3972580189
InScenePlacedSourceGlobalObjectIdHash: 0 InScenePlacedSourceGlobalObjectIdHash: 1619090677
AlwaysReplicateAsRoot: 0 AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1 SynchronizeTransform: 1
ActiveSceneSynchronization: 0 ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1 SceneMigrationSynchronization: 1
SpawnWithObservers: 1 SpawnWithObservers: 1
DontDestroyWithOwner: 0 DontDestroyWithOwner: 0
AutoObjectParentSync: 1 AutoObjectParentSync: 0
--- !u!114 &7717684785049474632 --- !u!114 &7717684785049474632
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -118,9 +119,6 @@ MonoBehaviour:
ropeCollidersParent: {fileID: 144529238244638330} ropeCollidersParent: {fileID: 144529238244638330}
lineRenderer: {fileID: 901761791259710742} lineRenderer: {fileID: 901761791259710742}
pullAnimationOvershootThreshold: 0.2 pullAnimationOvershootThreshold: 0.2
rope:
points: []
sticks: []
--- !u!120 &901761791259710742 --- !u!120 &901761791259710742
LineRenderer: LineRenderer:
serializedVersion: 2 serializedVersion: 2
@ -335,3 +333,34 @@ AudioSource:
m_PreInfinity: 2 m_PreInfinity: 2
m_PostInfinity: 2 m_PostInfinity: 2
m_RotationOrder: 4 m_RotationOrder: 4
--- !u!114 &7670104141912458081
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5991265243222894942}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e96cb6065543e43c4a752faaa1468eb1, type: 3}
m_Name:
m_EditorClassIdentifier:
UseUnreliableDeltas: 0
SyncPositionX: 1
SyncPositionY: 1
SyncPositionZ: 1
SyncRotAngleX: 0
SyncRotAngleY: 0
SyncRotAngleZ: 0
SyncScaleX: 0
SyncScaleY: 0
SyncScaleZ: 0
PositionThreshold: 0.001
RotAngleThreshold: 0.01
ScaleThreshold: 0.01
UseQuaternionSynchronization: 0
UseQuaternionCompression: 0
UseHalfFloatPrecision: 0
InLocalSpace: 0
Interpolate: 1
SlerpPosition: 0

View File

@ -4306,18 +4306,14 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z propertyPath: m_LocalEulerAnglesHint.z
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2894273998966960381, guid: 0248db69242a3dd47898c6742b6c9f60, type: 3}
propertyPath: GlobalObjectIdHash
value: 3972580189
objectReference: {fileID: 0}
- target: {fileID: 5991265243222894942, guid: 0248db69242a3dd47898c6742b6c9f60, type: 3} - target: {fileID: 5991265243222894942, guid: 0248db69242a3dd47898c6742b6c9f60, type: 3}
propertyPath: m_Name propertyPath: m_Name
value: Rope value: Rope
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6056950010778645813, guid: 0248db69242a3dd47898c6742b6c9f60, type: 3}
propertyPath: GlobalObjectIdHash
value: 1448608317
objectReference: {fileID: 0}
- target: {fileID: 6056950010778645813, guid: 0248db69242a3dd47898c6742b6c9f60, type: 3}
propertyPath: InScenePlacedSourceGlobalObjectIdHash
value: 331293026
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []

View File

@ -1,32 +1,15 @@
using UnityEngine; using UnityEngine;
using Unity.Netcode;
[System.Serializable] [System.Serializable]
public class Point : INetworkSerializable public class Point
{ {
public Vector3 position, prevPosition; public Vector3 position, prevPosition;
public bool locked; public bool locked;
public Point() {}
public Point(Vector3 position, bool locked = false) public Point(Vector3 position, bool locked = false)
{ {
this.position = position; this.position = position;
this.prevPosition = position; this.prevPosition = position;
this.locked = locked; this.locked = locked;
} }
public Point(Vector3 position, Vector3 prevPosition, bool locked = false)
{
this.position = position;
this.prevPosition = prevPosition;
this.locked = locked;
}
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref position);
serializer.SerializeValue(ref prevPosition);
serializer.SerializeValue(ref locked);
}
} }

View File

@ -1,18 +1,13 @@
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions;
using Unity.Netcode;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine;
[System.Serializable] [System.Serializable]
public class Rope public class Rope
{ {
public Point[] points; public List<Point> points { get ; private set; }
public Stick[] sticks; public List<Stick> sticks { get; private set; }
public Rope() {} public Rope(List<Point> points, List<Stick> sticks)
public Rope(Point[] points, Stick[] sticks)
{ {
this.points = points; this.points = points;
this.sticks = sticks; this.sticks = sticks;
@ -30,213 +25,4 @@ public class Rope
return sum; return sum;
} }
public static float CalcDiff(Rope r1, Rope r2, bool excludeZ = true)
{
if (r1.points.Length != r2.points.Length)
{
throw new System.ArgumentException("Ropes are not the same length");
}
float diff = 0;
if (excludeZ)
{
for (int i = 0; i < r1.points.Length; i++)
{
Vector3 p1, p2;
p1 = new Vector2(r1.points[i].position.x, r1.points[i].position.y);
p2 = new Vector2(r2.points[i].position.x, r2.points[i].position.y);
diff += Vector2.Distance(p1, p2);
}
}
else
{
for (int i = 0; i < r1.points.Length; i++)
{
diff += Vector3.Distance(r1.points[i].position, r2.points[i].position);
}
}
return diff;
}
public static NetworkRope ToNetworkRope(Rope rope)
{
return new NetworkRope
{
positions = rope.points.Select(p => p.position).ToArray(),
prevPositions = rope.points.Select(p => p.prevPosition).ToArray(),
locked = rope.points.Select(p => p.locked).ToArray(),
// sPosA = rope.sticks.Select(s => s.A.position).ToArray(),
// sPrevPosA = rope.sticks.Select(s => s.A.prevPosition).ToArray(),
// sPosB = rope.sticks.Select(s => s.B.position).ToArray(),
// sPrevPosB = rope.sticks.Select(s => s.B.prevPosition).ToArray(),
// dead = rope.sticks.Select(s => s.dead).ToArray(),
};
}
public static Rope FromNetworkRope(NetworkRope nrope, float stickLength)
{
Assert.IsTrue(nrope.positions.Length == nrope.prevPositions.Length);
Point[] points = new Point[nrope.positions.Length];
for (int i = 0; i < nrope.positions.Length; i++)
{
points[i] = new Point(nrope.positions[i], nrope.prevPositions[i], nrope.locked[i]);
}
RopeBuilder builder = new RopeBuilder(new List<Point>(points), new List<Stick>());
for (int i = 0; i < (points.Length - 1); i++)
{
builder.ConnectPointsWithDesiredLength(i, i + 1, desiredLength: stickLength);
}
return builder.Build();
}
/* public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
int pLen = 0;
int sLen = 0;
if (serializer.IsWriter)
{
pLen = points.Length;
sLen = sticks.Length;
}
serializer.SerializeValue(ref pLen);
serializer.SerializeValue(ref sLen);
if (serializer.IsReader)
{
points = new Point[pLen];
sticks = new Stick[sLen];
for (int i = 0; i < pLen; i++)
{
serializer.GetFastBufferReader().ReadValueSafe(out points[i]);
}
for (int i = 0; i < sLen; i++)
{
serializer.GetFastBufferReader().ReadValueSafe(out sticks[i]);
}
}
else
{
for (int i = 0; i < pLen; i++)
{
points[i].NetworkSerialize(serializer);
}
for (int i = 0; i < sLen; i++)
{
sticks[i].NetworkSerialize(serializer);
}
}
} */
}
public struct NetworkRope : INetworkSerializable
{
// For rope points
public Vector3[] positions;
public Vector3[] prevPositions;
public bool[] locked;
// For rope sticks
// public Vector3[] sPosA;
// public Vector3[] sPrevPosA;
//
// public Vector3[] sPosB;
// public Vector3[] sPrevPosB;
//
// public bool[] dead;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
int positionsLen = 0;
int prevPositionsLen = 0;
int lockedLen = 0;
// int sPosALen = 0;
// int sPrevPosALen = 0;
// int sPosBLen = 0;
// int sPrevPosBLen = 0;
// int deadLen = 0;
if (!serializer.IsReader)
{
positionsLen = positions.Length;
prevPositionsLen = prevPositions.Length;
lockedLen = locked.Length;
// sPosALen = sPosA.Length;
// sPrevPosALen = sPrevPosA.Length;
// sPosBLen = sPosB.Length;
// sPrevPosBLen = sPrevPosB.Length;
// deadLen = dead.Length;
}
serializer.SerializeValue(ref positionsLen);
serializer.SerializeValue(ref prevPositionsLen);
serializer.SerializeValue(ref lockedLen);
// serializer.SerializeValue(ref sPosALen);
// serializer.SerializeValue(ref sPrevPosALen);
// serializer.SerializeValue(ref sPosBLen);
// serializer.SerializeValue(ref sPrevPosBLen);
// serializer.SerializeValue(ref deadLen);
if (serializer.IsReader)
{
positions = new Vector3[positionsLen];
prevPositions = new Vector3[prevPositionsLen];
locked = new bool[lockedLen];
// sPosA = new Vector3[sPosALen];
// sPrevPosA = new Vector3[sPrevPosALen];
// sPosB = new Vector3[sPosBLen];
// sPrevPosB = new Vector3[sPrevPosBLen];
// dead = new bool[deadLen];
}
for (int i = 0; i < positionsLen; i++)
{
serializer.SerializeValue(ref positions[i]);
}
for (int i = 0; i < prevPositionsLen; i++)
{
serializer.SerializeValue(ref prevPositions[i]);
}
for (int i = 0; i < lockedLen; i++)
{
serializer.SerializeValue(ref locked[i]);
}
/* for (int i = 0; i < sPosALen; i++)
{
serializer.SerializeValue(ref sPosA[i]);
}
for (int i = 0; i < sPrevPosALen; i++)
{
serializer.SerializeValue(ref sPrevPosA[i]);
}
for (int i = 0; i < sPosBLen; i++)
{
serializer.SerializeValue(ref sPosB[i]);
}
for (int i = 0; i < sPrevPosBLen; i++)
{
serializer.SerializeValue(ref sPrevPosB[i]);
}
for (int i = 0; i < deadLen; i++)
{
serializer.SerializeValue(ref dead[i]);
} */
}
} }

View File

@ -40,6 +40,6 @@ public class RopeBuilder
public Rope Build() public Rope Build()
{ {
return new Rope(points: points.ToArray(), sticks: sticks.ToArray()); return new Rope(points: points, sticks: sticks);
} }
} }

View File

@ -65,9 +65,8 @@ public class RopeSimulator : NetworkBehaviour
[Header("Netcode")] [Header("Netcode")]
private const int k_rngSeed = 6969; private const int k_rngSeed = 6969;
private const float k_sendRopeDataRPCThreshold = 0.1f;
private const float k_ropeReconciliateThreshold = 0.25f;
private System.Random rng = new System.Random(k_rngSeed); private System.Random rng = new System.Random(k_rngSeed);
private NetworkTimer networkTimer;
private int[] order; private int[] order;
@ -82,6 +81,10 @@ public class RopeSimulator : NetworkBehaviour
private bool IsInitialized => start != null || end != null; private bool IsInitialized => start != null || end != null;
// TODO: also true in single player mode
private bool ShouldSimulate => IsHost;
private void Awake() private void Awake()
{ {
if (instance == null) if (instance == null)
@ -106,11 +109,17 @@ public class RopeSimulator : NetworkBehaviour
public void PlayersReady(GameObject[] players) public void PlayersReady(GameObject[] players)
{ {
if (ShouldSimulate)
{
Debug.Log(players[0].name);
BuildRope(players[0].GetComponent<RopeJoint>(), players[1].GetComponent<RopeJoint>()); BuildRope(players[0].GetComponent<RopeJoint>(), players[1].GetComponent<RopeJoint>());
} }
}
public void BuildRope(RopeJoint start, RopeJoint end) public void BuildRope(RopeJoint start, RopeJoint end)
{ {
Assert.IsTrue(ShouldSimulate, "Should not try build rope on client!");
Assert.IsNotNull(start); Assert.IsNotNull(start);
Assert.IsNotNull(end); Assert.IsNotNull(end);
@ -140,6 +149,8 @@ public class RopeSimulator : NetworkBehaviour
void ShrinkenRope(int playerNumber) void ShrinkenRope(int playerNumber)
{ {
Assert.IsTrue(ShouldSimulate, "Should not shrink rope on client!");
int prevSubDivision = (int) subDivision; int prevSubDivision = (int) subDivision;
subDivision -= ropeShrinkSpeed * Time.deltaTime; subDivision -= ropeShrinkSpeed * Time.deltaTime;
subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength); subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength);
@ -148,13 +159,10 @@ public class RopeSimulator : NetworkBehaviour
if (prevSubDivision - (int) subDivision <= 0) return; if (prevSubDivision - (int) subDivision <= 0) return;
// Shrink from rope point after start rope joint // Shrink from rope point after start rope joint
List<Point> newPoints = new(rope.points.Length - 1); rope.sticks.Clear();
for (int i = 0; i < (rope.points.Length - 1); i++) rope.points.RemoveAt(1);
{
newPoints.Add(rope.points[i]);
}
var builder = new RopeBuilder(newPoints, new List<Stick>()); var builder = new RopeBuilder(rope.points, rope.sticks);
// Re-gen sticks // Re-gen sticks
for (int i = 0; i < (int) subDivision; i++) for (int i = 0; i < (int) subDivision; i++)
@ -169,6 +177,8 @@ public class RopeSimulator : NetworkBehaviour
void ExtendRope(int playerNumber) void ExtendRope(int playerNumber)
{ {
Assert.IsTrue(ShouldSimulate, "Should not extend rope on client!");
int prevSubDivision = (int)subDivision; int prevSubDivision = (int)subDivision;
subDivision += ropeExtendSpeed * Time.deltaTime; subDivision += ropeExtendSpeed * Time.deltaTime;
subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength); subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength);
@ -177,14 +187,10 @@ public class RopeSimulator : NetworkBehaviour
if (prevSubDivision - (int) subDivision >= 0) return; if (prevSubDivision - (int) subDivision >= 0) return;
// Extend from rope point after start rope point // Extend from rope point after start rope point
List<Point> newPoints = new (rope.points.Length + 1); rope.sticks.Clear();
newPoints.Add(new Point(rope.points[1].position)); rope.points.Insert(1, new Point(rope.points[1].position));
for (int i = 1; i < rope.points.Length; i++)
{
newPoints.Add(rope.points[i]);
}
var builder = new RopeBuilder(newPoints, new List<Stick>()); var builder = new RopeBuilder(rope.points, rope.sticks);
// Re-gen sticks // Re-gen sticks
for (int i = 0; i < (int)subDivision; i++) for (int i = 0; i < (int)subDivision; i++)
@ -214,6 +220,8 @@ public class RopeSimulator : NetworkBehaviour
private void Rebuild() private void Rebuild()
{ {
Assert.IsTrue(ShouldSimulate, "Should not re-build on clients!");
Debug.Log("rebuild"); Debug.Log("rebuild");
RopeBuilder builder = new RopeBuilder(); RopeBuilder builder = new RopeBuilder();
@ -243,6 +251,8 @@ public class RopeSimulator : NetworkBehaviour
private void RebuildRopeColliders() private void RebuildRopeColliders()
{ {
Assert.IsTrue(ShouldSimulate, "Should not build rope colliders on client!");
for (int i = 0; i < ropeCollidersParent.childCount; i++) for (int i = 0; i < ropeCollidersParent.childCount; i++)
{ {
Destroy(ropeCollidersParent.GetChild(i)); Destroy(ropeCollidersParent.GetChild(i));
@ -251,8 +261,10 @@ public class RopeSimulator : NetworkBehaviour
foreach (var point in rope.points) foreach (var point in rope.points)
{ {
GameObject ropeCollider = Instantiate(colliderPrefab); GameObject ropeCollider = Instantiate(colliderPrefab);
ropeCollider.transform.parent = ropeCollidersParent; var ropeNO = ropeCollider.GetComponent<NetworkObject>();
ropeNO.Spawn();
ropeNO.TrySetParent(ropeCollidersParent);
ropeCollider.transform.position = point.position; ropeCollider.transform.position = point.position;
ropeCollider.tag = colliderTag; ropeCollider.tag = colliderTag;
ropeCollider.layer = LayerMask.NameToLayer("Rope"); ropeCollider.layer = LayerMask.NameToLayer("Rope");
@ -276,24 +288,14 @@ 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(diff);
if (diff > k_ropeReconciliateThreshold)
{
Debug.LogWarning("Reconciliating rope!");
this.rope = serverRope;
Debug.Log(Rope.CalcDiff(this.rope, serverRope));
}
}
private void Update() private void Update()
{ {
if (!ShouldSimulate)
{
DrawRope();
return;
}
if (!IsInitialized) if (!IsInitialized)
return; return;
@ -302,18 +304,10 @@ public class RopeSimulator : NetworkBehaviour
rope.points.First().position = start.position; rope.points.First().position = start.position;
rope.points.Last().position = end.position; rope.points.Last().position = end.position;
float ropeDiff = Simulate(Time.fixedDeltaTime); Simulate(Time.fixedDeltaTime);
if (IsServer && ropeDiff > k_sendRopeDataRPCThreshold)
{
Debug.Log($"Sending rope to client");
NetworkRope nrope = Rope.ToNetworkRope(this.rope);
// Send server rope to client for reconciliation
ServerRopeDataReceivedRpc(nrope);
}
// 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.Count; i++)
{ {
ropeCollidersParent.GetChild(i).position = rope.points[i].position; ropeCollidersParent.GetChild(i).position = rope.points[i].position;
} }
@ -358,6 +352,7 @@ public class RopeSimulator : NetworkBehaviour
private void PlayerPullAnimation(float overshoot) private void PlayerPullAnimation(float overshoot)
{ {
Assert.IsTrue(ShouldSimulate);
//if (overshoot > pullAnimationOvershootThreshold) //if (overshoot > pullAnimationOvershootThreshold)
//{ //{
@ -383,6 +378,8 @@ public class RopeSimulator : NetworkBehaviour
private void PullPlayers(float overshoot) private void PullPlayers(float overshoot)
{ {
Assert.IsTrue(ShouldSimulate);
if (overshoot <= 0f) return; if (overshoot <= 0f) return;
//start.position = prevStartPos; //start.position = prevStartPos;
@ -400,7 +397,7 @@ public class RopeSimulator : NetworkBehaviour
} }
if (!end.locked) if (!end.locked)
{ {
Vector2 pullDirection = (rope.points[rope.points.Length - 2].position - end.position).normalized; Vector2 pullDirection = (rope.points[rope.points.Count - 2].position - end.position).normalized;
Vector2 force = pullDirection * overshoot * (pullForce / divider); Vector2 force = pullDirection * overshoot * (pullForce / divider);
end.body.AddForce(force); end.body.AddForce(force);
} }
@ -424,9 +421,10 @@ public class RopeSimulator : NetworkBehaviour
} }
} }
float Simulate(float dt) void Simulate(float dt)
{ {
float diff = 0f; Assert.IsTrue(ShouldSimulate, "Should not simulate rope on client!");
foreach (Point p in rope.points) foreach (Point p in rope.points)
{ {
if (!p.locked) if (!p.locked)
@ -434,14 +432,13 @@ public class RopeSimulator : NetworkBehaviour
Vector3 positionBeforeUpdate = p.position; Vector3 positionBeforeUpdate = p.position;
p.position += p.position - p.prevPosition; p.position += p.position - p.prevPosition;
p.position.z -= gravity * dt * dt; p.position.z -= gravity * dt * dt;
diff += Mathf.Abs(Vector3.Distance(p.prevPosition, p.position));
p.prevPosition = positionBeforeUpdate; p.prevPosition = positionBeforeUpdate;
} }
} }
for (int i = 0; i < solveIterations; i++) for (int i = 0; i < solveIterations; i++)
{ {
for (int s = 0; s < rope.sticks.Length; s++) for (int s = 0; s < rope.sticks.Count; s++)
{ {
Stick stick = rope.sticks[order[s]]; Stick stick = rope.sticks[order[s]];
if (stick.dead) if (stick.dead)
@ -464,11 +461,12 @@ public class RopeSimulator : NetworkBehaviour
} }
} }
} }
return diff;
} }
private void TryMovePointToPosition(Point point, Vector3 position) private void TryMovePointToPosition(Point point, Vector3 position)
{ {
Assert.IsTrue(ShouldSimulate);
Vector2 moveDir = new Vector2(position.x, position.y) - new Vector2(point.position.x, point.position.y); Vector2 moveDir = new Vector2(position.x, position.y) - new Vector2(point.position.x, point.position.y);
int stepsRequired = (int) Mathf.Ceil(moveDir.magnitude / collisionCheckDist); int stepsRequired = (int) Mathf.Ceil(moveDir.magnitude / collisionCheckDist);
moveDir.Normalize(); moveDir.Normalize();
@ -507,6 +505,7 @@ public class RopeSimulator : NetworkBehaviour
private void HandleStaticCollidersOfPoint(Point p) private void HandleStaticCollidersOfPoint(Point p)
{ {
Assert.IsTrue(ShouldSimulate);
foreach (var hitCollider in Physics2D.OverlapCircleAll(p.position, ropeRadius*1.1f, staticColliderMask)) foreach (var hitCollider in Physics2D.OverlapCircleAll(p.position, ropeRadius*1.1f, staticColliderMask))
{ {
if (hitCollider == null) continue; if (hitCollider == null) continue;
@ -530,7 +529,7 @@ public class RopeSimulator : NetworkBehaviour
void CreateOrderArray() void CreateOrderArray()
{ {
order = new int[rope.sticks.Length]; order = new int[rope.sticks.Count];
for (int i = 0; i < order.Length; i++) for (int i = 0; i < order.Length; i++)
{ {
order[i] = i; order[i] = i;

View File

@ -1,15 +1,12 @@
using UnityEngine; using UnityEngine;
using Unity.Netcode;
[System.Serializable] [System.Serializable]
public class Stick : INetworkSerializable public class Stick
{ {
public Point A, B; public Point A, B;
public float desiredLength; public float desiredLength;
public bool dead; public bool dead;
public Stick() { }
public Stick(Point pointA, Point pointB) public Stick(Point pointA, Point pointB)
{ {
this.A = pointA; this.A = pointA;
@ -23,12 +20,4 @@ public class Stick : INetworkSerializable
this.B = pointB; this.B = pointB;
this.desiredLength = desiredLenght; this.desiredLength = desiredLenght;
} }
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
A.NetworkSerialize(serializer);
B.NetworkSerialize(serializer);
serializer.SerializeValue(ref desiredLength);
serializer.SerializeValue(ref dead);
}
} }