rope wip
This commit is contained in:
parent
026d427dc0
commit
f0f56c5b70
|
@ -11,8 +11,6 @@ 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
|
||||||
|
@ -98,55 +96,3 @@ 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
|
|
||||||
|
|
|
@ -9,12 +9,11 @@ GameObject:
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 144529238244638330}
|
- component: {fileID: 144529238244638330}
|
||||||
- component: {fileID: 2894273998966960381}
|
- component: {fileID: 6056950010778645813}
|
||||||
- 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
|
||||||
|
@ -37,7 +36,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 &2894273998966960381
|
--- !u!114 &6056950010778645813
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
@ -49,15 +48,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: 3972580189
|
GlobalObjectIdHash: 15502151
|
||||||
InScenePlacedSourceGlobalObjectIdHash: 1619090677
|
InScenePlacedSourceGlobalObjectIdHash: 0
|
||||||
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: 0
|
AutoObjectParentSync: 1
|
||||||
--- !u!114 &7717684785049474632
|
--- !u!114 &7717684785049474632
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -119,6 +118,9 @@ 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
|
||||||
|
@ -333,34 +335,3 @@ 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
|
|
||||||
|
|
|
@ -3722,7 +3722,6 @@ MonoBehaviour:
|
||||||
difficulty: 1
|
difficulty: 1
|
||||||
difficultyIncreasePerWave: 3
|
difficultyIncreasePerWave: 3
|
||||||
WaveTime: 20
|
WaveTime: 20
|
||||||
enemyDifficulties: []
|
|
||||||
SpawnRadius: 22.6
|
SpawnRadius: 22.6
|
||||||
NumEnemies: 6
|
NumEnemies: 6
|
||||||
initialSpawnDelay: 5
|
initialSpawnDelay: 5
|
||||||
|
@ -3902,14 +3901,18 @@ 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: []
|
||||||
|
|
|
@ -1,15 +1,32 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Unity.Netcode;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class Point
|
public class Point : INetworkSerializable
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,18 @@
|
||||||
using System.Collections.Generic;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Assertions;
|
||||||
|
using Unity.Netcode;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class Rope
|
public class Rope
|
||||||
{
|
{
|
||||||
public List<Point> points { get ; private set; }
|
public Point[] points;
|
||||||
public List<Stick> sticks { get; private set; }
|
public Stick[] sticks;
|
||||||
|
|
||||||
public Rope(List<Point> points, List<Stick> sticks)
|
public Rope() {}
|
||||||
|
|
||||||
|
public Rope(Point[] points, Stick[] sticks)
|
||||||
{
|
{
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.sticks = sticks;
|
this.sticks = sticks;
|
||||||
|
@ -25,4 +30,200 @@ public class Rope
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float CalcDiff(Rope r1, Rope r2)
|
||||||
|
{
|
||||||
|
if (r1.points.Length != r2.points.Length)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("Ropes are not the same length");
|
||||||
|
}
|
||||||
|
|
||||||
|
float diff = 0;
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,6 @@ public class RopeBuilder
|
||||||
|
|
||||||
public Rope Build()
|
public Rope Build()
|
||||||
{
|
{
|
||||||
return new Rope(points: points, sticks: sticks);
|
return new Rope(points: points.ToArray(), sticks: sticks.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,8 +65,9 @@ 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.1f;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -81,10 +82,6 @@ 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)
|
||||||
|
@ -109,17 +106,11 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
|
|
||||||
public void PlayersReady(GameObject[] players)
|
public void PlayersReady(GameObject[] players)
|
||||||
{
|
{
|
||||||
if (ShouldSimulate)
|
BuildRope(players[0].GetComponent<RopeJoint>(), players[1].GetComponent<RopeJoint>());
|
||||||
{
|
|
||||||
Debug.Log(players[0].name);
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -149,8 +140,6 @@ 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);
|
||||||
|
@ -159,10 +148,13 @@ 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
|
||||||
rope.sticks.Clear();
|
List<Point> newPoints = new(rope.points.Length - 1);
|
||||||
rope.points.RemoveAt(1);
|
for (int i = 0; i < (rope.points.Length - 1); i++)
|
||||||
|
{
|
||||||
|
newPoints.Add(rope.points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
var builder = new RopeBuilder(rope.points, rope.sticks);
|
var builder = new RopeBuilder(newPoints, new List<Stick>());
|
||||||
|
|
||||||
// Re-gen sticks
|
// Re-gen sticks
|
||||||
for (int i = 0; i < (int) subDivision; i++)
|
for (int i = 0; i < (int) subDivision; i++)
|
||||||
|
@ -177,8 +169,6 @@ 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);
|
||||||
|
@ -187,10 +177,14 @@ 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
|
||||||
rope.sticks.Clear();
|
List<Point> newPoints = new (rope.points.Length + 1);
|
||||||
rope.points.Insert(1, new Point(rope.points[1].position));
|
newPoints.Add(new Point(rope.points[1].position));
|
||||||
|
for (int i = 1; i < rope.points.Length; i++)
|
||||||
|
{
|
||||||
|
newPoints.Add(rope.points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
var builder = new RopeBuilder(rope.points, rope.sticks);
|
var builder = new RopeBuilder(newPoints, new List<Stick>());
|
||||||
|
|
||||||
// Re-gen sticks
|
// Re-gen sticks
|
||||||
for (int i = 0; i < (int)subDivision; i++)
|
for (int i = 0; i < (int)subDivision; i++)
|
||||||
|
@ -220,8 +214,6 @@ 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();
|
||||||
|
@ -251,8 +243,6 @@ 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));
|
||||||
|
@ -261,10 +251,8 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
foreach (var point in rope.points)
|
foreach (var point in rope.points)
|
||||||
{
|
{
|
||||||
GameObject ropeCollider = Instantiate(colliderPrefab);
|
GameObject ropeCollider = Instantiate(colliderPrefab);
|
||||||
var ropeNO = ropeCollider.GetComponent<NetworkObject>();
|
ropeCollider.transform.parent = ropeCollidersParent;
|
||||||
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");
|
||||||
|
@ -289,14 +277,21 @@ 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}");
|
||||||
|
Debug.Log(nrope.sPosA[1]);
|
||||||
|
Rope serverRope = Rope.FromNetworkRope(nrope, distBetweenRopePoints);
|
||||||
|
if (Rope.CalcDiff(this.rope, serverRope) > k_ropeReconciliateThreshold)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Reconciliating rope!");
|
||||||
|
this.rope = serverRope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (!ShouldSimulate)
|
|
||||||
{
|
|
||||||
DrawRope();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsInitialized)
|
if (!IsInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -305,10 +300,18 @@ 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;
|
||||||
|
|
||||||
Simulate(Time.fixedDeltaTime);
|
float ropeDiff = 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.Count; i++)
|
for (int i = 0; i < rope.points.Length; i++)
|
||||||
{
|
{
|
||||||
ropeCollidersParent.GetChild(i).position = rope.points[i].position;
|
ropeCollidersParent.GetChild(i).position = rope.points[i].position;
|
||||||
}
|
}
|
||||||
|
@ -353,7 +356,6 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
|
|
||||||
private void PlayerPullAnimation(float overshoot)
|
private void PlayerPullAnimation(float overshoot)
|
||||||
{
|
{
|
||||||
Assert.IsTrue(ShouldSimulate);
|
|
||||||
|
|
||||||
//if (overshoot > pullAnimationOvershootThreshold)
|
//if (overshoot > pullAnimationOvershootThreshold)
|
||||||
//{
|
//{
|
||||||
|
@ -379,8 +381,6 @@ 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;
|
||||||
|
@ -398,7 +398,7 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
}
|
}
|
||||||
if (!end.locked)
|
if (!end.locked)
|
||||||
{
|
{
|
||||||
Vector2 pullDirection = (rope.points[rope.points.Count - 2].position - end.position).normalized;
|
Vector2 pullDirection = (rope.points[rope.points.Length - 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);
|
||||||
}
|
}
|
||||||
|
@ -422,10 +422,9 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Simulate(float dt)
|
float Simulate(float dt)
|
||||||
{
|
{
|
||||||
Assert.IsTrue(ShouldSimulate, "Should not simulate rope on client!");
|
float diff = 0f;
|
||||||
|
|
||||||
foreach (Point p in rope.points)
|
foreach (Point p in rope.points)
|
||||||
{
|
{
|
||||||
if (!p.locked)
|
if (!p.locked)
|
||||||
|
@ -433,13 +432,14 @@ 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.Count; s++)
|
for (int s = 0; s < rope.sticks.Length; s++)
|
||||||
{
|
{
|
||||||
Stick stick = rope.sticks[order[s]];
|
Stick stick = rope.sticks[order[s]];
|
||||||
if (stick.dead)
|
if (stick.dead)
|
||||||
|
@ -462,12 +462,11 @@ 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();
|
||||||
|
@ -506,7 +505,6 @@ 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 +528,7 @@ public class RopeSimulator : NetworkBehaviour
|
||||||
|
|
||||||
void CreateOrderArray()
|
void CreateOrderArray()
|
||||||
{
|
{
|
||||||
order = new int[rope.sticks.Count];
|
order = new int[rope.sticks.Length];
|
||||||
for (int i = 0; i < order.Length; i++)
|
for (int i = 0; i < order.Length; i++)
|
||||||
{
|
{
|
||||||
order[i] = i;
|
order[i] = i;
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Unity.Netcode;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class Stick
|
public class Stick : INetworkSerializable
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -20,4 +23,12 @@ public class Stick
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue