|
#region Author |
|
///////////////////////////////////////// |
|
// RAPHAËL DAUMAS --> MoveAlongCurve |
|
// https://raphdaumas.wixsite.com/portfolio |
|
// https://github.com/Marsgames |
|
///////////////////////////////////////// |
|
#endregion |
|
using System.Collections; |
|
using UnityEngine; |
|
|
|
public class MoveAlongCurve : MonoBehaviour |
|
{ |
|
#region Variables |
|
[SerializeField] private Transform startPosition = null; |
|
[SerializeField] private Transform endPosition = null; |
|
[SerializeField] private Transform[] paths = null; |
|
|
|
#if UNITY_EDITOR |
|
[SerializeField] private Texture2D pathTexture = null; |
|
[SerializeField] private bool alwaysShowPath = false; |
|
#endif |
|
#endregion Variables |
|
|
|
/////////////////////////////////////////////////////////// |
|
|
|
#region Unity's functions |
|
// Start is called before the first frame update |
|
private void Start() |
|
{ |
|
CheckIfSetUp(); |
|
} |
|
|
|
#if UNITY_EDITOR |
|
private void OnDrawGizmosSelected() |
|
{ |
|
if (alwaysShowPath) |
|
{ |
|
return; |
|
} |
|
|
|
Color color = Color.blue; |
|
|
|
foreach (Transform path in paths) |
|
{ |
|
UnityEditor.Handles.DrawBezier(startPosition.position, endPosition.position, path.position, path.position, color, pathTexture, 2); |
|
} |
|
} |
|
|
|
private void OnDrawGizmos() |
|
{ |
|
if (!alwaysShowPath) |
|
{ |
|
return; |
|
} |
|
|
|
Color color = Color.blue; |
|
|
|
foreach (Transform path in paths) |
|
{ |
|
UnityEditor.Handles.DrawBezier(startPosition.position, endPosition.position, path.position, path.position, color, pathTexture, 2); |
|
} |
|
} |
|
#endif |
|
#endregion Unity's functions |
|
|
|
/////////////////////////////////////////////////////////// |
|
|
|
#region Functions |
|
/// <summary> |
|
/// Move an object while discribing a Bezier curve |
|
/// </summary> |
|
/// <param name="objectToMove">The GameObject you want to move</param> |
|
/// <param name="startPoint">Start point of the Bezier curve</param> |
|
/// <param name="tangentPoint">Tangent point of the Bezier curve</param> |
|
/// <param name="endPoint">End point of the Bezier curve</param> |
|
/// <param name="interpolationTimer">How long does it takes to go from start point to end point (in seconds)</param> |
|
public void MoveObject(GameObject objectToMove, Vector3 startPoint, Vector3 tangentPoint, Vector3 endPoint, float interpolationTimer) |
|
{ |
|
StartCoroutine(MoveObjectAlongCurve(objectToMove, startPoint, tangentPoint, endPoint, interpolationTimer)); |
|
} |
|
|
|
/// <summary> |
|
/// Move an object while discribing a Bezier curve |
|
/// </summary> |
|
/// <param name="objToMove">The GameObject you want to move</param> |
|
/// <param name="startPoint">Start point of the Bezier curve</param> |
|
/// <param name="tangentPoint">Tangent point of the Bezier curve</param> |
|
/// <param name="endPoint">End point of the Bezier curve</param> |
|
/// <param name="interpolationTimer">How long does it takes to go from start point to end point (in seconds)</param> |
|
private IEnumerator MoveObjectAlongCurve(GameObject objToMove, Vector3 startPoint, Vector3 tangentPoint, Vector3 endPoint, float interpolationTimer) |
|
{ |
|
float elapsedTime = 0; |
|
|
|
objToMove.transform.position = startPosition.position; |
|
|
|
while (elapsedTime < interpolationTimer) |
|
{ |
|
elapsedTime += Time.deltaTime; |
|
|
|
float t = Mathf.InverseLerp(0, interpolationTimer, elapsedTime); |
|
|
|
objToMove.transform.position = GetPointAlongCurve(startPoint, tangentPoint, endPoint, t); |
|
|
|
elapsedTime += Time.deltaTime; |
|
yield return null; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Get a point on a Bezier cruve |
|
/// </summary> |
|
/// <param name="startPoint">Start point of the Bezier curve</param> |
|
/// <param name="tangentPoint">Tangent point oof the Bezier curve</param> |
|
/// <param name="endPoint">End point of the Bezier curve</param> |
|
/// <param name="t">Position on the curve in percentage [0,1]</param> |
|
/// <returns></returns> |
|
private Vector3 GetPointAlongCurve(Vector3 startPoint, Vector3 tangentPoint, Vector3 endPoint, float t) |
|
{ |
|
return Vector3.Lerp(Vector3.Lerp(startPoint, tangentPoint, t), Vector3.Lerp(tangentPoint, endPoint, t), t); |
|
} |
|
|
|
/// <summary> |
|
/// Get a point on a Bezier curve of arbitrary degree using De Casteljau's algorithm. |
|
/// </summary> |
|
/// <param name="controlPoints">List of control points (start, tangents, end)</param> |
|
/// <param name="t">Position on the curve in percentage [0,1]</param> |
|
/// <returns>Point on the curve at the given t</returns> |
|
private Vector3 GetPointAlongCurve(List<Vector3> controlPoints, float t) |
|
{ |
|
if (controlPoints == null || controlPoints.Count < 2) |
|
{ |
|
throw new ArgumentException("You need at least two points to create a Bezier curve."); |
|
} |
|
|
|
// Make a copy of the control points list to work on |
|
var points = new List<Vector3>(controlPoints); |
|
|
|
// Iteratively reduce the list of points until only one point remains |
|
while (points.Count > 1) |
|
{ |
|
var nextPoints = new List<Vector3>(); |
|
for (int i = 0; i < points.Count - 1; i++) |
|
{ |
|
// Interpolate between each pair of points |
|
nextPoints.Add(Vector3.Lerp(points[i], points[i + 1], t)); |
|
} |
|
points = nextPoints; // Replace the current points with the next set |
|
} |
|
|
|
// The remaining point is the point on the curve at t |
|
return points[0]; |
|
} |
|
#endregion Functions |
|
|
|
/////////////////////////////////////////////////////////// |
|
|
|
#region Accessors |
|
#endregion Accessors |
|
|
|
/////////////////////////////////////////////////////////// |
|
|
|
#region Utils |
|
/// <summary> |
|
/// Checks if all variables are set up correctly, otherwise close Editor |
|
/// </summary> |
|
private void CheckIfSetUp() |
|
{ |
|
#if UNITY_EDITOR |
|
bool isSetUp = true; |
|
|
|
if (!startPosition) |
|
{ |
|
Debug.LogError("<b>Start Position</b> cannot be null in <color=#0000FF>" + name + "</color>", gameObject); |
|
isSetUp = false; |
|
} |
|
if (!endPosition) |
|
{ |
|
Debug.LogError("<b>End Position</b> cannot be null in <color=#0000FF>" + name + "</color>", gameObject); |
|
isSetUp = false; |
|
} |
|
if (null == paths) |
|
{ |
|
Debug.LogError("<b>Paths</b> cannot be null in <color=#0000FF>" + name + "</color>", gameObject); |
|
isSetUp = false; |
|
} |
|
|
|
UnityEditor.EditorApplication.isPlaying = isSetUp; |
|
#endif |
|
} |
|
#endregion Utils |
|
} |