hellbound/Assets/Scripts/Core/Extensions/MathfHelper.cs

125 lines
4.9 KiB
C#
Raw Normal View History

2021-11-26 11:16:25 +03:00
using UnityEngine;
public static class MathfHelper
{
public static bool QuadraticSolver(float a, float b, float c, out float t1, out float t2)
{
float D = Mathf.Pow(b, 2f) - 4f * a * c;
if (D > 0 || D == 0)
{
t1 = (-b + Mathf.Sqrt(D)) / (2 * a);
t2 = (-b - Mathf.Sqrt(D)) / (2 * a);
return true;
}
t1 = -1;
t2 = -1;
return false;
}
#region HaunterRegion
public static Vector3 CalculateTargetPositionForCatchUp(Vector3 startTargetPosition, Vector3 targetMoveDirection,
float targetMoveSpeed, Vector3 hauntingPoint, float haunterSpeed)
{
float time = TimeForCatchUpToThePoint(startTargetPosition, targetMoveDirection, targetMoveSpeed, hauntingPoint,
haunterSpeed);
return startTargetPosition + targetMoveDirection * (targetMoveSpeed * time);
;
}
public static Vector3 CalculateMoveDirectionForCatchUp(Vector3 startTargetPosition, Vector3 targetMoveDirection,
float targetMoveSpeed, Vector3 hauntingPoint, float haunterSpeed)
{
return CalculateTargetPositionForCatchUp(startTargetPosition, targetMoveDirection, targetMoveSpeed,
hauntingPoint,
haunterSpeed) - hauntingPoint;
}
public static bool CanCatchUpToThePoint(Vector3 targetPosition, Vector3 targetMoveDirection, float targetMoveSpeed,
Vector3 hauntingPoint, float haunterSpeed)
{
return CanCatchUpToThePoint(targetPosition, targetMoveDirection, targetMoveSpeed, hauntingPoint, haunterSpeed,
out float time);
}
public static bool CanCatchUpToThePoint(Vector3 targetPosition, Vector3 targetMoveDirection, float targetMoveSpeed,
Vector3 hauntingPoint, float haunterSpeed, out float time)
{
time = TimeForCatchUpToThePoint(targetPosition, targetMoveDirection, targetMoveSpeed, hauntingPoint,
haunterSpeed);
return time >= 0;
}
public static bool CanCatchUpToThePoint(Vector3 targetPosition, Vector3 targetMoveDirection,
float targetMoveSpeed, Vector3 hauntingPoint, float haunterSpeed, out Vector3 hitPoint)
{
CanCatchUpToThePoint(targetPosition, targetMoveDirection, targetMoveSpeed, hauntingPoint, haunterSpeed,
out float time);
hitPoint = (targetPosition + targetMoveDirection.normalized * time);
return time >= 0;
}
public static float TimeForCatchUpToThePoint(Vector3 startTargetPosition, Vector3 targetMoveDirection,
float targetMoveSpeed, Vector3 hauntingPoint, float haunterSpeed)
{
Vector3 targetToHaunter = hauntingPoint - startTargetPosition;
// float d = targetToHaunter.magnitude;
float a = haunterSpeed * haunterSpeed - targetMoveSpeed * targetMoveSpeed;
float b = 2 * Vector3.Dot(targetToHaunter, targetMoveDirection * targetMoveSpeed);
float c = -targetToHaunter.sqrMagnitude;
float time;
if (QuadraticSolver(a, b, c, out float t1, out float t2))
{
if (t1 < 0 && t2 < 0)
return -1;
if (t1 > 0 && t2 > 0)
time = Mathf.Min(t1, t2);
else
time = Mathf.Max(t1, t2);
}
else
return -1;
return time;
}
#endregion
#region NearestPoints
public static Vector3 NearestPointInRay(Vector3 position, Vector3 origin, Vector3 direction) =>
origin + direction * GetUForIntersectPoint(position, origin, direction);
public static Vector3 NearestPointInLineSegment(Vector3 position, Vector3 startPoint, Vector3 endPoint)
{
Vector3 startToEnd = endPoint - startPoint;
float u = GetUForIntersectPoint(position, startPoint, endPoint - startPoint);
return u < 0 ? startPoint : u > 1 ? endPoint : startPoint + startToEnd * u;
}
public static bool HasPerpendicularToLine(Vector3 position, Vector3 startPoint, Vector3 endPoint)
{
return TryGetPerpendicularPointInLineFromPosition(position, startPoint, endPoint, out Vector3 result);
}
public static bool TryGetPerpendicularPointInLineFromPosition(Vector3 position, Vector3 startPoint, Vector3 endPoint, out Vector3 result)
{
Vector3 startToEnd = endPoint - startPoint;
float u = GetUForIntersectPoint(position, startPoint, startToEnd);
bool isHas = IsCorrectUForPerpendicular(u);
result = isHas ? startPoint + startToEnd * u : Vector3.zero;
return isHas;
}
private static float GetUForIntersectPoint(Vector3 position, Vector3 origin, Vector3 direction) => Vector3.Dot(position - origin, direction) / direction.sqrMagnitude;
private static bool IsCorrectUForPerpendicular(float u) => u >= 0 && u <= 1;
#endregion
}