摄像机区域的架构改动

This commit is contained in:
2026-05-15 14:47:24 +08:00
parent 1b37297585
commit f264329751
3591 changed files with 1687228 additions and 446503 deletions

View File

@@ -0,0 +1,222 @@
# 单元测试 03 · 状态效果系统StatusEffects
> **测试类型**EditMode 单元测试NUnit
> **测试文件**`Assets/Tests/EditMode/StatusEffectTests.cs`(已存在,本文为完整规范)
> **被测程序集**`BaseGames.Combat.StatusEffects`
> **asmdef 依赖**`BaseGames.Tests.EditMode.asmdef` 需引用 `BaseGames.Combat.StatusEffects`
---
## 目录
1. [测试覆盖范围](#1-测试覆盖范围)
2. [现有测试验证](#2-现有测试验证)
3. [补充测试说明](#3-补充测试说明)
4. [完整扩展测试代码](#4-完整扩展测试代码)
5. [手动集成验证Play Mode](#5-手动集成验证play-mode)
---
## 1. 测试覆盖范围
| 类 | 测试点 |
|----|--------|
| `FireEffect` | MaxStacks=1MutualExclusions 含 FreezeOnStack 刷新持续时间EffectType=Fire |
| `PoisonEffect` | MaxStacks=3MutualExclusions 为空OnStack 增加 StackCount超限截断EffectType=Poison |
| `StaggerEffect` | MaxStacks=1BlockedBy 含 StunEffectType=Stagger |
| `StatusEffect` 基类 | IsExpired 在 Duration 耗尽后为 trueUpdate 正确减少剩余时间 |
| `StatusEffectManager` | ApplyEffect 正确添加;互斥效果自动移除;到期效果自动清理(需 MonoBehaviour Test 或接口 Mock |
---
## 2. 现有测试验证
项目已存在 `Assets/Tests/EditMode/StatusEffectTests.cs`,覆盖以下测试(共 14 个):
| 测试名 | 验证点 |
|--------|--------|
| `FireEffect_MaxStacks_IsOne` | FireEffect.MaxStacks == 1 |
| `PoisonEffect_MaxStacks_IsThree` | PoisonEffect.MaxStacks == 3 |
| `PoisonEffect_OnStack_IncreasesStackCount` | OnStack 后 StackCount == 2 |
| `PoisonEffect_OnStack_ClampsAtMaxStacks` | 多次叠加不超过 MaxStacks |
| `StaggerEffect_MaxStacks_IsOne` | StaggerEffect.MaxStacks == 1 |
| `FireEffect_MutualExclusions_ContainsFreeze` | MutualExclusions 含 Freeze |
| `PoisonEffect_MutualExclusions_IsEmpty` | PoisonEffect 无互斥 |
| `StaggerEffect_BlockedBy_ContainsStun` | BlockedBy 含 Stun |
| `FireEffect_BlockedBy_IsEmpty` | FireEffect 无阻断 |
| `StatusEffect_IsExpired_AfterDurationDepleted` | 时间耗尽后 IsExpired == true |
| `FireEffect_OnStack_RefreshDuration` | OnStack 刷新剩余时间 |
| `FireEffect_EffectType_IsFire` | EffectType == StatusEffectType.Fire |
| `PoisonEffect_EffectType_IsPoison` | EffectType == StatusEffectType.Poison |
| `StaggerEffect_EffectType_IsStagger` | EffectType == StatusEffectType.Stagger |
**运行现有测试步骤:**
1. 打开 `Window → General → Test Runner`
2. 选择 `EditMode` 标签页
3. 展开 `BaseGames.Tests.EditMode → StatusEffectTests`
4. 点击 `Run All`(或右键 `Run`
5. 确认所有 14 个测试 **全部绿色**
---
## 3. 补充测试说明
现有测试未覆盖以下场景,需补充:
### 3.1 StatusEffect.Update 时间精度
验证 `Update(delta)` 正确累计时间,不因浮点精度导致 IsExpired 判断提前/延迟。
### 3.2 多效果独立计时
同时持有 `FireEffect``PoisonEffect` 时,两个效果的剩余时间独立递减,互不影响。
### 3.3 OnApply / OnRemove 回调
`OnApply(owner)``OnRemove(owner)` 在正确时机被调用owner 可传 `null` 用于纯计时测试)。
### 3.4 StackCount 初始值
新建 Effect 时 `StackCount == 1`(已 Apply 一层)。
---
## 4. 完整扩展测试代码
将以下代码**追加**到现有 `StatusEffectTests.cs``}` 前,或创建新文件 `StatusEffectExtendedTests.cs`
```csharp
// 追加到 BaseGames.Tests.EditMode 命名空间下StatusEffectTests 类中
// ── 补充测试 ────────────────────────────────────────────────────────────────
[Test]
public void StatusEffect_StackCount_InitialValueIsOne()
{
var effect = new FireEffect();
Assert.AreEqual(1, effect.StackCount, "新建 Effect 的初始 StackCount 应为 1");
}
[Test]
public void StatusEffect_Update_RemainingTime_Decreases()
{
var effect = new StaggerEffect(2.0f);
effect.OnApply(null);
float initialDuration = effect.Duration;
effect.Update(0.5f);
Assert.Less(effect.Duration, initialDuration, "Update 后剩余时间应减少");
Assert.IsFalse(effect.IsExpired, "0.5s Update 后 2.0s 效果不应过期");
}
[Test]
public void StatusEffect_Update_ExactExpiry()
{
var effect = new StaggerEffect(1.0f);
effect.OnApply(null);
effect.Update(1.0f); // 恰好耗尽
Assert.IsTrue(effect.IsExpired, "恰好耗尽 duration 后应 IsExpired == true");
}
[Test]
public void MultipleEffects_IndependentTimers()
{
var fire = new FireEffect();
var poison = new PoisonEffect();
fire.OnApply(null);
poison.OnApply(null);
float fireDuration = fire.Duration;
float poisonDuration = poison.Duration;
fire.Update(0.5f);
// poison 未调用 Update时间不应变化
Assert.AreEqual(poisonDuration, poison.Duration, 0.0001f,
"未 Update 的 Effect 持续时间不应减少");
Assert.Less(fire.Duration, fireDuration, "已 Update 的 Effect 持续时间应减少");
}
[Test]
public void PoisonEffect_OnStack_DoesNotExceedMaxStacks_EdgeCase()
{
var effect = new PoisonEffect();
// MaxStacks = 3初始 StackCount = 1再叠加 2 次达到上限
effect.OnStack();
effect.OnStack();
Assert.AreEqual(3, effect.StackCount);
// 再叠加,不应超过 3
effect.OnStack();
effect.OnStack();
Assert.AreEqual(3, effect.StackCount, "StackCount 不应超过 MaxStacks");
}
[Test]
public void FireEffect_OnApply_ThenRemove_DoesNotThrow()
{
var effect = new FireEffect();
Assert.DoesNotThrow(() =>
{
effect.OnApply(null);
effect.OnRemove(null);
});
}
```
---
## 5. 手动集成验证Play Mode
以下场景需要在 Unity Editor 中手动测试(无法在 EditMode 测试中验证):
### 5.1 StatusEffectManager 添加效果
**前提条件**:测试场景中有玩家或敌人,其 GameObject 挂有 `StatusEffectManager` 组件。
**步骤:**
1. 进入 Play Mode
2. 在 Inspector 中找到目标对象的 `StatusEffectManager` 组件
3. 通过 Console 调用(或临时测试按钮):`statusEffectManager.Apply(new PoisonEffect())`
4. 在 Console 中观察 Poison 效果 Tick 日志(每 `tickInterval` 秒一条)
**预期结果:**
- Poison 效果持续 `duration`
- 每次 Tick 扣减目标 HP
- 到期后自动从管理器移除,不再 Tick
### 5.2 互斥效果测试
**步骤:**
1. 对同一目标施加 `FireEffect`
2. 随后施加 `FreezeEffect`FireEffect 的 MutualExclusion
**预期结果:**
- `FireEffect` 被自动移除
- Console 无 `NullReferenceException`
### 5.3 效果叠加Poison
**步骤:**
1. 对目标施加 `PoisonEffect`StackCount = 1
2. 再施加一次 `PoisonEffect`
3. 再施加一次StackCount 达到 3
4. 再施加一次(超过上限)
**预期结果:**
- StackCount 分别变为 2、3、3截断
- Inspector 中 `StatusEffectManager` 显示正确的 StackCount
### 5.4 阻断效果StaggerEffect BlockedBy Stun
**步骤:**
1. 对目标先施加 `StunEffect`
2. 尝试施加 `StaggerEffect`
**预期结果:**
- `StaggerEffect` 被阻断,未添加到管理器
- Console 无报错