using NightclubArcadia.Player.Math; using NUnit.Framework; using UnityEngine; namespace NightclubArcadia.Locomotion.Math.Tests { public class MotionInputMathTests { [Test] public void WorldToCameraRelativeInput_ZeroVelocity_ReturnsZero() { var result = MotionInputMath.WorldToCameraRelativeInput(Vector3.zero, 2f, 0f); Assert.AreEqual(Vector2.zero, result); } [Test] public void WorldToCameraRelativeInput_YawZero_PreservesForward() { var world = new Vector3(0f, 0f, 2f); var result = MotionInputMath.WorldToCameraRelativeInput(world, 2f, 0f); Assert.AreEqual(new Vector2(0f, 1f), result); } [Test] public void WorldToCameraRelativeInput_Yaw90_RotatesCorrectly() { // Camera yawed +90 degrees faces +X. World velocity is +Z, which from // that camera is to the LEFT, so the camera-relative x is -1, not +1. // The conversion applies Quaternion.Euler(0, -cameraYaw, 0), and Unity's // Y rotation is clockwise viewed from above, so forward maps to -right. // WorldToCameraRelativeInput_RoundTripsThroughAtan2 pins the same // convention: it only reconstructs the world direction because the yaw // is subtracted here and added back there. var world = new Vector3(0f, 0f, 2f); var result = MotionInputMath.WorldToCameraRelativeInput(world, 2f, 90f); Assert.That(result.x, Is.EqualTo(-1f).Within(0.001f)); Assert.That(result.y, Is.EqualTo(0f).Within(0.001f)); } [Test] public void WorldToCameraRelativeInput_ClampFractionToOne() { var world = new Vector3(0f, 0f, 10f); var result = MotionInputMath.WorldToCameraRelativeInput(world, 2f, 0f); Assert.That(result.magnitude, Is.EqualTo(1f).Within(0.001f)); } [Test] public void WorldToCameraRelativeInput_RoundTripsThroughAtan2() { var world = new Vector3(1f, 0f, 2f).normalized; var cameraYaw = 15f; var input = MotionInputMath.WorldToCameraRelativeInput(world, 1f, cameraYaw); var targetRotation = Mathf.Atan2(input.x, input.y) * Mathf.Rad2Deg + cameraYaw; var reconstructed = Quaternion.Euler(0f, targetRotation, 0f) * Vector3.forward; var flatWorld = new Vector3(world.x, 0f, world.z).normalized; Assert.That(Vector3.Dot(reconstructed, flatWorld), Is.EqualTo(1f).Within(0.001f)); } [Test] public void ScreenDeltaToWorldPan_UsesCameraBasis() { var right = Vector3.right; var forward = Vector3.forward; var delta = new Vector2(10f, 0f); var result = MotionInputMath.ScreenDeltaToWorldPan(delta, right, forward, 0.02f); // Compared per component with a tolerance rather than Assert.AreEqual: // Vector3.Equals is exact, and -10f * 0.02f lands one ulp away from the // -0.2f literal, so an exact comparison fails on a correct result. Assert.That(result.x, Is.EqualTo(-0.2f).Within(0.0001f)); Assert.That(result.y, Is.EqualTo(0f).Within(0.0001f)); Assert.That(result.z, Is.EqualTo(0f).Within(0.0001f)); } } }