29 lines
4.3 KiB
Plaintext
29 lines
4.3 KiB
Plaintext
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en"><head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<title>Game State — Unity-Roject-Test</title>
|
||
|
|
<style>
|
||
|
|
@import url('/fonts/barlow.css');
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body data-theme="default-roject">
|
||
|
|
<page--header></page--header>
|
||
|
|
|
||
|
|
<page--root data-theme="default-roject">
|
||
|
|
<full--width--block data--page--block="">
|
||
|
|
<full--width--area data--page--area="" contenteditable="true" spellcheck="false" autocorrect="off" autocapitalize="off" style="outline: none;"><h1>Game State</h1><div><marked-text>Assets/Scripts/Rokojori/GameState</marked-text> - the shared state layer everything else reads and writes through. See also <a href="../../outline/tech/index.page">outline/tech/index.page</a> for the design intent.</div></full--width--area>
|
||
|
|
</full--width--block>
|
||
|
|
<two--columns--block data--page--block="">
|
||
|
|
<two--columns--area data--page--area="" contenteditable="true" spellcheck="false" autocorrect="off" autocapitalize="off" style="outline: none;"><h2>The Split: Asset vs Runtime Value</h2><div>This is the one non-obvious thing about this system. <code>GameStateVariable</code> (and its subtypes <code>GameStateNumberVariable</code> / <code>GameStateBoolVariable</code>) are ScriptableObject <marked-text>assets</marked-text> - shared, on-disk config. They only hold an <code>initialValue</code> and a <code>key</code>. They do not hold the live, current value.</div><div><br></div><div>The actual mutable game state lives in two dictionaries on <code>GameStateManager</code> - <code>_numberValues</code> and <code>_boolValues</code>, both marked <code>[NonSerialized]</code> since they're pure runtime cache, rebuilt from the <code>variables</code> list in <code>Awake()</code>. Never read or write these dictionaries directly - always go through <code>GameStateManager.instance.GetValue(...)</code> / <code>SetValue(...)</code>, which are overloaded per variable type.</div></two--columns--area>
|
||
|
|
<two--columns--area data--page--area="" contenteditable="true" spellcheck="false" autocorrect="off" autocapitalize="off" style="outline: none;"><h2>key vs name</h2><div>ScriptableObjects already have a <code>name</code> (inherited from UnityEngine.Object - the asset's filename). <code>GameStateVariable.key</code> is a separate, deliberately-added field used as the stable identifier in JSON save data, so renaming an asset in the editor doesn't silently break old save files.</div><div><br></div><h2>SetValue Also Fires onChanged</h2><div><code>SetValue</code> updates the dictionary <marked-text>and</marked-text> dispatches the variable's own <code>onChanged</code> EventSlot in the same call - there's no separate notify step. Reading via <code>GetValue</code> never fires anything.</div></two--columns--area>
|
||
|
|
</two--columns--block>
|
||
|
|
<two--columns--block data--page--block="">
|
||
|
|
<two--columns--area data--page--area="" contenteditable="true" spellcheck="false" autocorrect="off" autocapitalize="off" style="outline: none;"><h2>Save / Load</h2><div><code>ToJson()</code> / <code>FromJson( json )</code> use Unity's <code>JsonUtility</code>, which can't serialize a <code>Dictionary</code> directly - hence the private <code>NumberEntry</code> / <code>BoolEntry</code> / <code>SaveData</code> classes that flatten the dictionaries into lists of key/value pairs first.</div><div><br></div><div><marked-text>Gotcha:</marked-text> if <code>FromJson</code> finds a saved key that no longer matches any variable in the current <code>variables</code> list, that entry is silently skipped - no error, no warning.</div></two--columns--area>
|
||
|
|
<two--columns--area data--page--area="" contenteditable="true" spellcheck="false" autocorrect="off" autocapitalize="off" style="outline: none;"><h2>Cheat Sheet</h2><div><code>GameStateManager.instance</code> - the singleton (via Unique<T>).</div><div><code>.GetValue( GameStateNumberVariable )</code> / <code>.GetValue( GameStateBoolVariable )</code></div><div><code>.SetValue( variable, value )</code> - updates + fires onChanged</div><div><code>.ToJson()</code> / <code>.FromJson( json )</code></div><div><br></div><div>To add a new variable type (e.g. string), mirror <code>GameStateNumberVariable</code>: a new <code>GameStateVariable</code> subclass, a new dictionary + Get/SetValue overload pair on GameStateManager, and a new Entry class for JSON.</div></two--columns--area>
|
||
|
|
</two--columns--block>
|
||
|
|
</page--root>
|
||
|
|
|
||
|
|
<page--footer></page--footer>
|
||
|
|
|
||
|
|
</body></html>
|