Untitled
csharp
a month ago
1.9 kB
3
Indexable
Never
using UnityEngine; public static class Ballistics { const float epsilon = 0.00000001f; public static Vector3 CalculateShootVelocity(Vector3 targetStartPos, Vector3 targetVelocity, Vector3 targetAcceleration, Vector3 projectileStartPos, Vector3 projectileAcceleration, float projectileSpeed, out float duration) { Vector3 a = targetAcceleration - projectileAcceleration; Vector3 relativeTargetStartPos = targetStartPos - projectileStartPos; var roots = MathNet.Numerics.FindRoots.Polynomial(new double[] { Vector3.Dot(a, a) / 4.0f, Vector3.Dot(a, targetVelocity), Vector3.Dot(a, relativeTargetStartPos) + Vector3.SqrMagnitude(targetVelocity) - projectileSpeed * projectileSpeed, 2.0f * Vector3.Dot(targetVelocity, relativeTargetStartPos), Vector3.SqrMagnitude(relativeTargetStartPos) }); float? smallestPositiveRoot = null; foreach(var root in roots) { if (root.Imaginary != 0) continue; float rootReal = System.Convert.ToSingle(root.Real); if (rootReal > epsilon) { if (!smallestPositiveRoot.HasValue || rootReal < smallestPositiveRoot.Value) smallestPositiveRoot = rootReal; } } if(smallestPositiveRoot.HasValue) { duration = smallestPositiveRoot.Value; Vector3 travel = relativeTargetStartPos + targetVelocity * duration + duration * duration * (targetAcceleration / 2.0f); return travel / duration - (projectileAcceleration / 2.0f) * duration; } else { Debug.LogError("Unimplemented"); duration = Mathf.Infinity; return Vector3.zero; } } }