diff --git a/CLAUDE.md b/CLAUDE.md
index a30caa2..464bc85 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -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.
diff --git a/NightclubArcadia/Assets/Editor/ScenePaths.cs b/NightclubArcadia/Assets/Editor/ScenePaths.cs
index 0d2975c..5fc7cc1 100644
--- a/NightclubArcadia/Assets/Editor/ScenePaths.cs
+++ b/NightclubArcadia/Assets/Editor/ScenePaths.cs
@@ -15,7 +15,30 @@ namespace NightclubArcadia.EditorTools
/// Persistent systems: dialogue, skills, UI, camera rig, player.
public const string Systems = "Assets/Scenes/Systems/Systems.unity";
- /// The scene the setup menus wire into. SC-101's conference hall.
+ ///
+ /// 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.
+ ///
public const string WorkingLevel = "Assets/Scenes/Levels/SC101_ConferenceHall.unity";
+
+ ///
+ /// 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.
+ ///
+ public const string Sandbox = "Assets/Scenes/Dev/YarnSandbox.unity";
+
+ ///
+ /// Guard for any menu that overwrites a whole scene. Generated scenes belong in
+ /// Scenes/Dev and nowhere else.
+ ///
+ public static bool IsDisposable(string scenePath) =>
+ !string.IsNullOrEmpty(scenePath) &&
+ scenePath.Replace('\\', '/').StartsWith("Assets/Scenes/Dev/", System.StringComparison.Ordinal);
}
}
diff --git a/NightclubArcadia/Assets/Editor/YarnDemoSetup.cs b/NightclubArcadia/Assets/Editor/YarnDemoSetup.cs
index 59c0caa..dc71b06 100644
--- a/NightclubArcadia/Assets/Editor/YarnDemoSetup.cs
+++ b/NightclubArcadia/Assets/Editor/YarnDemoSetup.cs
@@ -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.");
diff --git a/NightclubArcadia/Assets/Prefabs/UI/DialogueMessageRow.prefab b/NightclubArcadia/Assets/Prefabs/UI/DialogueMessageRow.prefab
index 7f26b4f..91d1bbf 100644
--- a/NightclubArcadia/Assets/Prefabs/UI/DialogueMessageRow.prefab
+++ b/NightclubArcadia/Assets/Prefabs/UI/DialogueMessageRow.prefab
@@ -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}
diff --git a/NightclubArcadia/Assets/Prefabs/UI/DialogueStreamCanvas.prefab b/NightclubArcadia/Assets/Prefabs/UI/DialogueStreamCanvas.prefab
index 68f19ce..0fc9d79 100644
--- a/NightclubArcadia/Assets/Prefabs/UI/DialogueStreamCanvas.prefab
+++ b/NightclubArcadia/Assets/Prefabs/UI/DialogueStreamCanvas.prefab
@@ -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}
diff --git a/NightclubArcadia/Assets/Prefabs/UI/HudCanvas.prefab b/NightclubArcadia/Assets/Prefabs/UI/HudCanvas.prefab
index 7d9c455..588f14f 100644
--- a/NightclubArcadia/Assets/Prefabs/UI/HudCanvas.prefab
+++ b/NightclubArcadia/Assets/Prefabs/UI/HudCanvas.prefab
@@ -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:
diff --git a/NightclubArcadia/Assets/Prefabs/UI/PlayerMenuCanvas.prefab b/NightclubArcadia/Assets/Prefabs/UI/PlayerMenuCanvas.prefab
index 15575fa..032788c 100644
--- a/NightclubArcadia/Assets/Prefabs/UI/PlayerMenuCanvas.prefab
+++ b/NightclubArcadia/Assets/Prefabs/UI/PlayerMenuCanvas.prefab
@@ -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
diff --git a/NightclubArcadia/Assets/Tests/PlayMode/BootstrapTests.cs b/NightclubArcadia/Assets/Tests/PlayMode/BootstrapTests.cs
index 653f788..ba05df9 100644
--- a/NightclubArcadia/Assets/Tests/PlayMode/BootstrapTests.cs
+++ b/NightclubArcadia/Assets/Tests/PlayMode/BootstrapTests.cs
@@ -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");
}
+ ///
+ /// 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.
+ ///
+ [Test]
+ public void TheDialogueRunner_HasItsYarnProject()
+ {
+ var runners = Object.FindObjectsByType(
+ 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()
{