stop the Yarn setup menu from overwriting a real scene

Fixes "Can't start dialogue: no Yarn Project has been configured."

Cause, and it was mine. Phase 3.7 said "retarget YarnDemoSetup.cs or retire it";
I retargeted it. But that menu does not modify a scene — it builds one from
scratch and calls SaveScene over its target. Pointing it at
SC101_ConferenceHall.unity armed it at the real level, and running it replaced
the scene with a bare Yarn demo: ten of fourteen roots gone, including the
player, the lighting and the navmesh. The leftover Dialogue System prefab
instance it left behind had no yarnProject override, auto-started, and produced
the error.

The scene was committed, so nothing was lost; it is restored from HEAD at 14
roots with its sun reference intact.

The menu now targets Assets/Scenes/Dev/YarnSandbox.unity and refuses to run if
its target is not under Scenes/Dev, via ScenePaths.IsDisposable. It is renamed
to "Set Up Yarn Sandbox Scene" so the menu says what it does. The other three
setup menus open and modify their target rather than regenerating it, so they
were never affected and are unchanged.

The test suite could not have caught this, because it asserted only that a
DialogueRunner existed. TheDialogueRunner_HasItsYarnProject now asserts there is
exactly one runner across the loaded scenes and that its project is set and
compiled — which reproduces the failure exactly when the scene is broken.

Also here: four UI prefabs pick up m_EditorClassIdentifier changes from
Assembly-CSharp to NightclubArcadia.Game, written by Unity after the assembly
split in the previous commit. Expected and correct.

