Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
IndexOutOfRangeException in CurvySplineSegment.LocalFToDistance function
(03-15-2021, 02:58 AM)mchangxe Wrote: Maybe theres some secret connection in between splines im not aware of?

That would highly surprise me, but only the investigation will say for sure. Will hopefully start working on this by the end of the week.
By the way, is "Use Threading" active in your scene's splines? If so, can you test with that option disabled?
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Sorry for taking this long.
Please replace the implementation of getApproximationIndexINTERNAL with this:

public int getApproximationIndexINTERNAL(float localF, out float frag)
                float testFrag;
                float testIndex;
                float clampedLocalF = Mathf.Clamp01(localF);
                if (clampedLocalF == 1)
                    testFrag = 1;
                    testIndex = Mathf.Max(0, Approximation.Length - 2);
                    float testf = clampedLocalF * (Approximation.Length - 1);
                    testIndex = (int)testf;
                    testFrag = testf - testIndex;

                    if (testIndex > Approximation.Length - 2)
                        Debug.LogError($"input: {localF:R} clamped: {clampedLocalF:R} f: {testf:R} frag:{testFrag:R} index: {testIndex:R}");

            float f = localF / mStepSize;
            int idx = Math.Max(0, Math.Min((int)f, Approximation.Length - 2));
            frag = Mathf.Max(0, Mathf.Min(f - idx, 1));
            return idx;
If my guess of what caused the bug is right, this code should do 2 things:
  • Avoid the exception. Please let me know if you still have exceptions
  • log an error message when the conditions previously leading to the exception happen. Please send me the error logs when they appear.
Thanks for your patience
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Have this happening to me as well. It seem to stem from a "issue" in TFToSegment, where a calculation sometimes come VERY close to 1, causing parts of the later logic to fail with the index out of range exception

func TFToSegment() ...

            float f = tf * segmentsCount;  // This is the issue, sometimes f comes out as something super close to 1, like 0.9999994 (due to float precision)
            int idx = (int)f; // causing idx to become 0
            localF = f - idx; // localF is still 0.9999994

In my case it happens when calling TFToDistance, which causes the subcalls TFToSegment (setting localF near 1), the returned segment (probably the wrong one due to the rounding error) is used to call LocalFToDistance, again sanity checks are passed to localF being close to 1 but not 1. This ends up calling getApproximationIndexINTERNAL, which again passes sanity checks, and returns a index equal to the size of ApproximationDistances.Length, causing the exception to happen.

Wonder if most "<some float> == 1" checks would be better off replaced with Mathf.Approximately(<some float>, 1)

Edit: In our case, segmentsCount was 32, and the tf value used as input was 0.0312499981 instead of 0.3125 due to float rounding errors (which are quite common).
You are absolutely right about the comparison fix. I have been fixing some of those through time in different places, but I need some day to go through all float comparisons in the code base and fix them once and for all.
One thing about Mathf.Approximately to be aware of, is that Mathf.Approximately(0, someVerySmallNonZeroValue) will return false. There are cases where I would like it to return true. For thoses cases, I use the following:
        public static bool Approximately(this float x, float y)
            bool result;
            const float zeroComparaisonMargin = 0.000001f;

            float nearlyZero = Mathf.Epsilon * 8f;

            float absX = Math.Abs(x);
            float absY = Math.Abs(y);

            if (absY < nearlyZero)
                result = absX < zeroComparaisonMargin;
            else if (absX < nearlyZero)
                result = absY < zeroComparaisonMargin;
                result = Mathf.Approximately(x, y);
            return result;
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.

Possibly Related Threads…
Thread Author Replies Views Last Post
  Disabling a CurvySplineSegment results in NullRefException Lupos 1 5 10-02-2023, 09:55 AM
Last Post: _Aka_
  Custom CurvySplineSegment prefabs Lupos 1 7 10-02-2023, 09:36 AM
Last Post: _Aka_
  Does Curvy has gameobjects pooling system function? Chanon 7 13 09-07-2023, 12:43 PM
Last Post: _Aka_
  IndexOutOfRangeException in CurvySplineSegment.LocalFToDistance billowe 2 753 09-06-2022, 06:09 AM
Last Post: sambutle

Forum Jump: