Refactor rope simulator

This commit is contained in:
Sveske Juice 2024-02-27 19:54:10 +01:00
parent f1c39f502c
commit a076f5000f
4 changed files with 98 additions and 4863 deletions

View File

@ -57,7 +57,6 @@ MonoBehaviour:
distBetweenRopePoints: 0.35
ropeRadius: 0.171
ignoreResolveThreshold: 0
ropeCollidersParent: {fileID: 144529238244638330}
staticColliderMask:
serializedVersion: 2
m_Bits: 1
@ -92,6 +91,11 @@ MonoBehaviour:
m_RotationOrder: 4
ropeMaxLength: 50
ropeMinLength: 20
colliderTag: Rope
colliderLayer:
serializedVersion: 2
m_Bits: 64
ropeCollidersParent: {fileID: 144529238244638330}
lineRenderer: {fileID: 901761791259710742}
pullAnimationOvershootThreshold: 0.2
--- !u!120 &901761791259710742
@ -112,6 +116,8 @@ LineRenderer:
m_ReflectionProbeUsage: 0
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@ -220,6 +226,7 @@ AudioSource:
serializedVersion: 4
OutputAudioMixerGroup: {fileID: 0}
m_audioClip: {fileID: 8300000, guid: fd92966d4cde3244d9a711094cb947f6, type: 3}
m_Resource: {fileID: 8300000, guid: fd92966d4cde3244d9a711094cb947f6, type: 3}
m_PlayOnAwake: 0
m_Volume: 0.107
m_Pitch: 1

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 0400e5e5779425c40ba3164b1e0b5b59
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions;
public class RopeSimulator : MonoBehaviour
{
@ -33,9 +34,6 @@ public class RopeSimulator : MonoBehaviour
[SerializeField]
float ignoreResolveThreshold = 0.08f;
[SerializeField]
Transform ropeCollidersParent;
[SerializeField]
LayerMask staticColliderMask;
@ -54,6 +52,10 @@ public class RopeSimulator : MonoBehaviour
[SerializeField]
public float ropeMaxLength, ropeMinLength;
[Header("Rope Colliders")]
[SerializeField] string colliderTag = "Rope";
[SerializeField] LayerMask colliderLayer;
[SerializeField] Transform ropeCollidersParent;
[Header("Rendering")]
[SerializeField] LineRenderer lineRenderer;
@ -72,6 +74,8 @@ public class RopeSimulator : MonoBehaviour
public static RopeSimulator instance;
private bool IsInitialized => start == null || end == null;
private void Awake()
{
if (instance == null)
@ -100,22 +104,23 @@ public class RopeSimulator : MonoBehaviour
// .Build();
// Build rope if rope joints specified in inspector
if (start != null && end != null)
if (IsInitialized)
BuildRope(start, end);
}
public void BuildRope(RopeJoint start, RopeJoint end)
{
// Sanity check if rope simulator was initialized before
if (this.start != null)
Assert.IsNotNull(start);
Assert.IsNotNull(end);
// Sanity check if rope simulator was initialized before - we are re-building the rope
if (IsInitialized)
{
start.playerInput.ropeLengthExtend -= ExtendRope;
start.playerInput.ropeLengthShrinken -= ShrinkenRope;
}
if (this.end != null)
{
end.playerInput.ropeLengthExtend -= ExtendRope;
end.playerInput.ropeLengthShrinken -= ShrinkenRope;
this.start.playerInput.ropeLengthExtend -= ExtendRope;
this.start.playerInput.ropeLengthShrinken -= ShrinkenRope;
this.end.playerInput.ropeLengthExtend -= ExtendRope;
this.end.playerInput.ropeLengthShrinken -= ShrinkenRope;
}
this.start = start;
@ -134,12 +139,12 @@ public class RopeSimulator : MonoBehaviour
{
int prevSubDivision = (int) subDivision;
subDivision -= ropeShrinkSpeed * Time.deltaTime;
if (subDivision < ropeMinLength)
subDivision = ropeMinLength;
subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength);
if (prevSubDivision - (int)subDivision <= 0) return;
// Only shrinken if the numeric value has changed
if (prevSubDivision - (int) subDivision <= 0) return;
// Shrink from start
// Shrink from rope point after start rope joint
rope.sticks.Clear();
rope.points.RemoveAt(1);
@ -160,20 +165,14 @@ public class RopeSimulator : MonoBehaviour
{
int prevSubDivision = (int)subDivision;
subDivision += ropeExtendSpeed * Time.deltaTime;
if (subDivision > ropeMaxLength)
subDivision = ropeMaxLength;
subDivision = Mathf.Clamp(subDivision, ropeMinLength, ropeMaxLength);
// Only extend if the numeric value has changed
if (prevSubDivision - (int) subDivision >= 0) return;
// Max from start
rope.points.Insert(1, new Point(rope.points[1].position));
// Extend from rope point after start rope point
rope.sticks.Clear();
// Ripple existing rope points
//for (int i = 2; i < (int) subDivision; i++)
//{
// rope.points[i].position = rope.points[i + 1].position;
//}
rope.points.Insert(1, new Point(rope.points[1].position));
var builder = new RopeBuilder(rope.points, rope.sticks);
@ -187,12 +186,12 @@ public class RopeSimulator : MonoBehaviour
RebuildRopeColliders();
CreateOrderArray();
}
private void OnDestroy()
{
if (start == null || end == null) return;
// May never have been initialized
if (!IsInitialized) return;
start.playerInput.ropeLengthShrinken -= ShrinkenRope;
end.playerInput.ropeLengthShrinken -= ShrinkenRope;
@ -208,16 +207,17 @@ public class RopeSimulator : MonoBehaviour
RopeBuilder builder = new RopeBuilder();
builder.AddPoint(new Point(start.position, locked: true));
// Build rope points
for (int i = 1; i < (int) subDivision; i++)
{
Vector3 pointPos = Vector3.Lerp(start.position, end.position, (float)i / (float)(int)subDivision);
//Debug.Log($"pos: {pointPos}, t={i / subDivision}");
Vector3 pointPos = Vector3.Lerp(start.position, end.position, (float)i / Mathf.Floor(subDivision));
Debug.DrawRay(pointPos, (end.position - start.position).normalized);
builder.AddPoint(new Point(pointPos));
}
builder.AddPoint(new Point(end.position, locked: true));
// Connect rope points
for (int i = 0; i < (int) subDivision; i++)
{
builder.ConnectPointsWithDesiredLength(i, i + 1, desiredLength: distBetweenRopePoints);
@ -231,7 +231,6 @@ public class RopeSimulator : MonoBehaviour
private void RebuildRopeColliders()
{
// ropeCollidersParent.DestroyChildren(); Did this to avoid unityutils
for (int i = 0; i < ropeCollidersParent.childCount; i++)
{
Destroy(ropeCollidersParent.GetChild(i));
@ -240,10 +239,10 @@ public class RopeSimulator : MonoBehaviour
foreach (var point in rope.points)
{
GameObject ropeCollider = new GameObject("Rope Collider");
ropeCollider.tag = "Rope";
ropeCollider.tag = colliderTag;
ropeCollider.transform.parent = ropeCollidersParent;
ropeCollider.transform.position = point.position;
ropeCollider.layer = LayerMask.NameToLayer("Rope");
ropeCollider.layer = colliderLayer;
var colliderComponent = ropeCollider.AddComponent<CircleCollider2D>();
colliderComponent.radius = ropeRadius;
@ -255,13 +254,9 @@ public class RopeSimulator : MonoBehaviour
private void Update()
{
// Dont update if no rope is initialized
if (start == null || end == null)
if (IsInitialized)
return;
//Debug.Log($"overshoot: {rope.CalculateLengthOvershoot()}");
//ShrinkenRope(1);
//ExtendRope(0);
colliderToSquezeForce.Clear();
rope.points.First().position = start.position;
@ -285,7 +280,38 @@ public class RopeSimulator : MonoBehaviour
// Constrain start transform based on overshoot
float overshoot = rope.CalculateLengthOvershoot();
if (overshoot > 0)
PlayerPullAnimation(overshoot);
PullPlayers(overshoot);
// Handle squeze kills
foreach (var collider in colliderToSquezeForce)
{
ISquezeDamageReceiver squezeDamageReceiver = collider.Key.transform.root.GetComponent<ISquezeDamageReceiver>();
if (squezeDamageReceiver == null)
squezeDamageReceiver = collider.Key.GetComponent<ISquezeDamageReceiver>();
if (squezeDamageReceiver == null) continue;
float swingMultiplier = InSwingMode ? swingSpeedToDamageMultiplier.Evaluate((start.locked ? end : start).body.velocity.magnitude) : 1f;
squezeDamageReceiver.TakeSquezeDamage(collider.Value * squezeDamage * swingMultiplier);
}
// Update line renderer
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 PlayerPullAnimation(float overshoot)
{
if (overshoot > pullAnimationOvershootThreshold)
{
@ -307,6 +333,11 @@ public class RopeSimulator : MonoBehaviour
start.playerAnimationHandler?.animator.SetBool("IsPulling", false);
end.playerAnimationHandler?.animator.SetBool("IsPulling", false);
}
}
private void PullPlayers(float overshoot)
{
if (overshoot <= 0f) return;
//start.position = prevStartPos;
float divider = !start.locked && !end.locked ? 2f : 1f;
@ -333,38 +364,9 @@ public class RopeSimulator : MonoBehaviour
}
}
// Handle squeze kills
foreach (var collider in colliderToSquezeForce)
{
ISquezeDamageReceiver squezeDamageReceiver = collider.Key.transform.root.GetComponent<ISquezeDamageReceiver>();
if (squezeDamageReceiver == null)
squezeDamageReceiver = collider.Key.GetComponent<ISquezeDamageReceiver>();
if (squezeDamageReceiver == null) continue;
float swingMultiplier = InSwingMode ? swingSpeedToDamageMultiplier.Evaluate((start.locked ? end : start).body.velocity.magnitude) : 1f;
squezeDamageReceiver.TakeSquezeDamage(collider.Value * squezeDamage * swingMultiplier);
}
// Update line renderer
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()
{
return;
if (IsInitialized) return;
if (!Application.isPlaying) return;
foreach (var point in rope.points)