using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; using BaseGames.Combat; namespace BaseGames.Tests.EditMode.Combat { public class HurtBoxMultiplierTests { /// 测试期建出的宿主对象;在 TearDown 统一销毁,断言失败也不会残留到编辑器场景。 private GameObject _host; [SetUp] public void SetUp() => LogAssert.ignoreFailingMessages = true; [TearDown] public void TearDown() { // 项目关闭了 Domain/Scene Reload:断言失败会跳过用例后续语句, // 清理必须放在 TearDown,否则失败一次就往编辑器场景里漏一个对象。 if (_host != null) Object.DestroyImmediate(_host); _host = null; LogAssert.ignoreFailingMessages = false; } /// /// HurtBox 标了 [RequireComponent(typeof(Collider2D))],而 Collider2D 是抽象类, /// Unity 无法自动补齐——裸 AddComponent<HurtBox>() 会返回真 null。 /// 必须先挂一个具体碰撞体。 /// private HurtBox CreateHurtBox() { _host = new GameObject("hurtbox"); _host.AddComponent(); var hb = _host.AddComponent(); Assert.IsNotNull(hb, "HurtBox 需要先有具体 Collider2D 才能挂载"); return hb; } [Test] public void DefaultMultiplier_IsOne() { var hb = CreateHurtBox(); Assert.AreEqual(1f, hb.DamageMultiplier); } [Test] public void SetDamageMultiplier_ClampsToNonNegative() { var hb = CreateHurtBox(); hb.SetDamageMultiplier(2.5f); Assert.AreEqual(2.5f, hb.DamageMultiplier); hb.SetDamageMultiplier(-3f); Assert.AreEqual(0f, hb.DamageMultiplier, "负倍率无意义,钳到 0"); } [Test] public void ApplyMultiplier_ScalesRawAmount_AndFloorsAtOne() { var hb = CreateHurtBox(); hb.SetDamageMultiplier(2f); Assert.AreEqual(20, hb.ApplyDamageMultiplier(10)); hb.SetDamageMultiplier(0f); Assert.AreEqual(1, hb.ApplyDamageMultiplier(10), "倍率 0 也至少造成 1 点,与防御减免同规则"); hb.SetDamageMultiplier(1f); Assert.AreEqual(10, hb.ApplyDamageMultiplier(10), "倍率 1 时数值原样通过"); // 倍率 1 必须是"原样通过",而不是"乘完再钳最低 1":10 在两种实现下都得 10, // 只有 0 能把二者区分开。这条断言守住"默认倍率不改变任何既有伤害数值"。 Assert.AreEqual(0, hb.ApplyDamageMultiplier(0), "倍率 1 时原样通过,不引入最低 1 的钳制"); } } }