GetOrientationFast will throw an IndexError if its called prior to refreshing the spline after creating new control points. Refreshing the spline is automatic when you use spline.Add and when you use spline.InsertAfter with skiprefreshingandevents set to false. I was using spline.InsertAfter with skiprefreshingandevents set to true, which I think I cut and paste from the InfiniteTrack example. Hopefully that's more clear.
I've continued to make progress in 2D and now have it working reliably for a whopping 62.5% of my 2D scenarios (see below). So I'm hoping you might have a hunch on where to look to solve the rest.
I gave up on the Static orientation approach and returned to using the dynamic mode and have discovered that the 2D orientation "bug" depends on the starting and ending orientation of the spline. If the start/end is a "valid" combination, the 2D sprite stays to the same side of the spline and on the 2D plane, regardless of the path shape in between the start and end. But if the start/end is an "invalid" combination, the sprite will "get skinny" at some point along the spline since the orientation at some control points leave the 2D plane.
Starting Direction: West
Valid Ending: West,
Invalid Ending : North, East, South
Starting Direction: North, East, or South
Valid Ending: North, East, South
Invalid Ending : West
To say a different way, if the initial control points are heading to the left in 2D, the final control points MUST head to the left to maintain the proper 2D orientation. If the initial control points start heading up, down, or right, the proper 2D orientation is maintained UNLESS the final control points head to the left. The shape/complexity of the spline in the middle does not seem to matter at all.
So this helps narrow it down, but I still haven't found the fix although I explored some hunches:
- getOrthoUp0INTERNAL() uses a static Vector3.up reference which may not be appropriate for 2D but I wasn't able to change that in a way that yielded better results
- Auto End Tangents toggling on and off didn't seem to have an impact
- the end of ProcessDirtyCheckpoints for !closed splines does something but I couldn't figure that one out
Any ideas are welcome, and thanks again for all the pointers so far.