public Vector3 RoadCenterAt(float distanceFromStart, out bool done, out Vector3 direction) { var segments = Math.Round(CachedNodes.Length * 100 * SegmentRate); var nodePositions = CachedNodes.Select(x => x.transform.localPosition).ToArray(); float lengthSeen = 0; for (int i = 0; i <= segments; i++) { var s = i / (float)segments; var center = MathfPlus.BSpline(nodePositions, s); Vector3 nextCenter = MathfPlus.BSpline(nodePositions, (i + 1) / (float)segments); direction = nextCenter - center; var segmentLength = Vector3.Distance(nextCenter, center); lengthSeen += segmentLength; if (lengthSeen > distanceFromStart) { float distanceAtLastSegment = lengthSeen - segmentLength; done = false; return(transform.localToWorldMatrix * MathfPlus.PadVector3(Vector3.Lerp(center, nextCenter, (distanceFromStart - distanceAtLastSegment) / (lengthSeen - distanceAtLastSegment)))); } } // fallback : at distance = 0 done = true; direction = Vector3.zero; return(Vector3.zero); }