Obi Official Forum

Full Version: Rope around collider
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hello dear developer,

Using ropes pretty much in project and have currently 2 difficulties:

1)I want to stretch my rope around cubeCollider- but because my rope don't produce new particles while stretching, after some limit, rope pass throught collider obviously- what's the way to do it, so that on release one of the ends rope will return to initial state?

2) For 3d rope cutting using ObiCollisionEventArgs- is there some way to process it without obiRope enabled and turn it on only if the tearing is happening (for optimization Reazons)?
(30-01-2023, 05:30 PM)alex798 Wrote: [ -> ]Hello dear developer,

Using ropes pretty much in project and have currently 2 difficulties:

1)I want to stretch my rope around cubeCollider- but because my rope don't produce new particles while stretching, after some limit, rope pass throught collider obviously- what's the way to do it, so that on release one of the ends rope will return to initial state?

You need to increase/decrease the length of your rope. This is done at runtime using a cursor:
http://obi.virtualmethodstudio.com/manua...ursor.html

(30-01-2023, 05:30 PM)alex798 Wrote: [ -> ]2) For 3d rope cutting using ObiCollisionEventArgs- is there some way to process it without obiRope enabled and turn it on only if the tearing is happening (for optimization Reazons)?

No, it's a chicken-and-egg problem: if the rope is not enabled, it cannot detect whether it's colliding against objects (and hence, be torn) since this detection is not performed if the rope is disabled.

kind regards,
(31-01-2023, 11:47 AM)josemendez Wrote: [ -> ]You need to increase/decrease the length of your rope. This is done at runtime using a cursor:
http://obi.virtualmethodstudio.com/manua...ursor.html


No, it's a chicken-and-egg problem: if the rope is not enabled, it cannot detect whether it's colliding against objects (and hence, be torn) since this detection is not performed if the rope is disabled.

kind regards,

I see- thought that there is some buildIn way- Is there some scripts to calculate lengths based on attached positions or something like this?

Ok- so I will Switch Obi, when Knife enters obi's proximity, dedused as much because Collisions calculates in StepEnd...
(31-01-2023, 02:55 PM)alex798 Wrote: [ -> ]I see- thought that there is some buildIn way- Is there some scripts to calculate lengths based on attached positions or something like this?

Yes, you have rope.CalculateLength() that returns the current length of the rope (including any stretch/compression and attachments) and rope.restLength, that returns the length of the rope at rest.

kind regards,
(31-01-2023, 03:19 PM)josemendez Wrote: [ -> ]Yes, you have rope.CalculateLength() that returns the current length of the rope (including any stretch/compression and attachments) and rope.restLength, that returns the length of the rope at rest.

kind regards,

void Update()
{
if (isGrabbed)
cursor.ChangeLength(rope.CalculateLength());
}

change Length like this- is this right?- because when i grab it becomes too long as it was heavily compressed (with 0 compress in distance). Another problem is gravity- should i stretch only if Calculate is much more than starting, or what? Whats the meaning of restLenght?- I thought that it was starting lenght, but it changes in runtime...

(31-01-2023, 03:19 PM)josemendez Wrote: [ -> ]Yes, you have rope.CalculateLength() that returns the current length of the rope (including any stretch/compression and attachments) and rope.restLength, that returns the length of the rope at rest.

kind regards,
void Update()
{
if (isGrabbed)
{
curLenght = rope.CalculateLength();
if (curLenght - prevCalculated > delta)
{
prevCalculated = curLenght;
cursor.ChangeLength(prevCalculated);
}
}
}

Adjusted to change only on armstretch, but now have a problem, that if our arms becomes closer the lenght don't shorten- I'd use armsTransforms instead of ropeCalculate, but in that case will be problem with stretching around object- armsPositions.magnitude can be small- any suggestions?

(31-01-2023, 04:20 PM)alex798 Wrote: [ -> ]void Update()
{
if (isGrabbed)
cursor.ChangeLength(rope.CalculateLength());
}

