using System; using UnityEngine; namespace DefaultNamespace { public enum BezierCurveType { Linear, Quadratic, Cubic } public class BezierCurves : MonoBehaviour { [SerializeField] private BezierCurveType _bezierCurveType; [SerializeField] private Color _color = Color.white; [SerializeField] private Transform[] _positions = new Transform[0]; [SerializeField, Min(1)] private int _separations = 1; private void OnDrawGizmos() { Gizmos.color = _color; switch (_bezierCurveType) { case BezierCurveType.Linear: DrawLinearBezierCurve(); break; case BezierCurveType.Quadratic: DrawQuadraticBezierCurve(); break; case BezierCurveType.Cubic: DrawCubicBezierCurve(); break; default: throw new ArgumentOutOfRangeException(); } for (int i = 0; i < _positions.Length; i++) { Gizmos.DrawSphere(_positions[i].position, 0.25f); } } private void DrawLinearBezierCurve() { if (_positions.Length < 2) return; // Gizmos.DrawLine(_positions[0].position, _positions[1].position); Vector3 p0 = _positions[0].position; Vector3 p1 = _positions[1].position; for (int i = 0; i < _separations; i++) { float t0 = i / (float)_separations; float t1 = (i + 1) / (float)_separations; Gizmos.DrawLine(LinearCurvePoint(p0, p1, t0), LinearCurvePoint(p0, p1, t1)); } } private void DrawQuadraticBezierCurve() { if (_positions.Length < 3) return; Vector3 p0 = _positions[0].position; Vector3 p1 = _positions[1].position; Vector3 p2 = _positions[2].position; for (int i = 0; i < _separations; i++) { float t0 = i / (float)_separations; float t1 = (i + 1) / (float)_separations; Gizmos.DrawLine(QuadraticCurvePoint(p0, p1, p2, t0), QuadraticCurvePoint(p0, p1, p2, t1)); } } private void DrawCubicBezierCurve() { if (_positions.Length < 4) return; Vector3 p0 = _positions[0].position; Vector3 p1 = _positions[1].position; Vector3 p2 = _positions[2].position; Vector3 p3 = _positions[3].position; for (int i = 0; i < _separations; i++) { float t0 = i / (float)_separations; float t1 = (i + 1) / (float)_separations; Gizmos.DrawLine(CubicCurvePoint(p0, p1, p2, p3, t0), CubicCurvePoint(p0, p1, p2, p3, t1)); } } private Vector3 LinearCurvePoint(Vector3 p0, Vector3 p1, float t) => (1 - t) * p0 + t * p1; private Vector3 QuadraticCurvePoint(Vector3 p0, Vector3 p1, Vector3 p2, float t) => // LinearCurvePoint(LinearCurvePoint(p0, p1, t), LinearCurvePoint(p1, p2, t), t); (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2; private Vector3 CubicCurvePoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) => // LinearCurvePoint(QuadraticCurvePoint(p0, p1, p2, t), QuadraticCurvePoint(p1, p2, p3, t), t); (1 - t) * (1 - t) * (1 - t) * p0 + 3 * (1 - t) * (1 - t) * t * p1 + 3 * (1 - t) * t * t * p2 + t * t * t * p3; } }