Обычная линейная интерполяция, но вместо двух точек на входе массив из Vector3. Таким образом можно плавно двигать объект по множеству точек.
Ещё, можно передавать в функцию массив с продолжительностью каждого шага, если необходимо, чтобы объект двигался с разной скоростью от точки к точке.
/// <summary>
/// Move the object to the specified positions
/// </summary>
/// <param name="positions">Array of control points</param>
/// <param name="time">Time for each segment</param>
public IEnumerator Move(Vector3[] positions, float time) {
for (var i = 0; i < positions.Length; i++) {
var startPosition = transform.position;
var t = 0f;
while (t < 1) {
t += Time.deltaTime / time;
transform.position = Vector3.Lerp(startPosition, positions[i], t);
yield return null;
}
transform.position = positions[i];
}
}
...
Vector3[] positionsArray = { new Vector3 (10f, 10f, 0f), new Vector3 (20f, 20f, 0f), ... };
StartCoroutine (Move(positionsArray, 1f));
Выглядит это примерно так:
Но, можно сгладить перемещение! Можно использовать Кривые Безье, но там надо дополнительно задавать промежуточные точки. Другой вариант интереснее — сплайн Кэтмулла-Рома (Catmull–Rom spline), он проходит по всем точкам и дополнительно ничего не надо указывать.
/// <summary>
/// Catmull-Rom spline interpolation
/// </summary>
public static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
return 0.5f * (
(2f * p1) +
(-p0 + p2) * t +
t * t * (2f * p0 - 5f * p1 + 4f * p2 - p3) +
t * t * t * (-p0 + 3f * p1 - 3f * p2 + p3)
);
}
/// <summary>
/// Move along a Catmull-Rom spline defined by the given positions
/// </summary>
/// <param name="positions">Array of control points</param>
/// <param name="time">Time to complete the spline</param>
public IEnumerator MoveSpline(Vector3[] positions, float time) {
if (positions.Length < 2) {
Debug.LogError("Requires at least 2 points for spline!");
yield break;
}
for (var i = 0; i < positions.Length - 1; i++) {
var p0 = (i == 0) ? positions[i] : positions[i - 1];
var p1 = positions[i];
var p2 = positions[i + 1];
var p3 = (i + 2 < positions.Length) ? positions[i + 2] : positions[i + 1];
var t = 0f;
while (t < 1f) {
t += Time.deltaTime / time;
transform.localPosition = CatmullRom(p0, p1, p2, p3, t);
yield return null;
}
transform.localPosition = p2;
}
}
Вот как это выглядит, даже с корявым примером выше:
Если же нужно, чтобы объект пробегал по всем точкам за заданное время, то функцию надо немного поменять и сначала посчитать расстояние между всеми точками.
Это если не хочется из-за одной функции тянуть большую библиотеку в проект 😁 А так, DOTween или любой другой твинер решает наверно все задачи связанные с перемещением объекта.
Нет комментариев