/// <param name="t">Параметр прогресса между p1 и p2. Принимает значение в диапазоне от 0 до 1</param> /// <param name="p0"></param> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> /// <returns></returns> public static Snapshot Interpolate(float t, Snapshot p0, Snapshot p1, Snapshot p2, Snapshot p3) { if (t < 0 || 1 < t) { throw new ArgumentOutOfRangeException($"t was {t}"); } Snapshot result = new Snapshot(); foreach (ushort entityId in p2.transforms.Keys) { bool v0Exists = p0.transforms.TryGetValue(entityId, out var v0); bool v1Exists = p1.transforms.TryGetValue(entityId, out var v1); //always true bool v2Exists = p2.transforms.TryGetValue(entityId, out var v2); bool v3Exists = p3.transforms.TryGetValue(entityId, out var v3); ViewTransformCompressed interpolated; //Сколько точек есть для интерполяции? if (v0Exists && v1Exists && v2Exists && v3Exists) { //интерполяция между черытьмя точками Vector3 position = CatmullRomSpline .GetCatmullRomPosition(t, v0.GetPosition(), v1.GetPosition(), v2.GetPosition(), v3.GetPosition()); float angle = Mathf.LerpAngle(v1.Angle, v2.Angle, t); interpolated = new ViewTransformCompressed(position.x, position.z, angle, v2.viewTypeEnum); } else if (v1Exists && v2Exists) { //интерполяция между двумя точками Vector3 position = v1.GetPosition() * (1 - t) + v2.GetPosition() * t; float angle = Mathf.LerpAngle(v1.Angle, v2.Angle, t); interpolated = new ViewTransformCompressed(position.x, position.z, angle, v2.viewTypeEnum); } else { //сущность была создана на этом кадре. интерполяция невозможна interpolated = v2; } result.transforms.Add(entityId, interpolated); } return(result); }
IEnumerator Mover() { coroutineAllowed = false; if (controlPointsIndex == 4) { controlPointsIndex = 0; } Vector3 p0 = controlPointsList[CatmullRomSpline.ClampListPos(controlPointsIndex - 1, controlPointsList)].position; Vector3 p1 = controlPointsList[controlPointsIndex].position; Vector3 p2 = controlPointsList[CatmullRomSpline.ClampListPos(controlPointsIndex + 1, controlPointsList)].position; Vector3 p3 = controlPointsList[CatmullRomSpline.ClampListPos(controlPointsIndex + 2, controlPointsList)].position; controlPointsIndex += 1; float travelled = 0; while (t < 1) { t += Time.deltaTime * speed; pos = CatmullRomSpline.GetCatmullRomPosition(t, p0, p1, p2, p3); // Numerical Methods for Arc Length while (travelled < distance_to_travel) { t += very_small_amount; travelled += (CatmullRomSpline.GetCatmullRomPosition(t, p0, p1, p2, p3) - pos).magnitude; pos = CatmullRomSpline.GetCatmullRomPosition(t, p0, p1, p2, p3); } Vector3 newDir = Vector3.RotateTowards(transform.forward, (pos - transform.position).normalized, Time.deltaTime * speed * 10, 0.0f); transform.rotation = Quaternion.LookRotation(newDir); transform.position = pos; Debug.DrawRay(transform.position, newDir, Color.green); yield return(new WaitForEndOfFrame()); } t = 0; coroutineAllowed = true; }