using NUnit.Framework; using ProjectM.Simulation; using Unity.Mathematics; namespace ProjectM.Tests { /// /// Pure unit tests for , 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. /// 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"); } } }