Skip to content

feat: Pause-point snapshots now identify which instance was hit#1737

Merged
hatayama merged 3 commits into
v3-betafrom
feat/pause-point-capture-this
Jul 13, 2026
Merged

feat: Pause-point snapshots now identify which instance was hit#1737
hatayama merged 3 commits into
v3-betafrom
feat/pause-point-capture-this

Conversation

@hatayama

@hatayama hatayama commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Every pause-point hit now includes a synthetic this entry in CapturedVariables, so the snapshot tells you which instance (and which GameObject, via its hierarchy path and InstanceID) the pause landed on.
  • While paused, UloopPausePoint.TryGetCapturedValue("this") returns the live instance reference, so watch expressions and dynamic code can read values like transform.position even when no captured field references a Unity object.

User Impact

  • Before: the snapshot listed instance fields but not the instance itself. With the same script attached to multiple GameObjects there was no way to tell which one was hit, and scripts without any UnityEngine.Object field gave watch expressions no path to reach the instance at all.
  • After: the this entry (new Scope This) carries UnityObjectKind, UnityObjectPath, and UnityObjectInstanceId for Unity objects, identifying the hit instance at a glance and opening the raw-capture route to it.

Changes

  • Emit one this entry after locals/parameters and before instance fields, so the variable-count cap keeps prioritizing locals and parameters. No property expansion; it is a single compact entry.
  • Async/coroutine methods resolve this to the original outer instance (via the hoisted state-machine reference), never the compiler-generated state machine. Static methods — and the byref-like struct path, where the patcher passes a null instance — emit no entry.
  • Added the This scope constant; the wire format is unchanged (Scope is passed through as a string), so no protocol version bump.
  • Updated the pause-point skill doc (source under CliOnlyTools~; the .agents//.claude/ copies were regenerated by the installer).
  • Updated five pre-existing tests that pinned exact captured-variable name lists from before the this entry existed; assertions stay exact, now including this at its spec'd position.

Verification

  • uloop compile: 0 errors, 0 warnings
  • uloop run-tests (EditMode, all pause-point suites): 144 passed / 0 failed, including 6 new collector tests (normal instance, entry ordering, state-machine outer-this resolution, missing outer-this, null instance, count-cap truncation)

hatayama added 2 commits July 13, 2026 13:12
Instance fields were captured but the paused instance itself was not,
so a hit could not identify which instance or GameObject it landed on
(name, hierarchy path, InstanceID), and scripts without any
UnityEngine.Object field gave watch expressions no path to reach the
instance via UloopPausePoint.TryGetCapturedValue.

- Emit a "this" entry (new Scope "This") after locals/parameters and
  before instance fields, so the count cap keeps prioritizing
  locals/params; the existing formatter then attaches
  UnityObjectKind/Path/InstanceId for UnityEngine.Object instances
- For async/coroutine state machines, resolve "this" to the hoisted
  outer instance via <>4__this and never surface the compiler-generated
  state machine; static methods emit no entry
Explain the new This scope, how the this entry identifies the hit
instance via UnityObjectPath/UnityObjectInstanceId, and how
TryGetCapturedValue("this") exposes the live reference while paused.
Skill copies under .agents/ and .claude/ are regenerated from the
source skill by the installer, not hand-edited.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a public This capture scope and emits a synthetic "this" variable for paused instance methods, including async/state-machine resolution. Updates collector tests, formatting and patcher expectations, file/line tests, and pause-point documentation.

Changes

Captured instance support

Layer / File(s) Summary
This scope contract and documentation
Packages/src/Runtime/PausePoints/UloopCapturedVariableScope.cs, .agents/.../SKILL.md, .claude/.../SKILL.md, Packages/src/Editor/CliOnlyTools~/PausePoint/SKILL.md
Adds the This scope and documents synthetic "this" capture behavior for instance, async, coroutine, and static methods.
Paused instance collection
Packages/src/Editor/FirstPartyTools/PausePoint/SourcePausePointVariableCollector.cs
Emits a synthetic "this" entry for normal instances and resolves async/state-machine instances to their hoisted outer instance before collecting fields.
Collection behavior tests
Assets/Tests/Editor/SourcePausePointCapture/SourcePausePointCaptureTests.cs
Covers entry creation, ordering, state-machine resolution, null/static instances, and count-cap truncation.
Formatting and pause-point expectations
Assets/Tests/Editor/SourcePausePointCapture/SourcePausePointVariableFormatterTests.cs, Assets/Tests/Editor/SourcePausePointPatcher/SourcePausePointPatcherTests.cs, Assets/Tests/Editor/PausePointTests.cs
Updates captured-variable ordering and end-to-end expectations to include "this".

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PausePoint
  participant SourcePausePointVariableCollector
  participant AsyncStateMachine
  participant CapturedVariables
  PausePoint->>SourcePausePointVariableCollector: collect paused instance variables
  SourcePausePointVariableCollector->>AsyncStateMachine: inspect instance type
  AsyncStateMachine->>SourcePausePointVariableCollector: provide hoisted outer instance
  SourcePausePointVariableCollector->>CapturedVariables: add synthetic "this"
  SourcePausePointVariableCollector->>CapturedVariables: add locals, parameters, and instance fields
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: pause-point snapshots now identify the instance that was hit.
Description check ✅ Passed The description is detailed and directly matches the captured this entry, behavior, and test updates in the changeset.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pause-point-capture-this

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Five pre-existing tests pinned exact captured-variable name lists from
before the synthetic "this" entry existed. Update the expected
sequences (and their explanatory comments) to include "this" at its
spec'd position between parameters and instance fields; assertions stay
exact rather than being loosened. The byref-like struct path is
unchanged: the patcher passes a null instance there, so no "this"
entry is expected.
@hatayama hatayama merged commit a086ac9 into v3-beta Jul 13, 2026
10 checks passed
@hatayama hatayama deleted the feat/pause-point-capture-this branch July 13, 2026 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant