Based on the image below, I have a curve (orange) which is a bezier sub-curve of an original curve (longer black curve). The original curve consists of a number of cubic bezier curves joined together. How can I move the sub-curve (which could be contain more than one cubic bezier curve) along it’s original curve whiles preserving its length?

Please note that the original curve/spline could be open or closed curve with the ends joining. I know that arc length is key to achieving this, but I’m not sure to do this.

enter image description here


The smaller curve was reduced using the solution from How to move points of a multi-segmented bezier curve to one side. DMGregory recommended Moving ships between two planets along a bezier, missing some equations for acceleration, which I have to admit I didn’t understand enough to fully utilise to solve my problem. One thing though that I took away from the solution was I needed to express the smaller curve as percentage of the original curve, so I implemented a slider as below.

 public void ReplaceCurveWithSubCurve(float curveVal) {

    subCurve = IntervalFromTo(curve, 0, curveVal);


In CurveEditor:

curveLengthValue = EditorGUILayout.Slider("Curve Length", creator.curveSizeValue, 0f, 1.0f);

if (!Mathf.Approximately(creator.curveSizeValue, curveLengthValue))
    creator.curveSizeValue = curveLengthValue;

My general understanding is the original (full) curve say runs from some t = 0.0 to t = 1.0 and my sub curve at any given point is made of a subset of those values, so I need to change the values along the full curve whiles preserving the arc length. Below are the methods I use to calculate the arc length. My problem is how to tie all this together to arrive at a working solution.

 public float SegLength(int segmentIndex)
    var steps = 10;
    var t = 1 / (float)steps;
    var sumArc = 0.0f;
    var j = 0.0f;
    var a = new Vector2(0.0f, 0.0f);

    var b = points[segmentIndex * 3];

    var dX = 0.0f;
    var dY = 0.0f;
    var dS = 0.0f;

    for (int i = 0; i < steps; j = j + t)
        a = SegmentAtPoint(segmentIndex, j);

        dX = a.x - b.x;
        dY = a.y - b.y;
        dS = Mathf.Sqrt((dX * dX) + (dY * dY));

        sumArc = sumArc + dS;
        b.x = a.x;
        b.y = a.y;

    return sumArc;


public float FullLength()
    var totalLength = 0.0f;

    for (int i = 0; i < NumSegments; i++)

        totalLength += SegLength(i);

    return totalLength;
  • \$\begingroup\$ This recent answer shows how to construct a subset of an input spline from a start point to an endpoint, specified as percentages of the total length. That specific version accurately preserves arclength at curve boundaries and approximates it in between, but you can make it accurate throughout with a small fixup to the starting / ending t selections once you've identified the starting/ending curve within the spline. \$\endgroup\$
    – DMGregory
    Mar 11, 2019 at 16:19
  • \$\begingroup\$ @DMGregory Interestingly I used your solution to get a subset of the spline. How will I get the ending curve that will enable me to make a fixup work for t selections? \$\endgroup\$ Mar 11, 2019 at 16:44
  • \$\begingroup\$ For more information on sampling a Bezier curve using arc length, check out this answer \$\endgroup\$
    – DMGregory
    Mar 11, 2019 at 16:49
  • 2
    \$\begingroup\$ @DMGregory I went through the solution in your previous comment. I have to admit, I don’t fully get how to use it to arrive at a solution to my question. I Implemented a slider with values 0 to 1 for reducing the original curve (based on the solution you provided for the other question), so I can express the smaller (sub-curve) as a percentage of the original. \$\endgroup\$ Mar 18, 2019 at 18:46
  • \$\begingroup\$ @NotEveryDay nice question. Have you been able to solve this? \$\endgroup\$
    – Bane
    Mar 26, 2019 at 7:11

1 Answer 1


You can build curve inside a coroutine and fill it with points while it building. You can use particle that will move you curve trajectory and left the tale behind.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .