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.
12 KiB
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
-
Start the relay server:
cd server/ python server.py -
Launch F4T with logging enabled:
- Start Fallout 4 with F4SE
- Plugin loads (check console for logs)
- Remote player should spawn near you
-
If testing with second instance:
# 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:
- Check velocity is being set (see console logs)
- Verify character controller is accessible
- Check animation graph manager is available
- 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:
- Enable logging:
UpdateProxyAnimationStateDebugcalls - Run single proxy moving
- Monitor console for timing data
- 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:
- Start with 1 proxy moving smoothly
- Add proxies one by one
- Monitor for crashes
- Try disconnecting/reconnecting
- 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:
- Normal case: Remote sends ~10 Hz (working)
- High frequency: Send 30 Hz updates
- Low frequency: Send 2 Hz updates
- Simulate packet loss: Drop 50% of packets
- 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):
snapshot.floats[0] = Speed;
snapshot.bools[0] = isSprinting;
snapshot.bools[1] = isSneaking;
How to verify:
- If animations work → Indices likely correct
- If animations don't play:
- Enable
F4TLocalAnimationGraphDebug.cppdebug logging - Dump actual variable indices from local player
- Compare with descriptor table
- Update
docs/f4-animation-descriptor.md
- Enable
Debug logging (add if needed):
// In ApplyProxyAnimationFromRemoteStateDescriptorBased
LogInfo(std::format("Variable index 'Speed': {}, value: {}",
descriptor.GetFloatVariableIndex("Speed"), desired.graphSpeed));
Velocity Scaling Tuning
Current scaling (from Phase 4):
float speed = distanceDrift / 0.016F; // Convert to units/sec
float clampedSpeed = min(speed, 400.0F); // Cap at 400 units/sec
Adjustment procedure:
- Watch proxy animations while moving
- If walk animation plays but shouldn't → velocity too high
- If sprint animation doesn't trigger → velocity too low
- Adjust multipliers:
// 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:
-
Speed blending isn't smooth:
- Check
speedDampedvariable (if implemented) - May need to scale Speed over time (lerp, not snap)
- Check
-
Weapon drawn/sneak animation missing:
- Confirm variable indices in descriptor
- May need dedicated action events (Phase 2.3)
- Document as limitation
-
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:
-
Verify velocity is being set:
Search logs for: "ApplyRuntimeProxyTransform" Should show: Character controller velocity being set -
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 -
Verify animation variables are being written:
Search logs for: "Runtime proxy animation sync" Should show Speed values changing (not always 0) -
Check if animation graph manager is available:
Search logs for: "animation graph manager unavailable" If present: Graph manager not accessible -
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