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.