From 8b10b735c94388eb6f1f6028f8afa412d104d74b Mon Sep 17 00:00:00 2001 From: Sveske Juice Date: Fri, 2 Feb 2024 17:47:40 -0800 Subject: [PATCH] rope with gravity effect --- Assets/Scenes/RopeTest.unity | 3 +- Assets/Scripts/Player/HealthComponent.cs | 1 - Assets/Scripts/Rope/Point.cs | 4 +- Assets/Scripts/Rope/RopeSimulator.cs | 51 ++++++++++++++++-------- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/Assets/Scenes/RopeTest.unity b/Assets/Scenes/RopeTest.unity index 580faa1..b141385 100644 --- a/Assets/Scenes/RopeTest.unity +++ b/Assets/Scenes/RopeTest.unity @@ -1515,7 +1515,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 27ac133d9e10e544ba603e07122e3359, type: 3} m_Name: m_EditorClassIdentifier: - gravity: 0 + gravity: 15 solveIterations: 10 constrainStickMinLength: 0 start: {fileID: 1451580753} @@ -1530,6 +1530,7 @@ MonoBehaviour: serializedVersion: 2 m_Bits: 1 pullForce: 65 + xyGravityDampScalor: 1 lineRenderer: {fileID: 1973576218} testPos: {x: 0, y: 0} --- !u!120 &1973576218 diff --git a/Assets/Scripts/Player/HealthComponent.cs b/Assets/Scripts/Player/HealthComponent.cs index d02a05f..871e302 100644 --- a/Assets/Scripts/Player/HealthComponent.cs +++ b/Assets/Scripts/Player/HealthComponent.cs @@ -33,7 +33,6 @@ public class HealthComponent : MonoBehaviour, ISquezeDamageReceiver public void TakeSquezeDamage(float squezeDamage) { - Debug.Log($"Taking {squezeDamage}"); if (squezeDamage < minThreshold) return; TakeDamage((int) Mathf.Round(squezeDamage * squezeDamageScalor)); diff --git a/Assets/Scripts/Rope/Point.cs b/Assets/Scripts/Rope/Point.cs index 65a928d..6bf6b10 100644 --- a/Assets/Scripts/Rope/Point.cs +++ b/Assets/Scripts/Rope/Point.cs @@ -3,10 +3,10 @@ using UnityEngine; [System.Serializable] public class Point { - public Vector2 position, prevPosition; + public Vector3 position, prevPosition; public bool locked; - public Point(Vector2 position, bool locked = false) + public Point(Vector3 position, bool locked = false) { this.position = position; this.prevPosition = position; diff --git a/Assets/Scripts/Rope/RopeSimulator.cs b/Assets/Scripts/Rope/RopeSimulator.cs index 4fc35c5..9034629 100644 --- a/Assets/Scripts/Rope/RopeSimulator.cs +++ b/Assets/Scripts/Rope/RopeSimulator.cs @@ -47,6 +47,9 @@ public class RopeSimulator : MonoBehaviour [SerializeField, Range(0f, 100f)] float pullForce = 20f; + [SerializeField] + float xyGravityDampScalor = 1f; + [Header("Rendering")] [SerializeField] LineRenderer lineRenderer; @@ -75,7 +78,7 @@ public class RopeSimulator : MonoBehaviour builder.AddPoint(new Point(start.position, locked: true)); for (int i = 1; i < subDivision; i++) { - Vector2 pointPos = Vector2.Lerp(start.position, end.position, (float)i / (float)subDivision); + Vector3 pointPos = Vector3.Lerp(start.position, end.position, (float)i / (float)subDivision); //Debug.Log($"pos: {pointPos}, t={i / subDivision}"); Debug.DrawRay(pointPos, (end.position - start.position).normalized); builder.AddPoint(new Point(pointPos)); @@ -93,6 +96,7 @@ public class RopeSimulator : MonoBehaviour { GameObject ropeCollider = new GameObject("Rope Collider"); ropeCollider.transform.parent = ropeCollidersParent; + ropeCollider.transform.position = point.position; ropeCollider.layer = LayerMask.NameToLayer("Rope"); var colliderComponent = ropeCollider.AddComponent(); @@ -129,7 +133,7 @@ public class RopeSimulator : MonoBehaviour if (overshoot > 0) { //start.position = prevStartPos; - Vector2 pullDirection = (rope.points.ElementAt(1).position - new Vector2(start.position.x, start.position.y)).normalized; + Vector2 pullDirection = (rope.points.ElementAt(1).position - start.position).normalized; start.gameObject.GetComponent().AddForce(pullDirection * overshoot * pullForce); } @@ -146,6 +150,15 @@ public class RopeSimulator : MonoBehaviour var positions = rope.points.Select(p => new Vector3(p.position.x, p.position.y, 0f)).ToArray(); lineRenderer.positionCount = positions.Length; lineRenderer.SetPositions(positions); + + // Handle xy dampening on z gravity + foreach (var point in rope.points) + { + if (point.position.z >= 0f) continue; + + Vector2 newXYPos = Vector2.MoveTowards(new Vector2(point.position.x, point.position.y), new Vector2(point.prevPosition.x, point.prevPosition.y), Mathf.Abs(point.position.z * xyGravityDampScalor)); + point.position.Set(newXYPos.x, newXYPos.y, 0f); + } } private void OnDrawGizmos() @@ -165,9 +178,9 @@ public class RopeSimulator : MonoBehaviour { if (!p.locked) { - Vector2 positionBeforeUpdate = p.position; + Vector3 positionBeforeUpdate = p.position; p.position += p.position - p.prevPosition; - p.position += Vector2.down * gravity * Time.deltaTime * Time.deltaTime; + p.position.z -= gravity * Time.deltaTime * Time.deltaTime; p.prevPosition = positionBeforeUpdate; } } @@ -182,8 +195,8 @@ public class RopeSimulator : MonoBehaviour continue; } - Vector2 stickCentre = (stick.A.position + stick.B.position) / 2; - Vector2 stickDir = (stick.A.position - stick.B.position).normalized; + Vector3 stickCentre = (stick.A.position + stick.B.position) / 2; + Vector3 stickDir = (stick.A.position - stick.B.position).normalized; float length = (stick.A.position - stick.B.position).magnitude; if (length > stick.desiredLength || constrainStickMinLength) @@ -201,16 +214,17 @@ public class RopeSimulator : MonoBehaviour } } - private void TryMovePointToPosition(Point point, Vector2 position) + private void TryMovePointToPosition(Point point, Vector3 position) { - Vector2 moveDir = position - point.position; + Vector2 moveDir = new Vector2(position.x, position.y) - new Vector2(point.position.x, point.position.y); int stepsRequired = (int) Mathf.Ceil(moveDir.magnitude / collisionCheckDist); moveDir.Normalize(); - Vector2 initialPos = point.position; + + Vector2 initialPos = new Vector2(point.position.x, point.position.y); for (int i = 0 ; i < stepsRequired; i++) { - Vector2 newPos = Vector2.MoveTowards(point.position, position, collisionCheckDist); - point.position = newPos; + Vector2 newPos = Vector2.MoveTowards(new Vector2(point.position.x, point.position.y), new Vector2(position.x, position.y), collisionCheckDist); + point.position.Set(newPos.x, newPos.y, point.position.z); Collider2D collider = Physics2D.OverlapCircle(point.position, ropeRadius, staticColliderMask); if (collider == null) continue; @@ -219,13 +233,15 @@ public class RopeSimulator : MonoBehaviour if (Vector2.Distance(initialPos, resolvedPos) < ignoreResolveThreshold) continue; - Vector2 penetrationDir = (resolvedPos - point.position).normalized; + Vector2 penetrationDir = (resolvedPos - new Vector2(point.position.x, point.position.y)).normalized; Vector2 finalPos = resolvedPos - penetrationDir * ropeRadius; //Debug.Log($"resolved pos: {point.position}->{finalPos}"); - point.position = finalPos; - //point.prevPosition = finalPos; + point.position.Set(finalPos.x, finalPos.y, point.position.z); break; } + + // Move z position + point.position.z = position.z; } private void HandleStaticCollidersOfPoint(Point p) @@ -234,8 +250,9 @@ public class RopeSimulator : MonoBehaviour if (hitCollider == null) return; // Register the squeze force this rope particle is squezing the collider - Vector2 resolvedPos = hitCollider.ClosestPoint(p.position); - Vector2 penetration = resolvedPos - p.position; + Vector2 pointPos = new Vector2(p.position.x, p.position.y); + Vector2 resolvedPos = hitCollider.ClosestPoint(pointPos); + Vector2 penetration = resolvedPos - pointPos; Vector2 finalPos = resolvedPos - penetration.normalized * ropeRadius; float squezeForce; @@ -244,7 +261,7 @@ public class RopeSimulator : MonoBehaviour else colliderToSquezeForce[hitCollider] = squezeForce + penetration.magnitude; - p.position = finalPos; + p.position.Set(finalPos.x, finalPos.y, p.position.z); } void CreateOrderArray()