f4c861ee91
+4 EditMode cases (identity/yaw-180/pitched-degenerate/normalized) for the helper the enemy animation drive uses to derive facing from the replicated LocalTransform.Rotation. EditMode suite 204 -> 208, all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
105 lines
4.2 KiB
C#
105 lines
4.2 KiB
C#
using NUnit.Framework;
|
|
using ProjectM.Simulation;
|
|
using Unity.Mathematics;
|
|
|
|
namespace ProjectM.Tests
|
|
{
|
|
public class AnimParamMathTests
|
|
{
|
|
const float Eps = 1e-3f;
|
|
static readonly float2 Fwd = new float2(0f, 1f); // facing world +Z
|
|
const float Max = 5f;
|
|
|
|
[Test] public void ZeroVelocity_AllZero()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(float3.zero, Fwd, Max);
|
|
Assert.AreEqual(0f, r.x, Eps); Assert.AreEqual(0f, r.y, Eps); Assert.AreEqual(0f, r.z, Eps);
|
|
}
|
|
|
|
[Test] public void FullForward_MoveZ1_Speed1()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, Max), Fwd, Max);
|
|
Assert.AreEqual(0f, r.x, Eps); Assert.AreEqual(1f, r.y, Eps); Assert.AreEqual(1f, r.z, Eps);
|
|
}
|
|
|
|
[Test] public void FullBackward_MoveZNeg1()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, -Max), Fwd, Max);
|
|
Assert.AreEqual(0f, r.x, Eps); Assert.AreEqual(-1f, r.y, Eps); Assert.AreEqual(1f, r.z, Eps);
|
|
}
|
|
|
|
[Test] public void StrafeRight_MoveX1()
|
|
{
|
|
// facing +Z -> right = (+X). world velocity +X -> MoveX = +1.
|
|
var r = AnimParamMath.LocomotionParams(new float3(Max, 0f, 0f), Fwd, Max);
|
|
Assert.AreEqual(1f, r.x, Eps); Assert.AreEqual(0f, r.y, Eps); Assert.AreEqual(1f, r.z, Eps);
|
|
}
|
|
|
|
[Test] public void StrafeLeft_MoveXNeg1()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(-Max, 0f, 0f), Fwd, Max);
|
|
Assert.AreEqual(-1f, r.x, Eps);
|
|
}
|
|
|
|
[Test] public void HalfForward_HalfSpeed()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, Max * 0.5f), Fwd, Max);
|
|
Assert.AreEqual(0.5f, r.y, Eps); Assert.AreEqual(0.5f, r.z, Eps);
|
|
}
|
|
|
|
[Test] public void OverMax_SpeedClampsTo1()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, Max * 3f), Fwd, Max);
|
|
Assert.AreEqual(1f, r.z, Eps); Assert.AreEqual(1f, r.y, Eps);
|
|
}
|
|
|
|
[Test] public void RotatedFacing_ProjectsIntoFrame()
|
|
{
|
|
// facing world +X; velocity world +X should read as forward (MoveZ+), not strafe.
|
|
var r = AnimParamMath.LocomotionParams(new float3(Max, 0f, 0f), new float2(1f, 0f), Max);
|
|
Assert.AreEqual(0f, r.x, Eps); Assert.AreEqual(1f, r.y, Eps);
|
|
}
|
|
|
|
[Test] public void DegenerateFacing_DefaultsToWorldForward()
|
|
{
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, Max), float2.zero, Max);
|
|
Assert.AreEqual(1f, r.y, Eps); // treated as facing +Z
|
|
}
|
|
|
|
[Test] public void ZeroMaxSpeed_NoNaN_NoDivByZero()
|
|
{
|
|
// guard: safeMax = max(maxSpeed, 1e-4) -> finite output even with maxSpeed 0.
|
|
var r = AnimParamMath.LocomotionParams(new float3(0f, 0f, 1f), Fwd, 0f);
|
|
Assert.IsFalse(float.IsNaN(r.x) || float.IsNaN(r.y) || float.IsNaN(r.z));
|
|
Assert.AreEqual(1f, r.z, Eps); // clamps to 1
|
|
}
|
|
|
|
// ---- PlanarForward (enemy facing from replicated LocalTransform.Rotation) ----
|
|
|
|
[Test] public void PlanarForward_Identity_IsWorldForward()
|
|
{
|
|
var f = AnimParamMath.PlanarForward(quaternion.identity);
|
|
Assert.AreEqual(0f, f.x, Eps); Assert.AreEqual(1f, f.y, Eps);
|
|
}
|
|
|
|
[Test] public void PlanarForward_Yaw180_IsBackward()
|
|
{
|
|
var f = AnimParamMath.PlanarForward(quaternion.RotateY(math.radians(180f)));
|
|
Assert.AreEqual(0f, f.x, Eps); Assert.AreEqual(-1f, f.y, Eps);
|
|
}
|
|
|
|
[Test] public void PlanarForward_PitchedToVertical_FallsBackToWorldForward()
|
|
{
|
|
// forward rotated to point straight down -> planar XZ ~ 0 -> degenerate fallback (0,1).
|
|
var f = AnimParamMath.PlanarForward(quaternion.RotateX(math.radians(90f)));
|
|
Assert.AreEqual(0f, f.x, Eps); Assert.AreEqual(1f, f.y, Eps);
|
|
}
|
|
|
|
[Test] public void PlanarForward_IsNormalized()
|
|
{
|
|
var f = AnimParamMath.PlanarForward(quaternion.RotateY(math.radians(37f)));
|
|
Assert.AreEqual(1f, math.length(f), Eps);
|
|
}
|
|
}
|
|
}
|