125 lines
4.9 KiB
C#
125 lines
4.9 KiB
C#
|
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
|
|||
|
}
|