No edit summary
No edit summary
Line 1: Line 1:
{{DISPLAYTITLE:Main Menu}}
= Main menu =


The '''main menu''' is the first interactive screen in ''[[PC Simulator]]'' after the '''Menu''' scene loads. It is driven by the {{mono|MainMenu}} behaviour, which initializes [[localization]], restores certain settings, presents navigation via {{mono|[[MenuManager]]}}, and starts [[asynchronous]] scene loads with a dedicated '''Loading''' page.
The '''main menu''' is the first interactive screen in '''PC Simulator''' after the '''Menu''' scene loads. It is driven by the <code>MainMenu</code> behaviour, which initializes localization, restores settings, coordinates child pages through <code>MenuManager</code>, and starts asynchronous scene loads behind a '''Loading''' screen.
 
{| style="float:right; width:300px; margin:0 0 1em 1em; border-collapse:collapse; border:1px solid #a7a7a7; background:#f8f9fa; font-size:92%;"
|+ style="background:#eaecf0; border:1px solid #a7a7a7; padding:6px; font-weight:bold;" | Quick facts
|-
| style="border:1px solid #a7a7a7; padding:6px; vertical-align:top; width:38%;" | '''Unity scene'''
| style="border:1px solid #a7a7a7; padding:6px;" | <code>Menu</code> (project: <code>Assets/Scenes/Menu.unity</code>)
|-
| style="border:1px solid #a7a7a7; padding:6px; vertical-align:top;" | '''Core scripts'''
| style="border:1px solid #a7a7a7; padding:6px;" | <code>MainMenu.cs</code>, <code>MenuManager.cs</code>, <code>FileMenu.cs</code>
|-
| style="border:1px solid #a7a7a7; padding:6px; vertical-align:top;" | '''Singleton'''
| style="border:1px solid #a7a7a7; padding:6px;" | <code>MainMenu.Instance</code>
|-
| style="border:1px solid #a7a7a7; padding:6px; vertical-align:top;" | '''Save loads'''
| style="border:1px solid #a7a7a7; padding:6px;" | <code>SaveManager.Loader</code> + scene <code>startRoomSceneIndex + GameData.room</code>
|-
| style="border:1px solid #a7a7a7; padding:6px; vertical-align:top;" | '''Examples'''
| style="border:1px solid #a7a7a7; padding:6px;" | <code>StreamingAssets/Examples/*.pc</code>
|}


== Overview ==
== Overview ==


The main menu acts as the hub for:
The main menu is the hub for:


* Starting or resuming a game from '''save files''' ({{mono|.pc}}) in the user save folder
* Opening and starting games from user '''save files''' (<code>.pc</code>) in the save folder
* Launching the '''[[Tutorial]]''' scene (and recording that the current tutorial version has been offered)
* Launching the '''Tutorial''' scene and recording that the current tutorial revision was shown
* Loading '''example''' presets from '''StreamingAssets/Examples''' (e.g. named saves such as {{mono|Classic.pc}}, versioned examples, or {{mono|Hidden Room.pc}} when triggered from in-game secrets)
* Loading '''example''' presets from streaming assets (e.g. <code>Classic.pc</code>, versioned examples, <code>Hidden Room.pc</code> when triggered from in-game)
* Opening sub-pages for options, language, credits, file management, etc. (each implemented as a child page under {{mono|MenuManager}})
* Navigating sub-pages (options, language, about, file tools, etc.) via a stacked UI managed by <code>MenuManager</code>
* '''Exiting''' the application on supported platforms
* Quitting the application where supported


The on-screen title alternates between {{mono|PC Simulator}} and {{mono|PC Simulator_}} with a blinking underscore, with {{mono|PC}} highlighted in orange (Rich Text on Unity UI).
The title line alternates every 0.5 seconds between <code>PC Simulator</code> and <code>PC Simulator_</code>, with <code>PC</code> in orange using Unity UI Rich Text.


== Localization ==
== Localization ==


On {{mono|Awake}}, the menu:
On <code>Awake</code>, <code>MainMenu</code>:


# Calls {{mono|Localization.CreateContent()}}
# Calls <code>Localization.CreateContent()</code>
# Sets the active language from {{mono|PlayerPrefs}} key {{mono|"Language"}}, or falls back to a code derived from {{mono|Application.systemLanguage}} (e.g. {{mono|EN}}, {{mono|DE}}, {{mono|ZH-CN}}, {{mono|JA}}, and many others)
# Sets language from <code>PlayerPrefs</code> key <code>"Language"</code>, or from <code>Application.systemLanguage</code> mapped to codes such as <code>EN</code>, <code>DE</code>, <code>ZH-CN</code>, <code>JA</code>, etc.
# Subscribes to {{mono|Localization.LanguageChanged}} to persist the chosen language back to {{mono|PlayerPrefs}}
# Subscribes to <code>Localization.LanguageChanged</code> to write the active language back to <code>PlayerPrefs</code>


== Settings restored at menu start ==
== Settings restored at menu start ==


In {{mono|Start}}, the menu restores:
<code>Start</code> restores:


* '''FPS''' settings via {{mono|FpsSetting.RestoreSetting()}}
* '''FPS''' — <code>FpsSetting.RestoreSetting()</code>
* '''Resolution''' via {{mono|ResolutionSetting.RestoreSetting()}}
* '''Resolution''' — <code>ResolutionSetting.RestoreSetting()</code>
* '''Master volume''' on the audio listener from {{mono|PlayerPrefs}} (key {{mono|"Volume"}}, default {{mono|1f}})
* '''Volume''' — <code>AudioListener.volume</code> from <code>PlayerPrefs "Volume"</code> (default <code>1f</code>)


== Tutorial prompt ==
== Tutorial prompt ==


If {{mono|PlayerPrefs.GetInt("TutorialVersion", -1)}} is strictly less than a serialized {{mono|tutorialVersion}} on the menu component, the '''guide to tutorial''' object is shown; otherwise it is hidden. Entering the tutorial via {{mono|Tutorial()}} sets {{mono|TutorialVersion}} to the current version and loads the '''Tutorial''' scene by name.
If <code>PlayerPrefs.GetInt("TutorialVersion", -1)</code> is less than the inspector field <code>tutorialVersion</code>, the object <code>guideToTutorial</code> is enabled; otherwise it is hidden. Calling <code>Tutorial()</code> sets <code>TutorialVersion</code> to the current value and loads the scene named <code>"Tutorial"</code>.


== Navigation stack ==
== Navigation stack (<code>MenuManager</code>) ==


The {{mono|MenuManager}} component maintains a '''stack''' of active menu {{mono|GameObject}} pages:
<code>MenuManager</code> keeps a stack of active menu <code>GameObject</code> pages:


* {{mono|ShowMenu(string pageName)}} finds a child menu whose '''name''' matches {{mono|pageName}}, hides the current top if different, and pushes the new page
* <code>ShowMenu(string pageName)</code> — finds a child whose '''hierarchy name''' equals <code>pageName</code> (e.g. <code>Loading</code>, <code>FileInformation</code>), hides the previous top if different, pushes and shows the new page
* {{mono|Back()}} pops the stack (if more than one entry) and reactivates the previous page
* <code>Back()</code> — pops one level if the stack has more than one entry, reactivates the previous page
* {{mono|HideMenu(bool hide)}} toggles visibility of the top page without changing the stack (used when gameplay hides UI)
* <code>HideMenu(bool hide)</code> — toggles visibility of the top page without changing the stack
* Optional '''click''' sounds can play on navigation when enabled


Loading a scene always calls {{mono|ShowMenu("Loading")}} first so the player sees the loading overlay for the duration of the async operation.
Optional UI click sounds can play on <code>ShowMenu</code> and <code>Back</code> when enabled in the inspector.
 
Scene loads always call <code>ShowMenu("Loading")</code> first so the loading panel is visible during the async operation.


== Loading screen behaviour ==
== Loading screen behaviour ==


Scene loads use {{mono|SceneManager.LoadSceneAsync}} with {{mono|allowSceneActivation}} held at {{mono|false}} until progress reaches {{mono|0.9f}}. The displayed percentage uses:
Loads use <code>SceneManager.LoadSceneAsync</code> with <code>allowSceneActivation == false</code> until progress reaches <code>0.9f</code>.


: <code>Mathf.Clamp01(operation.progress / 0.9f) * 100f</code>
* Displayed percent: <code>Mathf.Clamp01(operation.progress / 0.9f) * 100f</code>
 
* When <code>progress >= 0.9f</code>, the text shows 100%, waits '''0.5''' seconds, then sets <code>allowSceneActivation = true</code>
When progress is at least {{mono|0.9f}}, the text shows '''100%''', waits '''0.5''' seconds, then allows activation. The label uses the localized string for {{mono|"Loading..."}} plus a bracketed percentage on a new line.
* Label text: localized <code>"Loading..."</code> plus a new line and <code>[percentage%]</code>


== Save files and examples ==
== Save files and examples ==


=== User saves ===
=== User saves (<code>FileMenu</code>) ===


The '''File menu''' ({{mono|FileMenu}}) scans the save directory for files matching the save extension, sorts them by '''last write time''' (newest first), and instantiates a slot per valid file. Each slot shows the save’s {{mono|roomName}} and a '''Hardcore''' indicator when {{mono|GameData.hardcore}} is true. Clicking the name button calls {{mono|MainMenu.Instance.LoadFile(loader)}}, which assigns {{mono|SaveManager.Loader}} and loads the scene index {{mono|startRoomSceneIndex + GameData.room}}.
* Scans the save directory for files matching the save extension
* Sorts by '''last write time''', newest first
* Each slot shows <code>GameData.roomName</code> and a '''Hardcore''' marker when <code>GameData.hardcore</code> is true
* Clicking the name runs <code>MainMenu.Instance.LoadFile(loader)</code>, which sets <code>SaveManager.Loader</code> and loads build index <code>startRoomSceneIndex + GameData.room</code>


=== Example presets ===
=== Example presets ===


{{mono|LoadExample(string name)}} reads {{mono|StreamingAssets/Examples/<name>.pc}}. On '''Android''' and '''WebGL''', the file is fetched with {{mono|UnityWebRequest}}; on other platforms, {{mono|File.ReadAllText}} is used. The string is passed through {{mono|DataLoader.LoadFromString}} and then the same {{mono|LoadFile}} path as a user save.
<code>LoadExample(string name)</code> reads <code>StreamingAssets/Examples/</code> + name + <code>.pc</code>. On Android and WebGL the file is read via <code>UnityWebRequest</code>; elsewhere via <code>File.ReadAllText</code>. The string is parsed with <code>DataLoader.LoadFromString</code>, then the same <code>LoadFile</code> path as a normal save.
 
=== Scene index convention ===
 
<code>LoadScene(int sceneBuildIndex)</code> loads <code>startRoomSceneIndex + sceneBuildIndex</code>. Saves store a small integer <code>room</code>; the inspector base index aligns that id with the correct Unity scene in build order.
 
=== Exit ===
 
<code>Exit()</code> calls <code>Application.Quit()</code> (no visible effect in the Unity Editor).
 
== Implementation reference ==
 
{| style="border-collapse:collapse; width:100%; border:1px solid #a7a7a7;"
|+ style="caption-side:top; text-align:left; font-weight:bold; padding:4px 0;" | Components
|- style="background:#eaecf0;"
! style="border:1px solid #a7a7a7; padding:8px; text-align:left; width:22%;" | Script
! style="border:1px solid #a7a7a7; padding:8px; text-align:left;" | Role
|-
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | <code>MainMenu</code>
| style="border:1px solid #a7a7a7; padding:8px;" | Singleton; localization; tutorial gating; title blink (<code>InvokeRepeating</code> every 0.5 s); example and scene loading; quit
|-
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | <code>MenuManager</code>
| style="border:1px solid #a7a7a7; padding:8px;" | Stack of menu pages; show, back, hide; optional click sound
|-
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | <code>FileMenu</code>
| style="border:1px solid #a7a7a7; padding:8px;" | Lists saves, rename/metadata UI, delete, import external <code>.pc</code>
|}
 
== In-depth: source code ==
 
=== <code>MainMenu.cs</code> — lifecycle ===
 
==== <code>Awake</code> ====
 
* Sets <code>MainMenu.Instance</code> so other scripts (e.g. <code>FileMenu</code>, <code>HiddenRoom</code>) can invoke <code>LoadFile</code> / <code>LoadExample</code> without serialized references.
* Runs localization setup and applies stored or system-default language.
* Persists language changes through <code>Localization.LanguageChanged</code>.
 
==== <code>Start</code> ====
 
* Restores FPS and resolution from saved settings.
* Shows or hides the tutorial guide based on <code>TutorialVersion</code> vs <code>tutorialVersion</code>.
* Applies master volume to <code>AudioListener</code>.
* Starts the repeating title animation.
 
==== <code>Blinking</code> ====
 
Toggles between two Rich Text strings on the title <code>Text</code> component for a blinking underscore effect.
 
==== <code>LoadExample(string name)</code> ====


== Starting gameplay scenes ==
Resolves <code>StreamingAssets/Examples/{name}.pc</code>, reads file bytes as text (platform-specific), then <code>DataLoader.LoadFromString</code> and <code>LoadFile</code>. On Android/WebGL the implementation uses <code>UnityWebRequest</code> and waits synchronously for completion.


* '''Indexed rooms:''' {{mono|LoadScene(int sceneBuildIndex)}} loads build index {{mono|startRoomSceneIndex + sceneBuildIndex}}, where {{mono|sceneBuildIndex}} comes from the save’s {{mono|room}} field.
==== <code>LoadFile(DataLoader loader)</code> ====
* '''Named scenes:''' {{mono|LoadScene(string sceneName)}} loads by name (used for the tutorial).


== Exit ==
Assigns <code>SaveManager.Loader = loader</code> and loads <code>startRoomSceneIndex + loader.GameData.room</code>.


{{mono|Exit()}} calls {{mono|Application.Quit()}}. On some platforms (e.g. editor or certain mobile builds), this may have no visible effect.
==== <code>Tutorial()</code> ====


== Implementation notes ==
Writes <code>PlayerPrefs "TutorialVersion"</code> and loads the <code>"Tutorial"</code> scene by name via <code>LoadScene(string)</code>.


{| class="wikitable"
==== <code>LoadAsync</code> coroutine ====
! Unity component || Role
 
# Shows the <code>Loading</code> menu page by name.
# Holds <code>allowSceneActivation</code> false while updating <code>loadingText</code> from async <code>progress</code>.
# After <code>0.9f</code> progress, shows 100%, waits 0.5 s, then allows activation.
 
=== <code>MenuManager.cs</code> ===
 
==== <code>Start</code> ====
 
Initializes the stack: whichever entry in the <code>menus</code> array is already active is pushed as the initial page.
 
==== <code>ShowMenu(string pageName)</code> ====
 
Linear search for <code>menu.name == pageName</code>. If the stack top is a different object, deactivate it, push the new page, activate it. Same reference as current top results in no duplicate push.
 
==== <code>Back</code> ====
 
If <code>menuStack.Count <= 1</code>, return. Otherwise pop, deactivate popped page, activate new top.
 
==== <code>HideMenu(bool hide)</code> ====
 
Sets <code>SetActive(!hide)</code> on the stack top without popping.
 
=== <code>FileMenu.cs</code> ===
 
==== <code>Start</code> ====
 
Enumerates save files, maps path → last write time, sorts descending, calls <code>AddSlot</code> for each. Shows <code>empty</code> when the list is empty.
 
==== <code>AddSlot(string path)</code> ====
 
Wrapped in try/catch; failures are skipped. Instantiates a row, binds <code>roomName</code> and hardcore flag, wires '''Edit''' to file information and '''Name''' to <code>MainMenu.Instance.LoadFile</code>.
 
==== <code>RefreshLoadButton</code> / <code>DeleteLoadButton</code> ====
 
Refresh updates labels after metadata changes. Delete removes the file, destroys the row, updates empty state.
 
==== <code>Import</code> ====
 
Uses native file picker filtered to <code>.pc</code>. Verifies read permission, validates via <code>DataLoader.LoadFromPath</code>, copies into the save folder with <code>SaveUtility.GetNewPath</code>, then clears and rebuilds the slot list from disk.
 
=== Data flow summary ===
 
{| style="border-collapse:collapse; width:100%; border:1px solid #a7a7a7;"
|- style="background:#eaecf0;"
! style="border:1px solid #a7a7a7; padding:8px; text-align:left; width:28%;" | Action
! style="border:1px solid #a7a7a7; padding:8px; text-align:left;" | Code path
|-
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | Player starts a save from the list
| style="border:1px solid #a7a7a7; padding:8px;" | <code>MainMenu.LoadFile</code> → <code>SaveManager.Loader</code> → async load <code>startRoomSceneIndex + room</code>
|-
|-
| {{mono|MainMenu}} || Singleton {{mono|Instance}}; localization; tutorial gating; scene and example loading; title blink coroutine ({{mono|InvokeRepeating}} every 0.5 s)
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | Example or secret loads a preset
| style="border:1px solid #a7a7a7; padding:8px;" | <code>LoadExample</code> reads <code>StreamingAssets/Examples/&lt;name&gt;.pc</code> → <code>LoadFile</code>
|-
|-
| {{mono|MenuManager}} || Stack of menu pages; show/back/hide; optional UI click sound
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | Any scene load from menu
| style="border:1px solid #a7a7a7; padding:8px;" | <code>MenuManager.ShowMenu("Loading")</code> then <code>LoadAsync</code>
|-
|-
| {{mono|FileMenu}} || Lists saves, import, file info sub-page
| style="border:1px solid #a7a7a7; padding:8px; vertical-align:top;" | Player confirms tutorial
| style="border:1px solid #a7a7a7; padding:8px;" | <code>Tutorial()</code> updates <code>TutorialVersion</code> → load <code>"Tutorial"</code>
|}
|}


== See also ==
== See also ==


* [[Tutorial]]
* Tutorial scene and <code>Tutorial.cs</code> in-game steps
* [[Save file format]] <!-- optional redlink if you document GameData elsewhere -->
* Pause menu and in-game <code>MenuManager</code> usage
* [[Pause menu]]
* Save format: <code>DataLoader</code>, <code>GameData</code>, <code>SaveUtility</code>
* [[Achievements]] <!-- e.g. hidden room loads example save -->


[[Category:PC Simulator]]
<!-- Optional: add wiki links when your wiki has pages, e.g. [[Tutorial]] -->
[[Category:User interface]]

Revision as of 18:11, 22 March 2026

Main menu

The main menu is the first interactive screen in PC Simulator after the Menu scene loads. It is driven by the MainMenu behaviour, which initializes localization, restores settings, coordinates child pages through MenuManager, and starts asynchronous scene loads behind a Loading screen.

Quick facts
Unity scene Menu (project: Assets/Scenes/Menu.unity)
Core scripts MainMenu.cs, MenuManager.cs, FileMenu.cs
Singleton MainMenu.Instance
Save loads SaveManager.Loader + scene startRoomSceneIndex + GameData.room
Examples StreamingAssets/Examples/*.pc

Overview

The main menu is the hub for:

  • Opening and starting games from user save files (.pc) in the save folder
  • Launching the Tutorial scene and recording that the current tutorial revision was shown
  • Loading example presets from streaming assets (e.g. Classic.pc, versioned examples, Hidden Room.pc when triggered from in-game)
  • Navigating sub-pages (options, language, about, file tools, etc.) via a stacked UI managed by MenuManager
  • Quitting the application where supported

The title line alternates every 0.5 seconds between PC Simulator and PC Simulator_, with PC in orange using Unity UI Rich Text.

Localization

On Awake, MainMenu:

  1. Calls Localization.CreateContent()
  2. Sets language from PlayerPrefs key "Language", or from Application.systemLanguage mapped to codes such as EN, DE, ZH-CN, JA, etc.
  3. Subscribes to Localization.LanguageChanged to write the active language back to PlayerPrefs

Settings restored at menu start

Start restores:

  • FPSFpsSetting.RestoreSetting()
  • ResolutionResolutionSetting.RestoreSetting()
  • VolumeAudioListener.volume from PlayerPrefs "Volume" (default 1f)

Tutorial prompt

If PlayerPrefs.GetInt("TutorialVersion", -1) is less than the inspector field tutorialVersion, the object guideToTutorial is enabled; otherwise it is hidden. Calling Tutorial() sets TutorialVersion to the current value and loads the scene named "Tutorial".

Navigation stack (MenuManager)

MenuManager keeps a stack of active menu GameObject pages:

  • ShowMenu(string pageName) — finds a child whose hierarchy name equals pageName (e.g. Loading, FileInformation), hides the previous top if different, pushes and shows the new page
  • Back() — pops one level if the stack has more than one entry, reactivates the previous page
  • HideMenu(bool hide) — toggles visibility of the top page without changing the stack

Optional UI click sounds can play on ShowMenu and Back when enabled in the inspector.

Scene loads always call ShowMenu("Loading") first so the loading panel is visible during the async operation.

Loading screen behaviour

Loads use SceneManager.LoadSceneAsync with allowSceneActivation == false until progress reaches 0.9f.

  • Displayed percent: Mathf.Clamp01(operation.progress / 0.9f) * 100f
  • When progress >= 0.9f, the text shows 100%, waits 0.5 seconds, then sets allowSceneActivation = true
  • Label text: localized "Loading..." plus a new line and [percentage%]

Save files and examples

User saves (FileMenu)

  • Scans the save directory for files matching the save extension
  • Sorts by last write time, newest first
  • Each slot shows GameData.roomName and a Hardcore marker when GameData.hardcore is true
  • Clicking the name runs MainMenu.Instance.LoadFile(loader), which sets SaveManager.Loader and loads build index startRoomSceneIndex + GameData.room

Example presets

LoadExample(string name) reads StreamingAssets/Examples/ + name + .pc. On Android and WebGL the file is read via UnityWebRequest; elsewhere via File.ReadAllText. The string is parsed with DataLoader.LoadFromString, then the same LoadFile path as a normal save.

Scene index convention

LoadScene(int sceneBuildIndex) loads startRoomSceneIndex + sceneBuildIndex. Saves store a small integer room; the inspector base index aligns that id with the correct Unity scene in build order.

Exit

Exit() calls Application.Quit() (no visible effect in the Unity Editor).

Implementation reference

Components
Script Role
MainMenu Singleton; localization; tutorial gating; title blink (InvokeRepeating every 0.5 s); example and scene loading; quit
MenuManager Stack of menu pages; show, back, hide; optional click sound
FileMenu Lists saves, rename/metadata UI, delete, import external .pc

In-depth: source code

MainMenu.cs — lifecycle

Awake

  • Sets MainMenu.Instance so other scripts (e.g. FileMenu, HiddenRoom) can invoke LoadFile / LoadExample without serialized references.
  • Runs localization setup and applies stored or system-default language.
  • Persists language changes through Localization.LanguageChanged.

Start

  • Restores FPS and resolution from saved settings.
  • Shows or hides the tutorial guide based on TutorialVersion vs tutorialVersion.
  • Applies master volume to AudioListener.
  • Starts the repeating title animation.

Blinking

Toggles between two Rich Text strings on the title Text component for a blinking underscore effect.

LoadExample(string name)

Resolves StreamingAssets/Examples/{name}.pc, reads file bytes as text (platform-specific), then DataLoader.LoadFromString and LoadFile. On Android/WebGL the implementation uses UnityWebRequest and waits synchronously for completion.

LoadFile(DataLoader loader)

Assigns SaveManager.Loader = loader and loads startRoomSceneIndex + loader.GameData.room.

Tutorial()

Writes PlayerPrefs "TutorialVersion" and loads the "Tutorial" scene by name via LoadScene(string).

LoadAsync coroutine

  1. Shows the Loading menu page by name.
  2. Holds allowSceneActivation false while updating loadingText from async progress.
  3. After 0.9f progress, shows 100%, waits 0.5 s, then allows activation.

MenuManager.cs

Start

Initializes the stack: whichever entry in the menus array is already active is pushed as the initial page.

ShowMenu(string pageName)

Linear search for menu.name == pageName. If the stack top is a different object, deactivate it, push the new page, activate it. Same reference as current top results in no duplicate push.

Back

If menuStack.Count <= 1, return. Otherwise pop, deactivate popped page, activate new top.

HideMenu(bool hide)

Sets SetActive(!hide) on the stack top without popping.

FileMenu.cs

Start

Enumerates save files, maps path → last write time, sorts descending, calls AddSlot for each. Shows empty when the list is empty.

AddSlot(string path)

Wrapped in try/catch; failures are skipped. Instantiates a row, binds roomName and hardcore flag, wires Edit to file information and Name to MainMenu.Instance.LoadFile.

RefreshLoadButton / DeleteLoadButton

Refresh updates labels after metadata changes. Delete removes the file, destroys the row, updates empty state.

Import

Uses native file picker filtered to .pc. Verifies read permission, validates via DataLoader.LoadFromPath, copies into the save folder with SaveUtility.GetNewPath, then clears and rebuilds the slot list from disk.

Data flow summary

Action Code path
Player starts a save from the list MainMenu.LoadFileSaveManager.Loader → async load startRoomSceneIndex + room
Example or secret loads a preset LoadExample reads StreamingAssets/Examples/<name>.pcLoadFile
Any scene load from menu MenuManager.ShowMenu("Loading") then LoadAsync
Player confirms tutorial Tutorial() updates TutorialVersion → load "Tutorial"

See also

  • Tutorial scene and Tutorial.cs in-game steps
  • Pause menu and in-game MenuManager usage
  • Save format: DataLoader, GameData, SaveUtility