Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Resetting Rope causing Error
#1
Hi,

This is my old code that I got from this forum to reset the rope back to its original state.

Code:
float initialLength = 0.88f
ObiRopeCursor ropeCursor;
ObiRope rope;

public void ResetRope()
    {
        rope.RemoveFromSolver();
        rope.ClearState();
        rope.AddToSolver();
        ropeCursor.ChangeLength(initialLength);
    }


Now since the new update has changed the ChangeLength() method my new code becomes.

Code:
public void ResetRope()
    {
        rope.RemoveFromSolver();
        rope.ClearState();
        rope.AddToSolver();
        ropeCursor.ChangeLength(initialLength - rope.restLength);
    }

But its causing error, rope disappears and I get

Code:
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <bae5e84a08394aad9eb61062d3ccb3ca>:0)
Obi.ObiPathSmootherRenderSystem.Setup () (at Assets/Obi/Scripts/RopeAndRod/Rendering/ObiPathSmootherRenderSystem.cs:163)
Obi.ObiRenderSystemStack.Setup (System.Int32 dirtyFlags) (at Assets/Obi/Scripts/Common/Solver/ObiRenderSystemStack.cs:27)
Obi.ObiSolver.Render (System.Single unsimulatedTime) (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1784)
Obi.ObiSolver.LateUpdate () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1163)

If I remove 

Code:
rope.RemoveFromSolver();
rope.ClearState();
rope.AddToSolver();

Then error goes away but I dont get starting initial state like before
Reply
#2
Okay I have solved the issue by using the following new code


Code:
public void ResetRope()
    {
        rope.ResetParticles();
        ropeCursor.ChangeLength(initialLength - rope.restLength);
    }

I didn't knew about ResetParticles() before, is there is any major difference between my previous and new approach. It seems to does the trick for me.
Reply
#3
(07-08-2024, 07:13 AM)vrtraining Wrote: Okay I have solved the issue by using the following new code


Code:
public void ResetRope()
    {
        rope.ResetParticles();
        ropeCursor.ChangeLength(initialLength - rope.restLength);
    }

I didn't knew about ResetParticles() before, is there is any major difference between my previous and new approach. It seems to does the trick for me.

Hi!

ResetParticles() is much faster, as it doesn't take the entire rope out of the solver and then re-add it: it just resets particle data to whatever's in the blueprint. RemoveFromSolver()/AddToSolver() would destroy all particle/constraint data for that actor and recreate it anew, and trigger a full rebatching of all constraints in the solver.

However, ResetParticles won't reset constraints or elements (it only resets particles as the name implies) so if you're changing the length or the rope -which means constraints and elements are added at runtime- it won't work.

Also be mindful of *when* you call RemoveFromSolver() / AddToSolver(). In Obi 6 these are safe to be called anytime except FixedUpdate(), in Obi 7 calling them during Update() would result in them being called while the simulation is running, and you'd be pulling the rug from under the simulation's feet by modifying state from the main thread.

We'll upload updated API docs for Obi 7 later today, were these differences are highlighted.

kind regards,
Reply
#4
(07-08-2024, 08:06 AM)josemendez Wrote: Hi!

ResetParticles() is much faster, as it doesn't take the entire rope out of the solver and then re-add it: it just resets particle data to whatever's in the blueprint. RemoveFromSolver()/AddToSolver() would destroy all particle/constraint data for that actor and recreate it anew, and trigger a full rebatching of all constraints in the solver.

However, ResetParticles won't reset constraints or elements (it only resets particles as the name implies) so if you're changing the length or the rope -which means constraints and elements are added at runtime- it won't work.

Also be mindful of *when* you call RemoveFromSolver() / AddToSolver(). In Obi 6 these are safe to be called anytime except FixedUpdate(), in Obi 7 calling them during Update() would result in them being called while the simulation is running, and you'd be pulling the rug from under the simulation's feet by modifying state from the main thread.

We'll upload updated API docs for Obi 7 later today, were these differences are highlighted.

kind regards,

Thanks, it seems to be working fine for now. Like I reset particles and then I change length back to initial in very next line. I get the rope back at initial position with same length. You are saying it won't work, it means there could be some issue with it?
Reply
#5
(07-08-2024, 08:47 AM)vrtraining Wrote: Thanks, it seems to be working fine for now. Like I reset particles and then I change length back to initial in very next line. I get the rope back at initial position with same length. You are saying it won't work, it means there could be some issue with it?

The key thing to keep in mind is that the amount of particles in the blueprint and the amount of particles in the current rope may be different, if you're resizing the rope before calling ResetParticles().

Say you have 10 particles in the blueprint. You instantiate a rope using this blueprint, then increase its length so that it has 15 particles. After that you call ResetParticles(): this will set the position/orientation/velocity of the first 10 particles to match the blueprint, but will leave the extra 5 particles alone. It won't reset the length of the rope to what it previously was - won't destroy/add particles, constraints or elements.

As long as your logic takes this into account it will be fine.

kind regards,
Reply
#6
(07-08-2024, 09:38 AM)josemendez Wrote: The key thing to keep in mind is that the amount of particles in the blueprint and the amount of particles in the current rope may be different, if you're resizing the rope before calling ResetParticles().

Say you have 10 particles in the blueprint. You instantiate a rope using this blueprint, then increase its length so that it has 15 particles. After that you call ResetParticles(): this will set the position/orientation/velocity of the first 10 particles to match the blueprint, but will leave the extra 5 particles alone. It won't reset the length of the rope to what it previously was - won't destroy/add particles, constraints or elements.

As long as your logic takes this into account it will be fine.

kind regards,

Thanks, and if i resize it after calling ResetParticles() then it will delete the other 5 right?

What could be an OBI7 solution to?

Quote:public void ResetRope()
    {
        rope.RemoveFromSolver();
        rope.ClearState();
        rope.AddToSolver();
        ropeCursor.ChangeLength(initialLength - rope.restLength);
    }

that resets the rope and constraints everything to bring it back to initial state fully?
Reply
#7
(07-08-2024, 09:40 AM)vrtraining Wrote: Thanks, and if i resize it after calling ResetParticles() then it will delete the other 5 right?

Correct.

(07-08-2024, 09:40 AM)vrtraining Wrote: What could be an OBI7 solution to?

that resets the rope and constraints everything to bring it back to initial state fully?

This code should work fine in Obi 7 as well, as long as you don't call it while the simulation is being performed in other threads. Just tried calling it in Update() and it works fine for me. When/how are you calling ResetRope()?
Reply
#8
(07-08-2024, 10:20 AM)josemendez Wrote: This code should work fine in Obi 7 as well, as long as you don't call it while the simulation is being performed in other threads. Just tried calling it in Update() and it works fine for me. When/how are you calling ResetRope()?

Its called from an event but eventually that is propagated from Update method. It works fine as long as I don't resize the rope. If I increase the rope length and call it then it crashes in Obi 7
Reply
#9
(07-08-2024, 10:45 AM)vrtraining Wrote: Its called from an event but eventually that is propagated from Update method. It works fine as long as I don't resize the rope. If I increase the rope length and call it then it crashes in Obi 7

I've tried with and without calling ChangeLength(), doesn't make any difference for me. This is the code I'm using, which is nearly identical to yours:

Code:
using UnityEngine;
using Obi;

public class ResetRope : MonoBehaviour
{
    public float initialLength = 3;
    public ObiRope rope;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
            Reset();
    }

    public void Reset()
    {
        rope.RemoveFromSolver();
        rope.ClearState();
        rope.AddToSolver();
        rope.GetComponent<ObiRopeCursor>().ChangeLength(initialLength - rope.restLength);
    }
}
Reply
#10
Just realized there's an issue with both the above code and yours (in both Obi 6 and 7): it's not waiting for the rope to be actually loaded by the solver. So when called several times in a row the rest length may not be the length reflected in the blueprint, but the previous length of the rope. Won't cause any runtime errors, but the resulting length of the rope may not be correct.

Simply waiting for the rope to be loaded before changing its length fixes this:

Code:
using UnityEngine;
using Obi;
using System.Collections;

public class ResetRope : MonoBehaviour
{
    public float initialLength = 3;
    public ObiRope rope;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
            StartCoroutine(Reset());
    }

    public IEnumerator Reset()
    {
        rope.RemoveFromSolver();
        rope.ClearState();
        rope.AddToSolver();

        while (!rope.isLoaded)
            yield return new WaitForEndOfFrame();

        rope.GetComponent<ObiRopeCursor>().ChangeLength(initialLength - rope.restLength);
    }
}
Reply