change Length like this- is this right?- because when i grab it becomes too long as it was heavily compressed (with 0 compress in distance). Another problem is gravity- should i stretch only if Calculate is much more than starting, or what? Whats the meaning of restLenght?- I thought that it was starting lenght, but it changes in runtime...

void Update()
{
if (isGrabbed)
{
curLenght = rope.CalculateLength();
if (curLenght - prevCalculated > delta)
{
prevCalculated = curLenght;
cursor.ChangeLength(prevCalculated);
}
}
}

Adjusted to change only on armstretch, but now have a problem, that if our arms becomes closer the lenght don't shorten- I'd use armsTransforms instead of ropeCalculate, but in that case will be problem with stretching around object- armsPositions.magnitude can be small- any suggestions?


Is There any parameter as distance between particles- ideally normalized- then if distance is big- add particles to said limit, and visaVersa?
(31-01-2023, 04:20 PM)alex798 Wrote: [ -> ]void Update()
{
if (isGrabbed)
cursor.ChangeLength(rope.CalculateLength());
}

change Length like this- is this right?- because when i grab it becomes too long as it was heavily compressed (with 0 compress in distance). Another problem is gravity- should i stretch only if Calculate is much more than starting, or what?

Nope, doing this will result in the rope increasing its length non-stop. The reason is simple: any small force applied to the rope that stretches it even if it's a tiny bit, will cause the rope to increase its rest length to "absorb" the stretching.

You should only ChangeLength() when the calculated length exceeds the restLength by some predefined amount > 0.

(31-01-2023, 04:20 PM)alex798 Wrote: [ -> ]Whats the meaning of restLenght?- I thought that it was starting lenght, but it changes in runtime...

"restLength" is the length that the rope at rest, as the name implies. It changes as a result of calling ChangeLength() because...well, it changes the rope's length Sonrisa.

(31-01-2023, 04:20 PM)alex798 Wrote: [ -> ]Adjusted to change only on armstretch, but now have a problem, that if our arms becomes closer the lenght don't shorten- I'd use armsTransforms instead of ropeCalculate, but in that case will be problem with stretching around object- armsPositions.magnitude can be small- any suggestions?

Try to reduce your rope's length by a small amount every frame, to constantly "reel" it in. Only increase its length if it gets too stretched. There's an included utility script that does this, pasting it here for your convenience:

Code:
[RequireComponent(typeof(ObiRopeCursor))]
    public class ObiRopeReel : MonoBehaviour
    {
        private ObiRopeCursor cursor;
        private ObiRope rope;

        [Header("Roll out/in thresholds")]
        public float outThreshold = 0.8f;
        public float inThreshold = 0.4f;

        [Header("Roll out/in speeds")]
        public float outSpeed = 0.05f;
        public float inSpeed = 0.15f;

        public void Awake()
        {
            cursor = GetComponent<ObiRopeCursor>();
            rope = GetComponent<ObiRope>();
        }

        public void OnValidate()
        {
            // Make sure the range thresholds don't cross:
            outThreshold = Mathf.Max(inThreshold, outThreshold);
        }

        // Update is called once per frame
        void Update()
        {
            // get current and rest lengths:
            float length = rope.CalculateLength();
            float restLength = rope.restLength;

            // calculate difference between current length and rest length:
            float diff = Mathf.Max(0, length - restLength);

            // if the rope has been stretched beyond the reel out threshold, increase its rest length:
            if (diff > outThreshold)
                restLength += diff * outSpeed;

            // if the rope is not stretched past the reel in threshold, decrease its rest length:
            if (diff < inThreshold)
                restLength -= diff * inSpeed;

            // set the new rest length:
            cursor.ChangeLength(restLength);
        }
    }
(31-01-2023, 09:38 PM)josemendez Wrote: [ -> ]Nope, doing this will result in the rope increasing its length non-stop. The reason is simple: any small force applied to the rope that stretches it even if it's a tiny bit, will cause the rope to increase its rest length to "absorb" the stretching.

You should only ChangeLength() when the calculated length exceeds the restLength by some predefined amount > 0.


"restLength" is the length that the rope at rest, as the name implies. It changes as a result of calling ChangeLength() because...well, it changes the rope's length Sonrisa.


Try to reduce your rope's length by a small amount every frame, to constantly "reel" it in. Only increase its length if it gets too stretched. There's an included utility script that does this, pasting it here for your convenience:

Code:
[RequireComponent(typeof(ObiRopeCursor))]
    public class ObiRopeReel : MonoBehaviour
    {
        private ObiRopeCursor cursor;
        private ObiRope rope;

        [Header("Roll out/in thresholds")]
        public float outThreshold = 0.8f;
        public float inThreshold = 0.4f;

        [Header("Roll out/in speeds")]
        public float outSpeed = 0.05f;
        public float inSpeed = 0.15f;

        public void Awake()
        {
            cursor = GetComponent<ObiRopeCursor>();
            rope = GetComponent<ObiRope>();
        }

        public void OnValidate()
        {
            // Make sure the range thresholds don't cross:
            outThreshold = Mathf.Max(inThreshold, outThreshold);
        }

        // Update is called once per frame
        void Update()
        {
            // get current and rest lengths:
            float length = rope.CalculateLength();
            float restLength = rope.restLength;

            // calculate difference between current length and rest length:
            float diff = Mathf.Max(0, length - restLength);

            // if the rope has been stretched beyond the reel out threshold, increase its rest length:
            if (diff > outThreshold)
                restLength += diff * outSpeed;

            // if the rope is not stretched past the reel in threshold, decrease its rest length:
            if (diff < inThreshold)
                restLength -= diff * inSpeed;

            // set the new rest length:
            cursor.ChangeLength(restLength);
        }
    }

Thanks a lot, but now have another problem- created particles create weight that affected by gravity create more stretch- in some cases it ruin rope... And this new gravity stretch prevent rope to rollBack restLenght. Tryed to create 0 weight particle and clone it, but in this case particles don't stretch parallel (because of weight difference)...
(01-02-2023, 10:51 AM)alex798 Wrote: [ -> ]Thanks a lot, but now have another problem- created particles create weight that affected by gravity create more stretch- in some cases it ruin rope... And this new gravity stretch prevent rope to rollBack restLenght. Tryed to create 0 weight particle and clone it, but in this case particles don't stretch parallel (because of weight difference)...

Mass/weight doesn't work like this, and is not at all the reason why the rope is stretching.

By itself, mass doesn't affect at all the dynamics of an object: have two objects of the same mass collide with each other, and the results will be identical regardless of them being both 10, 100, or 1000 kg. The important part is their mass ratio: how much mass one of them has compared to the other.

Same in a rope: reducing the weight of all particles won't make the rope stretch lessĀ  (and increasing mass doesn't make it stretch more) since the mass distribution is still exactly the same across all particles. If only some particles in the rope have higher mass than the rest, these will "pull" the rest of the rope around which can be useful in some situations.

Also note mass doesn't affect gravity at all: gravity is an acceleration (not a force), so all objects fall at the same speed regardless of their mass. No matter how heavy your rope is or how many particles are in it, gravity will always make it fall at the same speed.

The stretching you're experiencing is a basic consequence of how physics engines work: the more constraints an engine needs to simulate (in a rope, constraints are the "links" holding particles together), the slower convergence becomes. This is because corrections on a body (particle) need to "propagate" to neighboring bodies trough constraints over multiple iterations: the more constraints you have, the longer it takes for corrections to propagate to all particles in the rope because they have to traverse a path with more steps in it.

