Rendering bezier curves question

hey all,

So I’m just starting to learn to program bezier curves in the editor by following the following tutorial.
Curves and Splines, a Unity C# Tutorial. I have it working to the point where I can deform a curve via 3 points (2 at either end of curve and 1 on the tangent). But at the moment I always need to select the curve in the scene view before I can see it and I don’t know how I can make it display the curve permanently in the scene view (without selecting it) as well as at runtime so that I may point a camera at it. I was wondering if anyone knew how I could achieve that so I can add other functions to it such as creating the curve on a terrain based on where the mouse clicks of each of the 3 points are on the terrain. Any help on how I would modify these script would be appreciated. Thanks.

And here is the code that I have so far. It is set up with 3 script files.

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(BezierCurve))]
public class BezierCurveInspector : Editor {
   
    private BezierCurve curve;
    private Transform handleTransform;
    private Quaternion handleRotation;
    //private const int lineSteps = 50;
    private const float directionScale = 0.5f;


    private void OnSceneGUI () {
   
        curve = target as BezierCurve;
        handleTransform = curve.transform;
        handleRotation = Tools.pivotRotation == PivotRotation.Local ?
            handleTransform.rotation : Quaternion.identity;
       
        Vector3 p0 = ShowPoint(0);
        Vector3 p1 = ShowPoint(1);
        Vector3 p2 = ShowPoint(2);
       
        Handles.color = Color.gray;
        Handles.DrawLine(p0, p1);
        Handles.DrawLine(p1, p2);

        /*Handles.color = Color.white;
        Vector3 lineStart = curve.GetPoint(0f);
        for (int i = 1; i <= lineSteps; i++) {
            Vector3 lineEnd = curve.GetPoint(i / (float)lineSteps);
            Handles.DrawLine(lineStart, lineEnd);
            lineStart = lineEnd;
        }*/

        Handles.DrawBezier(p0, p2, p0, p1, Color.white, null, 2f);
    }
   
    private Vector3 ShowPoint (int index) {
        Vector3 point = handleTransform.TransformPoint(curve.points[index]);
        EditorGUI.BeginChangeCheck();
        point = Handles.DoPositionHandle(point, handleRotation);
        if (EditorGUI.EndChangeCheck()) {
            Undo.RecordObject(curve, "Move Point");
            EditorUtility.SetDirty(curve);
            curve.points[index] = handleTransform.InverseTransformPoint(point);
        }
        return point;
    }
}

the beziercurveinspector does all the calculations for the in editor use.

using UnityEngine;

public class BezierCurve : MonoBehaviour {
   
    public Vector3[] points;

    public Vector3 GetPoint (float t) {
        return transform.TransformPoint(Bezier.GetPoint(points[0], points[1], points[2], t));
    }
    public void Reset () {
        points = new Vector3[] {
            new Vector3(1f, 0f, 0f),
            new Vector3(2f, 0f, 0f),
            new Vector3(3f, 0f, 0f)
        };
    }
}

The BezierCurve script gets attached to a empty game object which contains 3 sample points location (start of curve, tangent point, end of curve).

using UnityEngine;

public static class Bezier
{
       
        public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
            t = Mathf.Clamp01(t);
            float oneMinusT = 1f - t;
            return
                oneMinusT * oneMinusT * p0 +
                    2f * oneMinusT * t * p1 +
                    t * t * p2;
    }
    public static Vector3 GetFirstDerivative (Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
        return
            2f * (1f - t) * (p1 - p0) +
                2f * t * (p2 - p1);
    }

}

The bezier script contains the bezier curve equations.

OnDrawGizmos is a good way to achieve this. Add it to your MonoBehaviour script.

will that then show up at runtime? Because I ran the small example script from the script reference, which is a sphere, but it does not show up when I run it.

Yeah it should work at runtime. It wont show up in the game view unless you tick the gizmos box.
Also make sure that your script is expanded in the inspector.
Note this is an editor feature, not something that will work in a build for players.

Regards

Karl

Oh ok I see. I only really need it displayed temporarily as I’m planning to make a road/path tool that works in game where you can place straight paths and curved paths. So the bezier curve line as it is now is is only used to determine the offset vertices for a mesh. Anyway thanks for your help its much appreciated.

1 Like