09-08-2024, 09:40 AM
Wrote this reply on another thread but I think it is relevant.
I made a script for my game that connects multiple targets to a defined spline as an attachment. The rope is able to feed through the attachment with a desired friction.
Here's the code where the magic happens, maybe that can help you. The lambda for the distance constraint can be interpreted as the force stretching the rope element if you divide by time squared. Instead of manipulating _positionInElement and _elementIndex, I guess you want to update the cursor script instead.
I made a script for my game that connects multiple targets to a defined spline as an attachment. The rope is able to feed through the attachment with a desired friction.
Here's the code where the magic happens, maybe that can help you. The lambda for the distance constraint can be interpreted as the force stretching the rope element if you divide by time squared. Instead of manipulating _positionInElement and _elementIndex, I guess you want to update the cursor script instead.
Code:
float sqrTime = stepTime * stepTime;
float forwardForce = -SolverLambda(startElement, solverConstraints) / sqrTime;
float backwardForce = -SolverLambda(endElement, solverConstraints) / sqrTime;
float totalForce = forwardForce - backwardForce;
if (totalForce > ForwardFriction) ApplyForceToMovement(totalForce - ForwardFriction, sqrTime);
else if (totalForce < -BackwardFriction) ApplyForceToMovement(totalForce + BackwardFriction, sqrTime);
Code:
private float SolverLambda(int elementIndex, ObiConstraints<ObiDistanceConstraintsBatch> solverConstraints)
{
int batchCount = solverConstraints.GetBatchCount();
int index = elementIndex / batchCount;
int batchIndex = elementIndex % batchCount;
int offset = _rope.solverBatchOffsets[(int)Oni.ConstraintType.Distance][batchIndex];
return solverConstraints.batches[batchIndex].lambdas[offset + index];
}
Code:
private void ApplyForceToMovement(float force, float sqrTime)
{
float movement = (force) * sqrTime;
movement = Mathf.Lerp(movement, 0, _movemementDamping);
int startElement = Mathf.Clamp(_elementIndex - 1, 0, _rope.elements.Count - 1);
float movementInElement = movement / _rope.elements[startElement].restLength;
_positionInElement += movementInElement;
if (_positionInElement < 0)
{
_positionInElement += 1f;
_positionInElement *= _rope.elements[startElement].restLength;
_elementIndex--;
_positionInElement /= _rope.elements[startElement].restLength;
} else if (_positionInElement > 1f)
{
_positionInElement -= 1f;
_positionInElement *= _rope.elements[startElement].restLength;
_elementIndex++;
_positionInElement /= _rope.elements[startElement].restLength;
}
_position = _elementIndex + _positionInElement;
}