public void ChangeLength(float newLength) { if (!rope.isLoaded) { return; } var solver = rope.solver; // clamp new length to sane limits: newLength = Mathf.Clamp(newLength, 0, (rope.sourceBlueprint.particleCount - 1) * rope.ropeBlueprint.interParticleDistance); // calculate the change in rope length: float lengthChange = newLength - rope.restLength; // remove: if (lengthChange < 0) { lengthChange = -lengthChange; while (lengthChange > m_CursorElement.restLength) { lengthChange -= m_CursorElement.restLength; int index = rope.elements.IndexOf(m_CursorElement); if (index >= 0) { // positive direction: if (direction) { RemoveParticleAt(solver.particleToActor[m_CursorElement.particle2].indexInActor); rope.elements.RemoveAt(index); if (index < rope.elements.Count) { if (rope.elements[index].particle1 == m_CursorElement.particle2) { rope.elements[index].particle1 = m_CursorElement.particle1; } m_CursorElement = rope.elements[index]; } else { m_CursorElement = rope.elements[Mathf.Max(0, index - 1)]; } } else // negative direction: { RemoveParticleAt(solver.particleToActor[m_CursorElement.particle1].indexInActor); rope.elements.RemoveAt(index); if (index > 0) { if (rope.elements[index - 1].particle2 == m_CursorElement.particle1) { rope.elements[index - 1].particle2 = m_CursorElement.particle2; } m_CursorElement = rope.elements[index - 1]; } else { m_CursorElement = rope.elements[0]; } } } } // the remaining length is subtracted from the current constraint: if (lengthChange > 0) { m_CursorElement.restLength = Mathf.Max(0, m_CursorElement.restLength - lengthChange); } } // add else { float lengthDelta = Mathf.Min(lengthChange, Mathf.Max(0, rope.ropeBlueprint.interParticleDistance - m_CursorElement.restLength)); // extend the current element, if possible: if (lengthDelta > 0) { m_CursorElement.restLength += lengthDelta; lengthChange -= lengthDelta; } // once the current element has been extended, see if we must add new elements, if there's enough particles left: while (rope.activeParticleCount < rope.sourceBlueprint.particleCount && m_CursorElement.restLength + lengthChange > rope.ropeBlueprint.interParticleDistance) { // calculate added length: lengthDelta = Mathf.Min(lengthChange, rope.ropeBlueprint.interParticleDistance); lengthChange -= lengthDelta; if (direction) { // add new particle: int newParticleSolverIndex = AddParticleAt(solver.particleToActor[m_CursorElement.particle1].indexInActor); // set position of the new particle: solver.positions[newParticleSolverIndex] = solver.positions[m_CursorElement.particle1] + (solver.positions[m_CursorElement.particle2] - solver.positions[m_CursorElement.particle1]) * lengthDelta; // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = m_CursorElement.particle1; newElement.particle2 = newParticleSolverIndex; m_CursorElement.particle1 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index, newElement); m_CursorElement = newElement; } else { // add new particle: int newParticleSolverIndex = AddParticleAt(solver.particleToActor[m_CursorElement.particle2].indexInActor); // set position of the new particle: solver.positions[newParticleSolverIndex] = solver.positions[m_CursorElement.particle2] + (solver.positions[m_CursorElement.particle1] - solver.positions[m_CursorElement.particle2]) * lengthDelta; // insert a new element: ObiStructuralElement newElement = new ObiStructuralElement(); newElement.restLength = lengthDelta; newElement.particle1 = newParticleSolverIndex; newElement.particle2 = m_CursorElement.particle2; m_CursorElement.particle2 = newParticleSolverIndex; int index = rope.elements.IndexOf(m_CursorElement); rope.elements.Insert(index + 1, newElement); m_CursorElement = newElement; } } // the remaining length is added to the current constraint: if (lengthChange > 0) { m_CursorElement.restLength += lengthChange; } } // recalculate rest positions and length prior to constraints (bend constraints need rest positions): rope.RecalculateRestPositions(); rope.RecalculateRestLength(); // rebuild constraints: rope.RebuildConstraintsFromElements(); }