28-01-2019, 09:03 PM
(28-01-2019, 05:02 PM)crychair Wrote:Code:public void makeRope(Vector3 pos1, Vector3 pos2, GameObject obj1, GameObject obj2) {
GameObject rope = Instantiate(obiRopePrefab);
BetterRopeHelper helper = rope.GetComponent<BetterRopeHelper>();
helper.SetPoints(pos1, pos2);
helper.GenerateRope(obj1, obj2);
}Code:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;
[RequireComponent(typeof(ObiRope))]
[RequireComponent(typeof(ObiCatmullRomCurve))]
public class BetterRopeHelper : MonoBehaviour
{
public ObiSolver solver;
public ObiRopeSection section;
public Material material;
private ObiActor actor;
private ObiRope rope;
private ObiCatmullRomCurve path;
private Vector3 start, end;
public void SetPoints(Vector3 startpoint, Vector3 endpoint)
{
// Get all needed components and interconnect them:
rope = GetComponent<ObiRope>();
path = GetComponent<ObiCatmullRomCurve>();
rope.Solver = solver;
rope.ropePath = path;
rope.section = section;
GetComponent<MeshRenderer>().material = material;
// Calculate rope start/end and direction in local space:
start = startpoint;
end = endpoint;
Vector3 localStart = startpoint;
Vector3 localEnd = endpoint;
Vector3 direction = (localEnd - localStart).normalized;
// Generate rope path:
path.controlPoints.Clear();
path.controlPoints.Add(localStart - direction);
path.controlPoints.Add(localStart);
path.controlPoints.Add(localEnd);
path.controlPoints.Add(localEnd + direction);
}
public void GenerateRope(GameObject obj1, GameObject obj2)
{
// Setup the simulation:
StartCoroutine(Setup(obj1, obj2));
}
IEnumerator Setup(GameObject obj1, GameObject obj2)
{
// Generate particles and add them to solver:
yield return StartCoroutine(rope.GeneratePhysicRepresentationForMesh());
rope.AddToSolver(null);
// Fix first and last particle in place:
//rope.invMasses[0] = 0;
//rope.invMasses[rope.UsedParticles - 1] = 0;
//Oni.SetParticleInverseMasses(solver.OniSolver, new float[] { 0 }, 1, rope.particleIndices[0]);
//Oni.SetParticleInverseMasses(solver.OniSolver, new float[] { 0 }, 1, rope.particleIndices[rope.UsedParticles - 1]);
//rope.PushDataToSolver(ParticleData.INV_MASSES);
//batchConstraints = pinConstraints.GetBatches() as ObiPinConstraintBatch;
//pinConstraints.RemoveFromSolver(null);
//Debug.Log(obj1.name);
//batchConstraints.AddConstraint(0, obj1.GetComponent<ObiCollider>(), Vector3.zero, 0f);
//batchConstraints.AddConstraint(rope.UsedParticles - 1, obj2.GetComponent<ObiCollider>(), Vector3.zero, 0f);
//pinConstraints.AddToSolver(null);
//pinConstraints.PushDataToSolver();
rope.PinConstraints.RemoveFromSolver(null);
ObiPinConstraintBatch batch = (ObiPinConstraintBatch)rope.PinConstraints.GetFirstBatch();
Vector3 offset1 = obj1.transform.InverseTransformPoint(start);
Vector3 offset2 = obj1.transform.InverseTransformPoint(start);
batch.AddConstraint(0, obj1.GetComponent<ObiCollider>(), offset1, 1f);
batch.AddConstraint(rope.UsedParticles - 1, obj2.GetComponent<ObiCollider>(), offset2, 1f);
rope.PinConstraints.AddToSolver(null);
//actor.enabled = true;
}
}
I have the method and helper above and it works. My issue is that I want the rope to be taught on instantiation rather than modifying it after. Is there some way to do this. currently when the rope is generated it become slack and weighs itself down.
Any help is appreciated.
Hi there,
You could perform a few simulation steps in-place after creating the rope, by calling rope.Solver.SimulateStep(deltaTime) in a loop, similar to what the particle editor does. (See the Update() method of ObiParticleActorEditor.cs for reference)
Another, less expensive method is to use the catenary equation to determine initial particle positions. This is the shape adopted by any rope at rest. See:
https://en.wikipedia.org/wiki/Catenary