Hello!
I am having a problem where I'm extending a rope like ExtendableGrapplingHook.cs example.
Mine is a little different in that the rope is a fixed length. If the end particle (i.e. Hook) doesn't hit anything while the rope is extending it will just flop to the ground.
When first extending, I am using the same method of extending the rope.. basically LayParticlesInStraightLine() function from the Grappling Hook example.
I'm using the OnCollision callback to check if the rope's last/end particle hit something while extending.
If the end particle collides with something it can "Grapple", I add an ObiParticleAttachment to the last particle, and connect it to the object it collided with.
I will then stop LayParticlesInStraightLine, and just finish deploying the rope from the base until it's fully extended.
The problem is that the end of the rope sometimes passes through the object before the attachment can happen. It should connect at the exact point it first touched the object, but it sometimes attaches half-way through or even sometimes on the opposite side.
I have tried increasing the Collision constraint Iterations but it doesn't seem to help much. I suspect I'm doing something wrong..
Below are the functions I'm using to extend my rope (aka grappling hook) and where I check OnCollision callback for that last particle contact..
Any help would be appreciated as always!!
I am having a problem where I'm extending a rope like ExtendableGrapplingHook.cs example.
Mine is a little different in that the rope is a fixed length. If the end particle (i.e. Hook) doesn't hit anything while the rope is extending it will just flop to the ground.
When first extending, I am using the same method of extending the rope.. basically LayParticlesInStraightLine() function from the Grappling Hook example.
I'm using the OnCollision callback to check if the rope's last/end particle hit something while extending.
If the end particle collides with something it can "Grapple", I add an ObiParticleAttachment to the last particle, and connect it to the object it collided with.
I will then stop LayParticlesInStraightLine, and just finish deploying the rope from the base until it's fully extended.
The problem is that the end of the rope sometimes passes through the object before the attachment can happen. It should connect at the exact point it first touched the object, but it sometimes attaches half-way through or even sometimes on the opposite side.
I have tried increasing the Collision constraint Iterations but it doesn't seem to help much. I suspect I'm doing something wrong..
Below are the functions I'm using to extend my rope (aka grappling hook) and where I check OnCollision callback for that last particle contact..
Any help would be appreciated as always!!
Code:
IEnumerator ExtendTetherCR()
{
yield return null; //skip a step. then go.
extending = true;
extended = false;
retracting = false;
retracted = false;
lastParticleContact = false;
// Procedurally generate the rope path (just a short segment, as we will extend it over time):
int filter = ObiUtils.MakeFilter(collidesWithMask, collisionCategory);
blueprint.path.Clear();
blueprint.path.AddControlPoint(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.up, sectionMass, sectionRotMass, 0.1f, filter, Color.white, "Start");
blueprint.path.AddControlPoint(localDirection * 0.1f, Vector3.zero, Vector3.zero, Vector3.up, sectionMass, sectionRotMass, 0.1f, filter, Color.white, "End");
blueprint.path.FlushEvents();
// Generate the particle representation of the rope (wait until it has finished):
yield return blueprint.Generate();
// Set the blueprint (this adds particles/constraints to the solver and starts simulating them).
rope.ropeBlueprint = blueprint;
rope.GetComponent<ObiRopeExtrudedRenderer>().enabled = true;
yield return new WaitForFixedUpdate();
yield return null;
shipPA = rope.gameObject.AddComponent<ObiParticleAttachment>();
ObiParticleGroup startPG = rope.ropeBlueprint.groups[0];
shipPA.target = shipAttachment.transform;
shipPA.particleGroup = startPG;
shipPA.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
cursor = rope.gameObject.AddComponent<ObiRopeCursor>();
cursor.cursorMu = 0.0f; //Mu=0 means the start of the rope. .05 is the middle of the rope.
cursor.direction = true; //true means we extend from start to end.
//Debug.Log("Entend: rope.elements.Count: " + rope.elements.Count);
Vector3 direction = tetherDirectionHandle.transform.localPosition.normalized;
while (true )
{
Vector3 origin = solver.transform.InverseTransformPoint(rope.transform.position);
float length = 0;
if(!lastParticleContact)
{
for (int i = 0; i < rope.elements.Count; ++i)
{
int p1 = rope.elements[i].particle1;
int p2 = rope.elements[i].particle2;
solver.prevPositions[p1] = solver.positions[p1] = origin + direction * length;
length += rope.elements[i].restLength;
solver.prevPositions[p2] = solver.positions[p2] = origin + direction * length;
}
}
float distanceLeft = tetherTargetLength - cursor.ChangeLength(tetherShootSpeed * Time.deltaTime);
//Debug.Log("distanceLeft: " + distanceLeft);
if (distanceLeft < 0 )
{
cursor.cursorMu = 1.0f;
cursor.ChangeLength(distanceLeft);
break;
}
yield return null;
}
yield return new WaitForFixedUpdate();
yield return null;
extending = false;
extended = true;
retracting = false;
retracted = false;
}Code:
void Solver_OnCollision(object sender, ObiNativeContactList e)
{
///no need to check collisions if the tether is currently connected to something or in the process of retracting..
if (otherPA != null || retracting)
return;
//Debug.Log("Sender name: " + sender.ToString());
var world = ObiColliderWorld.GetInstance();
//iterate over all contacts in the current frame:
foreach (Oni.Contact contact in e)
{
// if this one is an actual collision:
if (contact.distance < collisionDistance)
{
ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;
if (col != null)
{//if we are here we know particles are colliding with something..
//Debug.Log("ObiRope Colliding with something: " + col.gameObject.name);
if (rope.solver.simplices[contact.bodyA] == rope.elements[rope.elements.Count - 1].particle2)
{//if we are here we know it's the last particle in the rope that collided with something. Stop exending in the handle direction now!
//Debug.Log("Rope Last Particle Contacted: " + col.gameObject.name);
lastParticleContact = true;
//if (col.gameObject.layer == 15)
if ((attachmentMask & (1 << col.gameObject.layer)) != 0)
{//if we are here, we know the last particle in the rope should attach to what it collided with!
otherPA = rope.gameObject.AddComponent<ObiParticleAttachment>();
ObiParticleGroup endPG = rope.ropeBlueprint.groups[1];
otherPA.target = col.transform;
otherPA.particleGroup = endPG;
otherPA.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
//Debug.Log("Tether attached!");
}
}
}
}
}
}
