rope start
This commit is contained in:
parent
692cbf4d10
commit
1cbff2800f
|
@ -0,0 +1,15 @@
|
|||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class Point
|
||||
{
|
||||
public Vector2 position, prevPosition;
|
||||
public bool locked;
|
||||
|
||||
public Point(Vector2 position, bool locked = false)
|
||||
{
|
||||
this.position = position;
|
||||
this.prevPosition = position;
|
||||
this.locked = locked;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a07dfdaccf053414085b41179c0ab234
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Rope
|
||||
{
|
||||
public List<Point> points { get ; private set; }
|
||||
public List<Stick> sticks { get; private set; }
|
||||
|
||||
public Rope(List<Point> points, List<Stick> sticks)
|
||||
{
|
||||
this.points = points;
|
||||
this.sticks = sticks;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fb42a2c8fa09c32489663226dc7167e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,32 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class RopeBuilder
|
||||
{
|
||||
List<Point> points = new();
|
||||
List<Stick> sticks = new();
|
||||
|
||||
public RopeBuilder AddPoint(Point point)
|
||||
{
|
||||
points.Add(point);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RopeBuilder ConnectPoints(Point A, Point B)
|
||||
{
|
||||
sticks.Add(new Stick(A, B));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RopeBuilder ConnectPoints(int idxA, int idxB)
|
||||
{
|
||||
sticks.Add(new Stick(points[idxA], points[idxB]));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rope Build()
|
||||
{
|
||||
return new Rope(points: points, sticks: sticks);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e87b5185694f23a4390596cc0294bee7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,129 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityUtils;
|
||||
|
||||
public class RopeSimulator : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float gravity = 10;
|
||||
|
||||
[SerializeField]
|
||||
private float solveIterations = 10;
|
||||
|
||||
[SerializeField]
|
||||
private float constrainStickMinLength = 0.1f;
|
||||
|
||||
int[] order;
|
||||
|
||||
public Vector2 testPos;
|
||||
|
||||
Rope rope;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
rope = new RopeBuilder()
|
||||
.AddPoint(new Point(testPos, locked: true))
|
||||
.AddPoint(new Point(testPos.Add(x:5f)))
|
||||
.AddPoint(new Point(testPos.Add(x: 10f)))
|
||||
.AddPoint(new Point(testPos.Add(x: 15f)))
|
||||
.AddPoint(new Point(testPos.Add(x: 20f)))
|
||||
.ConnectPoints(0, 1)
|
||||
.ConnectPoints(1, 2)
|
||||
.ConnectPoints(2, 3)
|
||||
.ConnectPoints(3, 4)
|
||||
.Build();
|
||||
CreateOrderArray();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Simulate();
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (!Application.isPlaying) return;
|
||||
|
||||
foreach (var point in rope.points)
|
||||
{
|
||||
Debug.Log($"pos: {point.position}");
|
||||
Gizmos.DrawSphere(point.position, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
void Simulate()
|
||||
{
|
||||
foreach (Point p in rope.points)
|
||||
{
|
||||
if (!p.locked)
|
||||
{
|
||||
Vector2 positionBeforeUpdate = p.position;
|
||||
p.position += p.position - p.prevPosition;
|
||||
p.position += Vector2.down * gravity * Time.deltaTime * Time.deltaTime;
|
||||
p.prevPosition = positionBeforeUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < solveIterations; i++)
|
||||
{
|
||||
for (int s = 0; s < rope.sticks.Count; s++)
|
||||
{
|
||||
Stick stick = rope.sticks[order[s]];
|
||||
if (stick.dead)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 stickCentre = (stick.A.position + stick.B.position) / 2;
|
||||
Vector2 stickDir = (stick.A.position - stick.B.position).normalized;
|
||||
float length = (stick.A.position - stick.B.position).magnitude;
|
||||
|
||||
if (length > stick.length || length > constrainStickMinLength)
|
||||
{
|
||||
if (!stick.A.locked)
|
||||
{
|
||||
stick.A.position = stickCentre + stickDir * stick.length / 2;
|
||||
}
|
||||
if (!stick.B.locked)
|
||||
{
|
||||
stick.B.position = stickCentre - stickDir * stick.length / 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateOrderArray()
|
||||
{
|
||||
order = new int[rope.sticks.Count];
|
||||
for (int i = 0; i < order.Length; i++)
|
||||
{
|
||||
order[i] = i;
|
||||
}
|
||||
ShuffleArray(order, new System.Random());
|
||||
}
|
||||
|
||||
public static T[] ShuffleArray<T>(T[] array, System.Random prng)
|
||||
{
|
||||
|
||||
int elementsRemainingToShuffle = array.Length;
|
||||
int randomIndex = 0;
|
||||
|
||||
while (elementsRemainingToShuffle > 1)
|
||||
{
|
||||
|
||||
// Choose a random element from array
|
||||
randomIndex = prng.Next(0, elementsRemainingToShuffle);
|
||||
T chosenElement = array[randomIndex];
|
||||
|
||||
// Swap the randomly chosen element with the last unshuffled element in the array
|
||||
elementsRemainingToShuffle--;
|
||||
array[randomIndex] = array[elementsRemainingToShuffle];
|
||||
array[elementsRemainingToShuffle] = chosenElement;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 27ac133d9e10e544ba603e07122e3359
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class Stick
|
||||
{
|
||||
public Point A, B;
|
||||
public float length;
|
||||
public bool dead;
|
||||
|
||||
public Stick(Point pointA, Point pointB)
|
||||
{
|
||||
this.A = pointA;
|
||||
this.B = pointB;
|
||||
length = Vector2.Distance(pointA.position, pointB.position);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 61cc19e8607c5c243941e77804b59b30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue