Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bug / Crash  ObiRopeCursor.ChangeLength causes IndexOutOfRangeExceptions
#1
I'm trying to create a harpoon gun which is launched from a flying drone and hooks into whatever it collides with. The rope blueprint looks like this:

   

To shoot the harpoon, I'm starting with a very short rope, and increasing the length of the rope along with the velocity of the tip of my harpoon in FixedUpdate. The rope is attached to both the drone and the harpoon tip via ObiParticleAttachment.

Code:
using Obi;
using UnityEngine;

public class HarpoonLauncher : MonoBehaviour
{
    public ObiRopeCursor ropeCursor;
    public float HarpoonVelocity = 10f;
    public HarpoonTip HarpoonTip;
    public Transform HarpoonConnection;
    public Transform TipSpawnPosition;
    public ObiSolver ObiSolver;
    public ObiRope Rope;
    public float InitialRopeLength = 1f;
    public float MaxRopeLength = 5f;
    public ObiParticleAttachment TipAttachment, DroneAttachment;

    public ObiRopeBlueprint RopeBlueprint;
    bool isShooting = false;

    // Start is called before the first frame update
    void Start() {
        InitialRopeLength = Rope.restLength;

        HarpoonTip.OnHarpoonEnter += WhenHarpoonImpacts;
    }

    private void OnDestroy() {
        HarpoonTip.OnHarpoonEnter -= WhenHarpoonImpacts;
    }

    private void WhenHarpoonImpacts(HarpoonTip source, Collider impact) {
        isShooting = false;
        // Readjust length after impact
        ropeCursor.ChangeLength((TipSpawnPosition.position - HarpoonTip.transform.position).magnitude + .02f);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) {
            ObiSolver.gameObject.SetActive(true);
            HarpoonTip.gameObject.SetActive(true);
            ropeCursor.ChangeLength(InitialRopeLength);
            HarpoonTip.transform.position = TipSpawnPosition.position;
            Vector3 velo = TipSpawnPosition.forward * HarpoonVelocity;
            HarpoonTip.Fire(velo);
            //Rope.SetMass(.01f);
            isShooting = true;
        }
    }

    private void FixedUpdate() {
        if (isShooting) {
            Debug.Log($"{Rope.restLength}");
            if (Rope.restLength >= MaxRopeLength) {
                isShooting = false;
            }
            else {
                //Rope.SetMass(.01f);
                ropeCursor.ChangeLength(Rope.restLength + HarpoonTip.GetComponent<Rigidbody>().velocity.magnitude * Time.fixedDeltaTime);
                //CurrentRopeLength += HarpoonTip.velocity.magnitude;
            }
        }
    }
}


When I run this code, i get an IndexOutOfRangeExceptions in FixedUpdate after shooting the harpoon:
Quote:IndexOutOfRangeException: Index was outside the bounds of the array.
Obi.ObiActor.SwapWithFirstInactiveParticle (System.Int32 actorIndex) (at Assets/Obi/Scripts/Common/Actors/ObiActor.cs:420)
Obi.ObiActor.ActivateParticle (System.Int32 actorIndex) (at Assets/Obi/Scripts/Common/Actors/ObiActor.cs:434)
Obi.ObiRopeCursor.AddParticleAt (System.Int32 index) (at Assets/Obi/Scripts/RopeAndRod/Actors/ObiRopeCursor.cs:118)
Obi.ObiRopeCursor.ChangeLength (System.Single newLength) (at Assets/Obi/Scripts/RopeAndRod/Actors/ObiRopeCursor.cs:203)
HarpoonLauncher.FixedUpdate () (at Assets/Scripts/HarpoonLauncher.cs:60)

However the rope length still seems to change! So what am I doing wrong here?
Reply
#2
I discovered some new information which may help fix this bug. I think it is related to the cursor not updating the particle index it is pointing to when the length of the rope is changed. I did a test where I created a rope with a cursor, and set the cursorMu to .5

Then I slowly reduced the length of the rope with cursor.ChangeLength(). Reliably, the error occurs after the length starts getting shorter than 1/2 of the original rope length. In other words, the cursor is pointing off the end of the rope!

(Ignore the unrelated NullRefException at the top)
   

I was able to workaround the issue for now by setting the cursorMu every time just before calling ChangeLength().
Reply