130 lines
5.1 KiB
C#
130 lines
5.1 KiB
C#
using NUnit.Framework;
|
|
using ProjectM.Simulation;
|
|
using Unity.Mathematics;
|
|
|
|
namespace ProjectM.Tests
|
|
{
|
|
/// <summary>
|
|
/// Pure unit tests for <see cref="AimMath"/>, the Burst-safe cursor->ground projection used by the client
|
|
/// input gather (facing) and the aim-reticle presentation (world point). No camera or ECS world is needed:
|
|
/// the methods are deterministic functions of a ray, the player position, a plane Y, and a dead-zone, so
|
|
/// each case constructs a ray and asserts the hit point / normalized planar direction (or that the fallback
|
|
/// is held on a degenerate ray or inside the dead-zone). Mirrors AutoTargetTests / PlayerSpawnMathTests.
|
|
/// </summary>
|
|
public class AimMathTests
|
|
{
|
|
const float Tol = 1e-4f;
|
|
static readonly float2 Fallback = new float2(0f, 1f);
|
|
|
|
static void AssertDirEqual(float2 expected, float2 actual, string message)
|
|
{
|
|
Assert.AreEqual(expected.x, actual.x, Tol, message + " (x)");
|
|
Assert.AreEqual(expected.y, actual.y, Tol, message + " (y)");
|
|
}
|
|
|
|
// ---- PlanarAimFromRay (facing direction) ----
|
|
|
|
[Test]
|
|
public void StraightDownRay_AimsFromPlayerToCursorGroundPoint()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(5f, 10f, 5f), new float3(0f, -1f, 0f),
|
|
float3.zero, 0f, Fallback);
|
|
AssertDirEqual(math.normalize(new float2(5f, 5f)), aim, "down ray");
|
|
}
|
|
|
|
[Test]
|
|
public void DiagonalNonNormalizedRay_ProjectsToPlaneAndNormalizes()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(0f, 10f, 0f), new float3(0.5f, -1f, 0.5f),
|
|
float3.zero, 0f, Fallback);
|
|
AssertDirEqual(math.normalize(new float2(5f, 5f)), aim, "diagonal ray");
|
|
}
|
|
|
|
[Test]
|
|
public void RayParallelToPlane_ReturnsFallback()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(0f, 10f, 0f), new float3(1f, 0f, 0f),
|
|
float3.zero, 0f, Fallback);
|
|
AssertDirEqual(Fallback, aim, "parallel ray");
|
|
}
|
|
|
|
[Test]
|
|
public void RayPointingAwayFromPlane_ReturnsFallback()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(0f, 10f, 0f), new float3(0f, 1f, 0f),
|
|
float3.zero, 0f, Fallback);
|
|
AssertDirEqual(Fallback, aim, "upward ray");
|
|
}
|
|
|
|
[Test]
|
|
public void CursorOverPlayer_ReturnsFallback()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(0f, 10f, 0f), new float3(0f, -1f, 0f),
|
|
float3.zero, 0f, Fallback);
|
|
AssertDirEqual(Fallback, aim, "cursor over player");
|
|
}
|
|
|
|
[Test]
|
|
public void ValidHit_ResultIsUnitLength()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(-3f, 8f, 2f), new float3(0.2f, -1f, -0.4f),
|
|
new float3(1f, 0f, 1f), 0f, Fallback);
|
|
Assert.AreEqual(1f, math.length(aim), Tol, "unit length");
|
|
}
|
|
|
|
[Test]
|
|
public void NonZeroPlaneY_UsesPlayerPlane()
|
|
{
|
|
var aim = AimMath.PlanarAimFromRay(new float3(2f, 11f, 0f), new float3(0f, -1f, 0f),
|
|
new float3(0f, 1f, 0f), 1f, Fallback);
|
|
AssertDirEqual(new float2(1f, 0f), aim, "plane y=1");
|
|
}
|
|
|
|
// ---- dead-zone (hold facing when the cursor is near the player) ----
|
|
|
|
[Test]
|
|
public void HitWithinDeadZone_HoldsFallback()
|
|
{
|
|
// Cursor ground point 0.4u from the player; dead-zone 0.6u => facing is held (fallback).
|
|
var aim = AimMath.PlanarAimFromRay(new float3(0.4f, 10f, 0f), new float3(0f, -1f, 0f),
|
|
float3.zero, 0f, Fallback, 0.6f);
|
|
AssertDirEqual(Fallback, aim, "inside dead-zone");
|
|
}
|
|
|
|
[Test]
|
|
public void HitOutsideDeadZone_PointsAtCursor()
|
|
{
|
|
// Cursor ground point 2u along +X; dead-zone 0.6u => faces +X (distinct from the +Z fallback).
|
|
var aim = AimMath.PlanarAimFromRay(new float3(2f, 10f, 0f), new float3(0f, -1f, 0f),
|
|
float3.zero, 0f, Fallback, 0.6f);
|
|
AssertDirEqual(new float2(1f, 0f), aim, "outside dead-zone");
|
|
}
|
|
|
|
// ---- TryGroundHit (world ground point) ----
|
|
|
|
[Test]
|
|
public void TryGroundHit_StraightDownRay_ReturnsPlanePoint()
|
|
{
|
|
bool ok = AimMath.TryGroundHit(new float3(5f, 10f, 5f), new float3(0f, -1f, 0f), 0f, out var hit);
|
|
Assert.IsTrue(ok, "should hit");
|
|
Assert.AreEqual(5f, hit.x, Tol, "hit.x");
|
|
Assert.AreEqual(0f, hit.y, Tol, "hit.y");
|
|
Assert.AreEqual(5f, hit.z, Tol, "hit.z");
|
|
}
|
|
|
|
[Test]
|
|
public void TryGroundHit_ParallelRay_ReturnsFalse()
|
|
{
|
|
bool ok = AimMath.TryGroundHit(new float3(0f, 10f, 0f), new float3(1f, 0f, 0f), 0f, out _);
|
|
Assert.IsFalse(ok, "parallel never hits");
|
|
}
|
|
|
|
[Test]
|
|
public void TryGroundHit_RayAwayFromPlane_ReturnsFalse()
|
|
{
|
|
bool ok = AimMath.TryGroundHit(new float3(0f, 10f, 0f), new float3(0f, 1f, 0f), 0f, out _);
|
|
Assert.IsFalse(ok, "t<0 behind ray");
|
|
}
|
|
}
|
|
}
|