/// <summary>
    /// 履带平铺计算
    /// </summary>
    private List <TrackChildInfo> ComputeTrackSpread()
    {
        //find the curve node that is parallel to the circle's right axis
        Vector3 midPos, midTangent, midUp;
        float   midDistance;

        circleCurve.GetBottomMidSample(out midPos, out midTangent, out midUp, out midDistance);

        Vector3    midForward  = Vector3.Cross(midUp, midTangent);
        Quaternion midRotation = Quaternion.LookRotation(midForward, midUp);

        Vector3 startPos = midPos - midTangent * 0.5f * circleCurve.Length;
        Vector3 scale    = Scale * Vector3.one;

        float distance    = 0;
        float totalLength = circleCurve.Length;
        int   index       = 0;

        while (distance <= totalLength)
        {
            TrackChildInfo tInfo = new TrackChildInfo();
            tInfo.distOnCurve = distance;
            tInfo.position    = startPos + midTangent * distance + midForward * Deviation;
            tInfo.scale       = scale;
            tInfo.rotation    = midRotation;

            transInfos.Add(tInfo);

            index++;
            distance += Spacing;
        }

        return(transInfos);
    }
    public List <TrackChildInfo> ComputeTrack()
    {
        transInfos.Clear();

        if (!circleCurve.IsBuilt)
        {
            circleCurve.Build(Circles, CurveType);
        }

        if (IsSpread)
        {
            return(ComputeTrackSpread());
        }

        float distance    = 0;
        float totalLength = circleCurve.Length;
        int   index       = 0;

        while (distance <= totalLength)
        {
            Vector3 pos, tangent, up, forward;
            float   curveDistance = (StartOffset + distance) - totalLength * Mathf.FloorToInt((StartOffset + distance) / totalLength);
            circleCurve.GetSampleAtDistance(curveDistance, out pos, out tangent, out up);

            TrackChildInfo tInfo = new TrackChildInfo();
            tInfo.distOnCurve = curveDistance;

            // scale
            tInfo.scale = Scale * Vector3.one;
            // rotate, get forward from left and up
            forward        = Vector3.Cross(up, tangent);
            tInfo.rotation = Quaternion.LookRotation(forward, up);

            // move along spline, according to spacing
            tInfo.position = pos + forward * Deviation;

            transInfos.Add(tInfo);

            index++;
            distance += Spacing;
        }

        return(transInfos);
    }
    protected override void Create()
    {
        if (Spacing <= 0 || Prefab == null || Circles == null || Circles.Length == 0)
        {
            return;
        }

        ComputeTrack();

        int index = 0;

        while (index < transInfos.Count)
        {
            Transform child = null;
            if (index >= transform.childCount)
            {
                GameObject go = Instantiate(Prefab, transform, false);
                child      = go.transform;
                child.name = Prefab.name + "_" + index;
            }
            else
            {
                child = transform.GetChild(index);
            }

            TrackChildInfo tInfo = transInfos[index];
            child.position   = tInfo.position;
            child.rotation   = tInfo.rotation;
            child.localScale = tInfo.scale;

            index++;
        }

        //delete unused
        int startIndex = transform.childCount - 1;

        for (int j = startIndex; j >= index; j--)
        {
            DestroyImmediate(transform.GetChild(j).gameObject);
        }
    }