EditMode 42/42, PlayMode 6/6, YarnCheck 9 files / 35 nodes.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-25 21:14:13 +02:00
co-authored by Claude Opus 5
parent ad598143f8
commit 46160d86dc
8 changed files with 243 additions and 170 deletions
+16 -8
View File
@@ -486,24 +486,32 @@ should not be — see `docs/restructure-plan.md`.
four runtime files use — without that, everything referencing it would have stopped compiling.
Keep it in mind before adding loose scripts outside an asmdef folder.
5. **`unity run` reserves `-batchmode`, `-nographics`, `-quit`, `-logFile`.** Passing any of them
5. **`Tools ▸ Nightclub Arcadia ▸ Set Up Yarn Sandbox Scene` overwrites its target scene
wholesale.** It builds a scene from scratch and calls `SaveScene` over `ScenePath`. It is
pinned to `Assets/Scenes/Dev/` and guarded by `ScenePaths.IsDisposable`, because it was once
briefly retargeted at `SC101_ConferenceHall` and destroyed it — ten of fourteen roots, the
player and the lighting included. **Never point a scene-generating menu at a real scene.**
The other three setup menus (`PlayerControlSetup`, `UILayerSetup`, `SkillSystemSetup`) open
and modify their target, which is safe.
6. **`unity run` reserves `-batchmode`, `-nographics`, `-quit`, `-logFile`.** Passing any of them
after `--` is a hard error, and its output does not reach stdout — read `Logs/Editor.log` (§3.4).
6. **`-quit` with `-runTests`** hangs or truncates. Omit it (§3.2).
7. **`-quit` with `-runTests`** hangs or truncates. Omit it (§3.2).
7. **Exit code alone is not a test verdict.** Parse the results XML (§3.2), which is what
8. **Exit code alone is not a test verdict.** Parse the results XML (§3.2), which is what
`make test` does.
8. **`which unity` fails** in non-interactive shells even though the CLI is installed. Use the
9. **`which unity` fails** in non-interactive shells even though the CLI is installed. Use the
absolute path `/Users/lennart/.unity/bin/unity` (§3.0).
9. **Editor lock** — check before every headless run, filtering out `AssetImportWorker` children.
10. **Editor lock** — check before every headless run, filtering out `AssetImportWorker` children.
`make test` and `make build` do this for you (§2b).
10. **Regenerated assets** — hand edits to `Skills/Definitions/*`, `Candidates/Definitions/*`
11. **Regenerated assets** — hand edits to `Skills/Definitions/*`, `Candidates/Definitions/*`
and the two `*Database.asset` files are silently discarded (§2.1).
11. **`top_skill` ties** resolve to the first argument. Reordering arguments changes the game.
12. **`top_skill` ties** resolve to the first argument. Reordering arguments changes the game.
12. **`Bootstrap` must stay index 0** in the build settings, and all three scenes must be listed,
13. **`Bootstrap` must stay index 0** in the build settings, and all three scenes must be listed,
or `LoadSceneAsync` by name fails at runtime with nothing but a console error.
+24 -1
View File
@@ -15,7 +15,30 @@ namespace NightclubArcadia.EditorTools
/// <summary>Persistent systems: dialogue, skills, UI, camera rig, player.</summary>
public const string Systems = "Assets/Scenes/Systems/Systems.unity";
/// <summary>The scene the setup menus wire into. SC-101's conference hall.</summary>
/// <summary>
/// The scene the setup menus wire into. SC-101's conference hall.
///
/// Only for menus that OPEN and MODIFY a scene. A menu that builds a scene from
/// scratch and saves over its target must never point here — see Sandbox.
/// </summary>
public const string WorkingLevel = "Assets/Scenes/Levels/SC101_ConferenceHall.unity";
/// <summary>
/// Scratch scene for menus that generate a scene wholesale.
///
/// This exists because pointing such a menu at WorkingLevel destroyed it once:
/// YarnDemoSetup builds a demo scene and calls SaveScene over its target, so
/// running it replaced SC-101 with a bare Yarn demo. Anything under Scenes/Dev
/// is disposable by definition; nothing outside it is.
/// </summary>
public const string Sandbox = "Assets/Scenes/Dev/YarnSandbox.unity";
/// <summary>
/// Guard for any menu that overwrites a whole scene. Generated scenes belong in
/// Scenes/Dev and nowhere else.
/// </summary>
public static bool IsDisposable(string scenePath) =>
!string.IsNullOrEmpty(scenePath) &&
scenePath.Replace('\\', '/').StartsWith("Assets/Scenes/Dev/", System.StringComparison.Ordinal);
}
}
@@ -9,11 +9,27 @@ using Yarn.Unity.Editor;
public static class YarnDemoSetup
{
const string YarnProjectPath = "Assets/Dialogue/NightclubArcadia.yarnproject";
const string ScenePath = NightclubArcadia.EditorTools.ScenePaths.WorkingLevel;
const string ScenePath = NightclubArcadia.EditorTools.ScenePaths.Sandbox;
[MenuItem("Tools/Nightclub Arcadia/Set Up Yarn Dialogue Test")]
[MenuItem("Tools/Nightclub Arcadia/Set Up Yarn Sandbox Scene")]
public static void SetUpYarnDialogueTest()
{
// This menu BUILDS A SCENE FROM SCRATCH and saves over ScenePath. Pointed at a
// real level it silently destroys it, which is exactly what happened when it
// was briefly retargeted at SC101_ConferenceHall. The guard is the fix; do not
// remove it, and do not point ScenePath outside Scenes/Dev.
if (!NightclubArcadia.EditorTools.ScenePaths.IsDisposable(ScenePath))
{
Debug.LogError($"Refusing to run: '{ScenePath}' is not under Assets/Scenes/Dev/. " +
"This menu overwrites its target scene wholesale.");
return;
}
if (!AssetDatabase.IsValidFolder("Assets/Scenes/Dev"))
{
AssetDatabase.CreateFolder("Assets/Scenes", "Dev");
}
if (!AssetDatabase.IsValidFolder("Assets/TextMesh Pro"))
{
Debug.LogWarning("TextMesh Pro essential resources are missing. Run Window → TextMeshPro → Import TMP Essential Resources.");
@@ -51,7 +51,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a7773ea9a6f44798aa98356903037d16, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueMessageRow
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueMessageRow
speakerText: {fileID: 5900251945930220314}
bodyText: {fileID: 1670956017877202442}
speakerLabel: {fileID: 5822252844234204748}
@@ -542,7 +542,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 88cb6495795a4e13ac7fb72343c132af, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueStreamPresenter
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueStreamPresenter
messageRowPrefab: {fileID: 5353601244371665078, guid: 90818ef7dc74247ceb348994755cea86, type: 3}
messageContainer: {fileID: 4838388606347767229}
scrollRect: {fileID: 7105587415705135446}
@@ -559,7 +559,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8d86cc99d5b545c4a3fad9e1482031a2, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Dialogue.DialogueStreamOptionsPresenter
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Dialogue.DialogueStreamOptionsPresenter
optionViewPrefab: {fileID: 2576261519635394347, guid: e605972137b0b4c1399ffb07beae9a9b, type: 3}
optionsContainer: {fileID: 6329947636030823459}
canvasGroup: {fileID: 5117926241503925785}
@@ -252,7 +252,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fd1354ade14b4b1d80da9acac4aa9e12, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.HUD.PortraitHudView
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.HUD.PortraitHudView
panelRoot: {fileID: 4989543578856257477}
--- !u!1 &4989543578856257477
GameObject:
@@ -61,7 +61,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 74efa3bf7a354892a401418d8f56fb2b, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.JournalPanelView
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.JournalPanelView
placeholderLabel: {fileID: 438358810008138731}
--- !u!1 &2044419659697384337
GameObject:
@@ -140,7 +140,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: db83a1a74e0e418881880ca808f68160, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.MenuTabBar
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.MenuTabBar
tabs:
- button: {fileID: 1673770274793931208}
panel: {fileID: 5076829831943889175}
@@ -245,7 +245,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ef17c93c7dec4af2ae7ce565c8984de3, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.CharacterPanelView
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.CharacterPanelView
nameLabel: {fileID: 8967222838737055253}
aliasLabel: {fileID: 4652515771799086270}
inventoryPlaceholder: {fileID: 1990427928476398531}
@@ -483,7 +483,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 118cc9783dba4b3cac1646d97ebd3998, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::NightclubArcadia.UI.Menu.PlayerMenuController
m_EditorClassIdentifier: NightclubArcadia.Game::NightclubArcadia.UI.Menu.PlayerMenuController
menuRoot: {fileID: 2249656863633318815}
menuInput: {fileID: 0}
controlLock: {fileID: 0}
@@ -783,6 +783,143 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &3123656435113957211
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2894368236897154238}
- component: {fileID: 8211184503074210791}
- component: {fileID: 8997850575536806412}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2894368236897154238
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3123656435113957211}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6001922808625371455}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8211184503074210791
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3123656435113957211}
m_CullTransparentMesh: 1
--- !u!114 &8997850575536806412
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3123656435113957211}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Skills
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 22
m_fontSizeBase: 22
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 1
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &3533277334474984255
GameObject:
m_ObjectHideFlags: 0
@@ -1388,7 +1525,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3528103284151106981}
- {fileID: 1481520485721663919}
m_Father: {fileID: 5714344749226447693}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@@ -1605,7 +1742,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1015917500768946775}
- {fileID: 2894368236897154238}
m_Father: {fileID: 5714344749226447693}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@@ -1873,7 +2010,7 @@ MonoBehaviour:
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1
--- !u!1 &7644334300092530069
--- !u!1 &7967390318583634950
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -1881,9 +2018,9 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1015917500768946775}
- component: {fileID: 4696967337599140493}
- component: {fileID: 3131234387202370334}
- component: {fileID: 1481520485721663919}
- component: {fileID: 2759775973399345411}
- component: {fileID: 6167893425112707945}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
@@ -1891,40 +2028,40 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1015917500768946775
--- !u!224 &1481520485721663919
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7644334300092530069}
m_GameObject: {fileID: 7967390318583634950}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6001922808625371455}
m_Father: {fileID: 453386429374550589}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4696967337599140493
--- !u!222 &2759775973399345411
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7644334300092530069}
m_GameObject: {fileID: 7967390318583634950}
m_CullTransparentMesh: 1
--- !u!114 &3131234387202370334
--- !u!114 &6167893425112707945
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7644334300092530069}
m_GameObject: {fileID: 7967390318583634950}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
@@ -1938,7 +2075,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Skills
m_text: Journal
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
@@ -2213,143 +2350,6 @@ MonoBehaviour:
rowPrefab: {fileID: 1141587833647839303, guid: e14f68d6a57ea4945bd93c44202db910, type: 3}
axisHeaderPrefab: {fileID: 5719341463139795832}
displayMaxRank: 6
--- !u!1 &8926189410052142562
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3528103284151106981}
- component: {fileID: 8980946710928878816}
- component: {fileID: 5867361342524513168}
m_Layer: 0
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3528103284151106981
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8926189410052142562}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 453386429374550589}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8980946710928878816
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8926189410052142562}
m_CullTransparentMesh: 1
--- !u!114 &5867361342524513168
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8926189410052142562}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Journal
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: 0
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 22
m_fontSizeBase: 22
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 1
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &9109014941581283762
GameObject:
m_ObjectHideFlags: 0
@@ -1,4 +1,5 @@
using System.Collections;
using System.Linq;
using NUnit.Framework;
using NightclubArcadia.Cinematics;
using Unity.Cinemachine;
@@ -73,6 +74,31 @@ namespace NightclubArcadia.PlayMode.Tests
"No DialogueRunner in any loaded scene");
}
/// <summary>
/// Regression: "Can't start dialogue: no Yarn Project has been configured."
///
/// Asserting the runner merely exists is not enough — it auto-starts on Start(),
/// and a runner with no project throws that at load with nothing else wrong.
/// The project is a serialized asset reference supplied by a prefab override, so
/// it breaks silently if the override is ever dropped.
/// </summary>
[Test]
public void TheDialogueRunner_HasItsYarnProject()
{
var runners = Object.FindObjectsByType<DialogueRunner>(
FindObjectsInactive.Include, FindObjectsSortMode.None);
Assert.AreEqual(1, runners.Length,
"Expected exactly one DialogueRunner across the loaded scenes, found " +
string.Join(", ", runners.Select(r => $"'{r.name}' in {r.gameObject.scene.name}")));
var runner = runners[0];
Assert.IsNotNull(runner.YarnProject,
$"'{runner.name}' in scene '{runner.gameObject.scene.name}' has no Yarn Project. " +
"It auto-starts, so this is the 'no Yarn Project has been configured' error.");
Assert.IsNotEmpty(runner.YarnProject.NodeNames, "The Yarn Project compiled no nodes");
}
[Test]
public void EveryNpc_ResolvedItsDialogueRunner()
{