diag(motion): #39 — per-tick [CURRNODE] for sequencer node identity
Visual-verify of fix #2 (commit 863d96b) showed [SCFULL] correctly reports
currNodeIsCyclic=True after each direct Walk↔Run SetCycle (the link is
removed and _currNode is set to _firstCyclic). User report still:
- Animation continues running visually after Shift toggle to Walk
- Body slows ("speed decreases"), causing rubber-banding
- Adding a turn motion in that state makes the cycle finally transition
to walking
So either:
- _currNode is reset to a stale node BETWEEN SetCycle and Advance
- _currNode is correctly on the new cycle but its AnimRef is wrong
(e.g., the same Animation as the previous cycle, dat-side issue)
- BuildBlendedFrame reads from somewhere other than _currNode
Adds CurrentNodeDiag + FirstCyclicAnimRefHash properties on
AnimationSequencer that expose the active node's Animation
identity-hash, IsLooping, Framerate, frame range, and FramePosition.
TickAnimations logs them on every SEQSTATE tick (1 Hz throttle, gated
on ACDREAM_REMOTE_VEL_DIAG=1).
The [CURRNODE] line with animRef vs firstCyclicAnimRef proves whether
_currNode is actually on the new cycle's anim or has drifted to
something else. Compared across SetCycle SCFULL log lines + the
following CURRNODE ticks, we can see the exact moment the cycle
diverges from what SetCycle set.
No code-behavior changes. Pure read-only instrumentation. Per
Phase 4.5 of systematic-debugging — STOP attempting fixes; gather
evidence first.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
863d96bb23
commit
bb026b7991
2 changed files with 50 additions and 0 deletions
|
|
@ -6805,6 +6805,23 @@ public sealed class GameWindow : IDisposable
|
|||
System.Console.WriteLine(
|
||||
$"[SEQSTATE] guid={serverGuid:X8} CurrentMotion=0x{ae.Sequencer.CurrentMotion:X8} "
|
||||
+ $"CurrentSpeedMod={ae.Sequencer.CurrentSpeedMod:F3}");
|
||||
|
||||
// #39 fix-3 evidence (2026-05-06): CURRNODE proves
|
||||
// whether _currNode is actually on the cycle (anim
|
||||
// ref hash matches FirstCyclic) or stuck somewhere
|
||||
// else. SCFULL captures _currNode==_firstCyclic only
|
||||
// at SetCycle return; this captures it per render
|
||||
// tick so we can see if something resets it later.
|
||||
var d = ae.Sequencer.CurrentNodeDiag;
|
||||
int firstHash = ae.Sequencer.FirstCyclicAnimRefHash;
|
||||
System.Console.WriteLine(
|
||||
$"[CURRNODE] guid={serverGuid:X8} "
|
||||
+ $"animRef=0x{d.AnimRefHash:X8} firstCyclicAnimRef=0x{firstHash:X8} "
|
||||
+ $"isOnCyclic={d.AnimRefHash == firstHash && firstHash != 0} "
|
||||
+ $"isLooping={d.IsLooping} fr={d.Framerate:F2} "
|
||||
+ $"frame=[{d.StartFrame}..{d.EndFrame}] "
|
||||
+ $"pos={d.FramePosition:F2} qCount={d.QueueCount}");
|
||||
|
||||
rmDiag.LastSeqStateLogTime = nowSec;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,6 +254,39 @@ public sealed class AnimationSequencer
|
|||
public int QueueCount => _queue.Count;
|
||||
public bool HasCurrentNode => _currNode != null;
|
||||
|
||||
/// <summary>
|
||||
/// Diagnostic snapshot of <c>_currNode</c>'s identity + frame state, for
|
||||
/// the per-tick CURRNODE log line in <c>GameWindow.TickAnimations</c>.
|
||||
/// Lets the caller see whether the actual node being read by Advance /
|
||||
/// BuildBlendedFrame is what SetCycle was supposed to leave it on.
|
||||
/// AnimRefHash uses object-identity hashing on the Animation reference
|
||||
/// so different Walk vs Run anim resources can be distinguished even
|
||||
/// without exposing the full Animation type.
|
||||
/// </summary>
|
||||
public (int AnimRefHash, bool IsLooping, double Framerate, int StartFrame, int EndFrame, double FramePosition, int QueueCount) CurrentNodeDiag
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_currNode is null)
|
||||
return (0, false, 0.0, 0, 0, 0.0, _queue.Count);
|
||||
var n = _currNode.Value;
|
||||
int hash = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(n.Anim);
|
||||
return (hash, n.IsLooping, n.Framerate, n.StartFrame, n.EndFrame, _framePosition, _queue.Count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diagnostic: the AnimRefHash for the FIRST cyclic node in the queue
|
||||
/// (i.e., what SetCycle is trying to land us on for a locomotion cycle).
|
||||
/// Compare against <see cref="CurrentNodeDiag"/>'s AnimRefHash to see
|
||||
/// whether <c>_currNode</c> is actually pointing at the new cycle or
|
||||
/// something stale.
|
||||
/// </summary>
|
||||
public int FirstCyclicAnimRefHash =>
|
||||
_firstCyclic is null
|
||||
? 0
|
||||
: System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(_firstCyclic.Value.Anim);
|
||||
|
||||
// ── Private state ────────────────────────────────────────────────────────
|
||||
|
||||
private readonly Setup _setup;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue