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.
427 lines
12 KiB
Markdown
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
|
|
|