StorySystem
This commit is contained in:
@@ -21,15 +21,19 @@ namespace Ichni.Story
|
||||
public class CharacterData : SerializedScriptableObject
|
||||
{
|
||||
[LabelText("Character ID")]
|
||||
[InfoBox("此 ID 需与 .yarn 文件中对应台词的 speaker 名完全一致。")]
|
||||
[Tooltip("此 ID 需与 .yarn 文件中对应台词的 speaker 名完全一致。")]
|
||||
public string characterId;
|
||||
|
||||
[LabelText("Display Name Key")]
|
||||
[InfoBox("Unity Localization String Table Key,用于多语言角色名显示。")]
|
||||
[Tooltip("Unity Localization String Table Key,用于多语言角色名显示。")]
|
||||
public string displayNameKey;
|
||||
|
||||
[LabelText("Portrait Style")]
|
||||
public PortraitStyle portraitStyle = PortraitStyle.Sprite;
|
||||
|
||||
[LabelText("Position Offset")]
|
||||
[Tooltip("立绘在舞台上的位置偏移(单位:映射百分比)")]
|
||||
public Vector2 positionOffset = new Vector2(0f, 0f);
|
||||
|
||||
// ── Sprite ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -46,7 +50,6 @@ namespace Ichni.Story
|
||||
[InfoBox("Live2D / Spine 立绘预制体,需挂载实现 IPortraitRenderer 接口的组件(阶段 3 制作)。")]
|
||||
public GameObject dynamicPortraitPrefab;
|
||||
|
||||
private bool IsDynamicPortrait =>
|
||||
portraitStyle == PortraitStyle.Live2D || portraitStyle == PortraitStyle.Spine;
|
||||
private bool IsDynamicPortrait => portraitStyle == PortraitStyle.Live2D || portraitStyle == PortraitStyle.Spine;
|
||||
}
|
||||
}
|
||||
|
||||
140
Assets/Scripts/NewStorySystem/Data/StoryVariables.cs
Normal file
140
Assets/Scripts/NewStorySystem/Data/StoryVariables.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Story
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局剧情变量的统一数据枢纽。
|
||||
/// 所有外部系统(包括 Yarn、UI、小游戏)读写剧情变量的唯一官方入口。
|
||||
/// 自动桥接至 GameSaveManager 的 StorySaveModule 中持久化。
|
||||
/// </summary>
|
||||
public static class StoryVariables
|
||||
{
|
||||
// 应对游戏尚未初始化(或者单独测试场景)的内存兜底
|
||||
private static readonly StoryVariablesSave _fallback = new StoryVariablesSave();
|
||||
|
||||
private static StoryVariablesSave Variables
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameSaveManager.instance != null && GameSaveManager.instance.StorySaveModule != null)
|
||||
return GameSaveManager.instance.StorySaveModule.variables;
|
||||
return _fallback;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 读取 ────────────────────────────────────────────────────────────────
|
||||
|
||||
public static float GetFloat(string key, float defaultValue = 0f)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (vars.floatVariables.TryGetValue(key, out float f)) return f;
|
||||
if (vars.boolVariables.TryGetValue(key, out bool b)) return b ? 1f : 0f;
|
||||
if (vars.stringVariables.TryGetValue(key, out string s) && float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out float p)) return p;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static int GetInt(string key, int defaultValue = 0)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (vars.floatVariables.TryGetValue(key, out float f)) return Mathf.RoundToInt(f);
|
||||
if (vars.boolVariables.TryGetValue(key, out bool b)) return b ? 1 : 0;
|
||||
if (vars.stringVariables.TryGetValue(key, out string s) && float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out float p)) return Mathf.RoundToInt(p);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static bool GetBool(string key, bool defaultValue = false)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (vars.boolVariables.TryGetValue(key, out bool b)) return b;
|
||||
if (vars.floatVariables.TryGetValue(key, out float f)) return f != 0f;
|
||||
if (vars.stringVariables.TryGetValue(key, out string s) && bool.TryParse(s, out bool p)) return p;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static string GetString(string key, string defaultValue = "")
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (vars.stringVariables.TryGetValue(key, out string s)) return s;
|
||||
if (vars.floatVariables.TryGetValue(key, out float f)) return f.ToString(CultureInfo.InvariantCulture);
|
||||
if (vars.boolVariables.TryGetValue(key, out bool b)) return b.ToString();
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static bool HasVariable(string key)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
return vars.floatVariables.ContainsKey(key) || vars.boolVariables.ContainsKey(key) || vars.stringVariables.ContainsKey(key);
|
||||
}
|
||||
|
||||
// ── 写入 ────────────────────────────────────────────────────────────────
|
||||
|
||||
public static void SetFloat(string key, float value)
|
||||
{
|
||||
RemoveStaleEntries(key, keepFloat: true, keepString: false, keepBool: false);
|
||||
Variables.floatVariables[key] = value;
|
||||
}
|
||||
|
||||
public static void SetInt(string key, int value)
|
||||
{
|
||||
// 在 Yarn/存档底层中数字统一存为 float,避免双字典冗余
|
||||
SetFloat(key, value);
|
||||
}
|
||||
|
||||
public static void SetBool(string key, bool value)
|
||||
{
|
||||
RemoveStaleEntries(key, keepFloat: false, keepString: false, keepBool: true);
|
||||
Variables.boolVariables[key] = value;
|
||||
}
|
||||
|
||||
public static void SetString(string key, string value)
|
||||
{
|
||||
RemoveStaleEntries(key, keepFloat: false, keepString: true, keepBool: false);
|
||||
Variables.stringVariables[key] = value;
|
||||
}
|
||||
|
||||
public static void ClearAll()
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
vars.floatVariables.Clear();
|
||||
vars.stringVariables.Clear();
|
||||
vars.boolVariables.Clear();
|
||||
}
|
||||
|
||||
private static void RemoveStaleEntries(string name, bool keepFloat, bool keepString, bool keepBool)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (!keepFloat) vars.floatVariables.Remove(name);
|
||||
if (!keepString) vars.stringVariables.Remove(name);
|
||||
if (!keepBool) vars.boolVariables.Remove(name);
|
||||
}
|
||||
|
||||
// ── 字典批量操作(内部供 Yarn Adapter 使用) ─────────────────────────────
|
||||
|
||||
internal static void SetAllVariables(Dictionary<string, float> floats, Dictionary<string, string> strings, Dictionary<string, bool> bools, bool clear = true)
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
if (clear)
|
||||
{
|
||||
vars.floatVariables.Clear();
|
||||
vars.stringVariables.Clear();
|
||||
vars.boolVariables.Clear();
|
||||
}
|
||||
|
||||
if (floats != null) foreach (var kv in floats) vars.floatVariables[kv.Key] = kv.Value;
|
||||
if (strings != null) foreach (var kv in strings) vars.stringVariables[kv.Key] = kv.Value;
|
||||
if (bools != null) foreach (var kv in bools) vars.boolVariables[kv.Key] = kv.Value;
|
||||
}
|
||||
|
||||
internal static (Dictionary<string, float> floats, Dictionary<string, string> strings, Dictionary<string, bool> bools) GetAllVariables()
|
||||
{
|
||||
StoryVariablesSave vars = Variables;
|
||||
return (
|
||||
new Dictionary<string, float>(vars.floatVariables),
|
||||
new Dictionary<string, string>(vars.stringVariables),
|
||||
new Dictionary<string, bool>(vars.boolVariables)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c69dde49931abdd40aeabc0dc35582f5
|
||||
Reference in New Issue
Block a user