Summary
The package already keeps Unity's "The open scene(s) have been modified externally — Ignore / Reload" dialog away from the common paths. uloop compile runs an external Scene change preflight, and a focus return runs another (see docs/focus-return-asset-handling.md). Two gaps remain:
- With Auto Refresh Enabled, an external Scene change that is not followed by a focus return shows the dialog right after Play Mode stops. It then blocks
uloop control-play-mode --action Stop.
- Answering the dialog can crash Unity 2022.3. This makes gap 1, and any other way the dialog appears, more costly than a stalled command.
Gap 1: dialog after Stop with Auto Refresh Enabled
Observed on Unity 2022.3.62f3, macOS:
- A Scene saved under
Assets/ is open in the Editor with no unsaved changes, and Auto Refresh is set to Enabled.
- The Scene file is changed on disk (a root GameObject renamed with
sed) while no focus return follows. The change happened while Unity was focused. The same would happen with an Editor that stays unfocused throughout.
uloop control-play-mode --action Play starts Play Mode without a dialog, running the in-memory (old) Scene content.
uloop control-play-mode --action Stop: the dialog appears as the Editor returns to Edit Mode, and the Stop request does not return until it is answered.
With Auto Refresh Disabled, the same Stop returned to Edit Mode and loaded the new file content for the clean Scene silently.
Probable cause: the focus-return preflight is deferred during Play Mode and runs on EnteredEditMode only when a focus return was actually deferred. Here no focus return happened, so nothing reloads the changed Scene before Unity's own tick raises the dialog. This has not been confirmed in code.
What we know works: calling AssetDatabase.Refresh() and reopening the clean Scene in the same frame, before the next Editor tick, prevented the dialog. Reopening the Scene before the refresh did not. That matches the existing compile preflight, which imports the changed Scene first and then reloads it.
A possible fix is to run the fingerprint comparison on EnteredEditMode whenever a Scene changed on disk, whether or not a focus return was deferred. Whether that runs before Unity's tick handler on the Auto Refresh path still has to be checked.
Gap 2: answering the dialog crashed the Editor
On the same Editor, answering the dialog crashed Unity twice, once with Ignore and once with Reload. Both crashes were SIGSEGV (KERN_INVALID_ADDRESS at 0x38) inside EditorSceneManager::HandleOpenScenesChangeOnDisk(), called from EditorSceneManager::OnApplicationTick(). One further answer did not crash. In both crashes a uloop request was waiting for the Editor while the dialog was up (an execute-dynamic-code call, and the Stop above). Whether that pending request is involved is unconfirmed.
Open questions
- Whether Unity 6 behaves the same for both gaps.
- Whether a Prefab Stage has the same gap after Stop (it has its own "Prefab Has Been Changed on Disk" prompt).
Related
Summary
The package already keeps Unity's "The open scene(s) have been modified externally — Ignore / Reload" dialog away from the common paths.
uloop compileruns an external Scene change preflight, and a focus return runs another (seedocs/focus-return-asset-handling.md). Two gaps remain:uloop control-play-mode --action Stop.Gap 1: dialog after Stop with Auto Refresh Enabled
Observed on Unity 2022.3.62f3, macOS:
Assets/is open in the Editor with no unsaved changes, and Auto Refresh is set to Enabled.sed) while no focus return follows. The change happened while Unity was focused. The same would happen with an Editor that stays unfocused throughout.uloop control-play-mode --action Playstarts Play Mode without a dialog, running the in-memory (old) Scene content.uloop control-play-mode --action Stop: the dialog appears as the Editor returns to Edit Mode, and the Stop request does not return until it is answered.With Auto Refresh Disabled, the same Stop returned to Edit Mode and loaded the new file content for the clean Scene silently.
Probable cause: the focus-return preflight is deferred during Play Mode and runs on
EnteredEditModeonly when a focus return was actually deferred. Here no focus return happened, so nothing reloads the changed Scene before Unity's own tick raises the dialog. This has not been confirmed in code.What we know works: calling
AssetDatabase.Refresh()and reopening the clean Scene in the same frame, before the next Editor tick, prevented the dialog. Reopening the Scene before the refresh did not. That matches the existing compile preflight, which imports the changed Scene first and then reloads it.A possible fix is to run the fingerprint comparison on
EnteredEditModewhenever a Scene changed on disk, whether or not a focus return was deferred. Whether that runs before Unity's tick handler on the Auto Refresh path still has to be checked.Gap 2: answering the dialog crashed the Editor
On the same Editor, answering the dialog crashed Unity twice, once with Ignore and once with Reload. Both crashes were SIGSEGV (
KERN_INVALID_ADDRESS at 0x38) insideEditorSceneManager::HandleOpenScenesChangeOnDisk(), called fromEditorSceneManager::OnApplicationTick(). One further answer did not crash. In both crashes aulooprequest was waiting for the Editor while the dialog was up (anexecute-dynamic-codecall, and the Stop above). Whether that pending request is involved is unconfirmed.Open questions
Related
control-play-modePlay no longer saves dirty Scenes by default.