Files
Commonwealth-Online-Public/docs/phase6-testing-guide.md
T
andrew 56d9c2c514 Add Phase 6 testing docs and update dev-log
Add comprehensive Phase 6 documentation and testing artifacts: a high-level PHASES-1-6 summary, a Phase 6 quick-start checklist, and a detailed Phase 6 testing & iteration guide. Also append a Phase 6 entry to docs/dev-log.md describing the testing framework, test cases (including the critical velocity→animation test), success criteria, and next steps for in-game validation. These docs prepare the repo for Phase 6 in-game testing and outline debugging, performance benchmarks, and iteration procedures.
2026-06-03 17:09:30 +12:00

427 lines
12 KiB
Markdown

# Phase 6: Testing & Iteration - Animation Testing Guide
## Overview
Phase 6 validates that the TiltedEvolution-aligned animation synchronization works end-to-end in Fallout 4. This document provides testing procedures, expected results, and debugging guidance.
**Prerequisites:**
- F4T plugin built and installed
- Fallout 4 running with F4SE
- Network relay server running (`python server.py`)
- Fake client or second F4T instance ready
---
## Testing Phase 6.1: In-Game Animation Testing
### Setup
1. **Start the relay server:**
```bash
cd server/
python server.py
```
2. **Launch F4T with logging enabled:**
- Start Fallout 4 with F4SE
- Plugin loads (check console for logs)
- Remote player should spawn near you
3. **If testing with second instance:**
```bash
# Terminal 1: Relay server
python server/server.py
# Terminal 2: Fake client
python server/fake_client.py
# In-game: Two separate F4T instances, each with F4SE plugin loaded
```
### Test 1: Dynamic Proxy Spawning
**What to test:**
- [ ] Remote player proxy spawns successfully
- [ ] Proxy appears near your position (not at world origin)
- [ ] Multiple proxies can spawn (up to 4 concurrent)
**Expected results:**
- Proxy NPC visible in-game
- Name/ID visible in console logs
- No crashes on spawn
**Debug logs to check:**
```
[Local Player ID: 0] SpawnDynamicProxyActor: Spawned proxy actor <FORMID> for remote player <ID> with base <BASE_FORMID>.
[Local Player ID: 0] Assigned dynamically spawned proxy <FORMID> to remote player <ID>
```
### Test 2: Smooth Movement Synchronization
**What to test:**
- [ ] Remote proxy moves smoothly to player position
- [ ] Movement is not jerky/teleporting
- [ ] Heading (rotation) updates correctly
**Expected results:**
- Proxy walks/runs toward network position
- Smooth interpolation (lerp alpha 0.15)
- No position snapping
**Debug logs to check:**
```
[Local Player ID: 0] First smoothed runtime proxy movement for remote player <ID>: actor=<FORMID>, alpha=0.15.
[Local Player ID: 0] Moved runtime proxy actor <FORMID> from remote player <ID> state for the first time
```
### Test 3: Velocity Injection & Animation Triggering
**CRITICAL TEST:** Does velocity injection cause animations to play?
**What to test:**
- [ ] Proxy plays idle animation when stationary
- [ ] Proxy plays walk animation when moving slowly
- [ ] Proxy plays run animation when moving fast
- [ ] Proxy plays sprint animation when sprinting
**Expected results:**
```
Movement State | Expected Animation
---------------------|---------------------
Stationary | Idle
Speed 0-50 units/s | Walk
Speed 50-100 units/s | Run
Speed 100+ units/s | Sprint
```
**Debug logs to check:**
```
[Local Player ID: 0] ApplyRuntimeProxyTransform: Proxy <FORMID> has AIProcess: true
[Local Player ID: 0] Runtime proxy animation sync <changed/initial> for remote player <ID>:
moving=<bool>, sprinting=<bool>, graphSpeed=<float>
```
**If animations DON'T play:**
1. Check velocity is being set (see console logs)
2. Verify character controller is accessible
3. Check animation graph manager is available
4. Look for "Failed to load animation variables" warnings
### Test 4: Actor State Flags & Sneak Animation
**What to test:**
- [ ] Remote player sneaking → proxy crouches
- [ ] Remote player normal → proxy stands
- [ ] State transitions are smooth
**Expected results:**
- Proxy visibly crouches when remote player crouches
- Proxy crouch pose visible (animation, not just flag)
- No lag in state transition
**Debug logs to check:**
```
[Local Player ID: 0] Moved runtime proxy actor <FORMID> ... flags1=<FLAGS1>, flags2=<FLAGS2>
```
**If sneak animation doesn't work:**
- Sneak might require more than just flags
- May need dedicated action event (Phase 2.3 capture)
- Document in iteration log
### Test 5: Multiple Proxy Actors
**What to test:**
- [ ] 2 simultaneous proxies move smoothly
- [ ] 3 simultaneous proxies move smoothly
- [ ] 4 simultaneous proxies (max) move smoothly
- [ ] No crashes with multiple proxies
**Expected results:**
- Each proxy moves independently to its network position
- All proxies animate correctly
- Performance acceptable (no frame rate drops)
**Debug logs to check:**
```
[Local Player ID: 0] Runtime proxy slot created for remote player <ID> with holding index <INDEX>.
```
---
## Testing Phase 6.2: Performance & Stability Profiling
### Benchmark: Per-Proxy Update Cost
**Metric:** Time to update one proxy per frame
**Measure:**
1. Enable logging: `UpdateProxyAnimationStateDebug` calls
2. Run single proxy moving
3. Monitor console for timing data
4. Expected: < 1ms per proxy update
**Command (in console):**
```
help F4T # Check if debug timers are available
```
### Benchmark: Descriptor vs String-Based Writes
**Phase 5.3 improvement verification:**
**Old way (string-based):**
- Multiple `TrySetGraphFloat()` calls
- Each call: string allocation + graph lookup
**New way (descriptor-based):**
- Single `LoadAnimationVariablesToCache()` call
- Array indexing + one graph manager lock
**Expected result:** Descriptor approach should be ~3-5x faster for animation variable writes.
### Stability: Crash Testing
**What to test:**
- [ ] No crash with 1 proxy moving
- [ ] No crash with 4 proxies moving
- [ ] No crash on proxy disconnect/reconnect
- [ ] No crash on actor reload
**Procedure:**
1. Start with 1 proxy moving smoothly
2. Add proxies one by one
3. Monitor for crashes
4. Try disconnecting/reconnecting
5. Run for 5-10 minutes per configuration
**If crashes occur:**
- Note exact conditions
- Check console for error logs
- Review actor handle validity
- Check for memory leaks
### Stability: Lag Simulation
**What to test:**
- [ ] Proxy handles high-frequency position updates (no lag)
- [ ] Proxy handles low-frequency updates (lerp smoothing works)
- [ ] Proxy handles packet loss gracefully
**Procedure:**
1. Normal case: Remote sends ~10 Hz (working)
2. High frequency: Send 30 Hz updates
3. Low frequency: Send 2 Hz updates
4. Simulate packet loss: Drop 50% of packets
5. Verify proxy still animates correctly
---
## Testing Phase 6.3: Iterate & Tune
### Variable Index Verification
**Goal:** Confirm animation graph variable indices are correct for FO4
**Current assumptions (from Phase 3):**
```cpp
snapshot.floats[0] = Speed;
snapshot.bools[0] = isSprinting;
snapshot.bools[1] = isSneaking;
```
**How to verify:**
1. If animations work → Indices likely correct
2. If animations don't play:
- Enable `F4TLocalAnimationGraphDebug.cpp` debug logging
- Dump actual variable indices from local player
- Compare with descriptor table
- Update `docs/f4-animation-descriptor.md`
**Debug logging (add if needed):**
```cpp
// In ApplyProxyAnimationFromRemoteStateDescriptorBased
LogInfo(std::format("Variable index 'Speed': {}, value: {}",
descriptor.GetFloatVariableIndex("Speed"), desired.graphSpeed));
```
### Velocity Scaling Tuning
**Current scaling (from Phase 4):**
```cpp
float speed = distanceDrift / 0.016F; // Convert to units/sec
float clampedSpeed = min(speed, 400.0F); // Cap at 400 units/sec
```
**Adjustment procedure:**
1. Watch proxy animations while moving
2. If walk animation plays but shouldn't → velocity too high
3. If sprint animation doesn't trigger → velocity too low
4. Adjust multipliers:
```cpp
// Try different scaling
float speed = (distanceDrift / 0.016F) * 0.8F; // Reduce by 20%
```
**Testing different speeds:**
```
Network Speed | Graph Speed | Expected Animation | Adjust If...
2 units/frame | 125 units/s | Sprint | Too low → reduce divisor
1 unit/frame | 62 units/s | Run | Too high → increase divisor
0.5 units | 31 units/s | Walk | Not triggering → reduce
```
### Animation Variable Tuning
**If animations partially work:**
1. **Speed blending isn't smooth:**
- Check `speedDamped` variable (if implemented)
- May need to scale Speed over time (lerp, not snap)
2. **Weapon drawn/sneak animation missing:**
- Confirm variable indices in descriptor
- May need dedicated action events (Phase 2.3)
- Document as limitation
3. **Transitions are jerky:**
- Velocity might be changing too rapidly
- Add smoothing: lerp velocity over 0.1-0.2 seconds
- Or increase lerp alpha on position (currently 0.15)
---
## Test Results Template
Create a new dev-log entry (example):
```
## Test Session: <DATE> - <TESTER>
### Session Setup
- Number of proxies: 1/2/4
- Duration: 5 minutes
- Network condition: Normal/Lag/Packet Loss
### Test 1: Dynamic Spawning
- [x] Proxy spawned successfully
- [ ] Proxy appeared at correct location
- Result: PASS/FAIL/PARTIAL
### Test 2: Smooth Movement
- [x] Movement is smooth
- [ ] No visible jitter
- Result: PASS/FAIL/PARTIAL
### Test 3: Animation Triggering (CRITICAL)
- [ ] Idle animation plays
- [ ] Walk animation plays
- [ ] Run animation plays
- [ ] Sprint animation plays
- Result: PASS/FAIL/PARTIAL
- Notes: <describe any issues>
### Test 4: Sneak Animation
- [ ] Crouch plays when sneaking
- Result: PASS/FAIL/PARTIAL
### Test 5: Multiple Proxies (4x)
- [ ] All 4 proxies move smoothly
- [ ] No crashes
- [ ] Frame rate acceptable
- Result: PASS/FAIL/PARTIAL
### Performance Metrics
- Per-proxy update time: <N> ms
- Descriptor bulk write time: <N> ms
- Frame rate: <N> fps
### Issues Found
1. <Issue description>
- Severity: Critical/Major/Minor
- Workaround: <if any>
- Fix needed in: <file/phase>
### Conclusion
Overall result: READY FOR PHASE 7 / NEEDS ITERATION / NEEDS FIXES
### Next Steps
- <Action items>
```
---
## Debugging Checklist
If animations aren't working:
1. **Verify velocity is being set:**
```
Search logs for: "ApplyRuntimeProxyTransform"
Should show: Character controller velocity being set
```
2. **Verify actor state flags are applied:**
```
Search logs for: "Moved runtime proxy actor ... flags1="
Should show non-zero flags if remote player in combat/sneak
```
3. **Verify animation variables are being written:**
```
Search logs for: "Runtime proxy animation sync"
Should show Speed values changing (not always 0)
```
4. **Check if animation graph manager is available:**
```
Search logs for: "animation graph manager unavailable"
If present: Graph manager not accessible
```
5. **Enable full animation debugging:**
- Set logging interval to 100ms (from 2s)
- Enables detailed animation state transitions
- Generates large log files
---
## Common Issues & Fixes
| Issue | Possible Cause | Fix |
|-------|---|---|
| Proxy doesn't spawn | PlaceAtMe failed | Check proxy base actor exists |
| Proxy stands still | Velocity not set | Verify character controller access |
| Walk/run doesn't play | Speed variable wrong index | Check f4-animation-descriptor.md indices |
| Sneak doesn't work | Needs action replay | Phase 2.3 action capture needed |
| Multiple proxies crash | Handle leak | Check proxy pool cleanup |
| Frame rate drops | Too many descriptor writes | Already optimized; check log frequency |
---
## Success Criteria (Phase 6 Complete)
- ✅ Proxy spawns and moves smoothly (dynamic)
- ✅ Velocity injection triggers animation system
- ✅ At least idle/walk/run animations visible
- ✅ Multiple proxies (4x) stable and animating
- ✅ No crashes in 10-minute test session
- ✅ Performance acceptable (< 1ms per proxy update)
- ✅ Actor state flags affect proxy (sneak at minimum)
---
## Ready for Phase 7?
If all tests PASS:
→ Phase 7: Cleanup & Documentation
If tests FAIL/PARTIAL:
→ Iterate Phase 6.3 (tune velocity/variables)
→ Return to Phase 5 if infrastructure issues found
If tests CRASH:
→ Debug and fix issues
→ Return to Phase 4-5 as needed