In some engines (like Unity's built-in engine), this low convergence speed manifests as instabilities: jittering, dancing objects, explosions, etc, because object velocities can't be corrected fast enough. In others like Obi, it manifests as spurious elasticity: things become stretchy/soft, because positional corrections can't be propagated across all particles given the current simulation budget. This is why you can't have arbitrarily long ropes at fixed cost: at some point you have to limit their length, or spend more resources simulating them, or reduce their resolution (less particles->less constraints).

There's two ways to fix this: increase the amount of distance constraint iterations in your ObiSolver (to spend more time propagating constraint corrections, which will allow these to reach further along the rope) or increase the amount of substeps in your ObiFixedUpdater to reduce the amount of correction required in the first place.

The manual contains a very in-depth explanation of what iterations/substeps are and how they affect simulation quality: http://obi.virtualmethodstudio.com/manua...gence.html

kind regards,
(01-02-2023, 11:13 AM)josemendez Wrote: [ -> ]Mass/weight doesn't work like this, and is not at all the reason why the rope is stretching.

By itself, mass doesn't affect at all the dynamics of an object: have two objects of the same mass collide with each other, and the results will be identical regardless of them being both 10, 100, or 1000 kg. The important part is their mass ratio: how much mass one of them has compared to the other.

Same in a rope: reducing the weight of all particles won't make the rope stretch lessĀ  (and increasing mass doesn't make it stretch more) since the mass distribution is still exactly the same across all particles. If only some particles in the rope have higher mass than the rest, these will "pull" the rest of the rope around which can be useful in some situations.

Also note mass doesn't affect gravity at all: gravity is an acceleration (not a force), so all objects fall at the same speed regardless of their mass. No matter how heavy your rope is or how many particles are in it, gravity will always make it fall at the same speed.

The stretching you're experiencing is a basic consequence of how physics engines work: the more constraints an engine needs to simulate (in a rope, constraints are the "links" holding particles together), the slower convergence becomes. This is because corrections on a body (particle) need to "propagate" to neighboring bodies trough constraints over multiple iterations: the more constraints you have, the longer it takes for corrections to propagate to all particles in the rope because they have to traverse a path with more steps in it.

In some engines (like Unity's built-in engine), this low convergence speed manifests as instabilities: jittering, dancing objects, explosions, etc, because object velocities can't be corrected fast enough. In others like Obi, it manifests as spurious elasticity: things become stretchy/soft, because positional corrections can't be propagated across all particles given the current simulation budget. This is why you can't have arbitrarily long ropes at fixed cost: at some point you have to limit their length, or spend more resources simulating them, or reduce their resolution (less particles->less constraints).

There's two ways to fix this: increase the amount of distance constraint iterations in your ObiSolver (to spend more time propagating constraint corrections, which will allow these to reach further along the rope) or increase the amount of substeps in your ObiFixedUpdater to reduce the amount of correction required in the first place.

The manual contains a very in-depth explanation of what iterations/substeps are and how they affect simulation quality: http://obi.virtualmethodstudio.com/manua...gence.html

kind regards,

I reduced obiSolver gravity to -5 (half) and it looks better- at least I don't crash rope after this manipulation this easily... Also tryed your solution of constraint- doubled them or made relaxation to 2, but there were some unwanted behaviours- can't recall them now,,,
(01-02-2023, 11:45 AM)alex798 Wrote: [ -> ]I reduced obiSolver gravity to -5 (half) and it looks better- at least I don't crash rope after this manipulation this easily... Also tryed your solution of constraint- doubled them or made relaxation to 2, but there were some unwanted behaviours- can't recall them now,,,

Reducing gravity will make your rope look "floatier" and won't help at all with convergence, but if it works for you, it works for you Sonrisa

Setting relaxation to 2 will almost certainly result in jittering and instabilities in your case. Best keep it within the 1-1.3 range unless you're absolutely sure what you're doing.

As for increasing the amount of iterations/substeps, there should be no adverse effects, let me know if you need further help.

cheers!
Pages: 1 2