mirror of
https://github.com/HoonTB/Project-AS.git
synced 2025-12-26 11:51:21 +09:00
feat: Add variable system, scene transition, and improve character layout
- **Introduce Variable System**
- Added singleton class for variable management
- Implemented script commands `[var]` and `[add]` for variable control
- Supported variable substitution (`{variable}`) in dialogue and choices
- **Expand Script Features**
- Added `[scene]` command for scene transition (load scene and link next script)
- **Improve Character Presentation**
- Refactored character object hierarchy for better animation control
- Applied mask-based soft transition effect (Soft Wipe) for expression changes
This commit is contained in:
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
public class ScriptAction
|
public class ScriptAction
|
||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
public Dictionary<string, object> Params { get; set; } = new Dictionary<string, object>();
|
public Dictionary<string, object> Params { get; set; } = new();
|
||||||
public List<Dictionary<string, string>> Choices { get; set; }
|
public List<Dictionary<string, string>> Choices { get; set; }
|
||||||
|
|
||||||
public string GetParam(string key, string defaultValue = "")
|
public string GetParam(string key, string defaultValue = "")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using PrimeTween;
|
|||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
public class ScriptManager : MonoBehaviour
|
public class ScriptManager : MonoBehaviour
|
||||||
@@ -30,6 +31,8 @@ public class ScriptManager : MonoBehaviour
|
|||||||
private Tween dialogueTween;
|
private Tween dialogueTween;
|
||||||
private Script _currentScript;
|
private Script _currentScript;
|
||||||
|
|
||||||
|
public static string NextScriptPath = "";
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
speakerText.SetText(" ");
|
speakerText.SetText(" ");
|
||||||
@@ -37,7 +40,25 @@ public class ScriptManager : MonoBehaviour
|
|||||||
dialogueText.SetText(" ");
|
dialogueText.SetText(" ");
|
||||||
dialogueText.ForceMeshUpdate(true);
|
dialogueText.ForceMeshUpdate(true);
|
||||||
|
|
||||||
_currentScript = ScriptParser.Parse(scriptFile.text);
|
if (!string.IsNullOrEmpty(NextScriptPath))
|
||||||
|
{
|
||||||
|
TextAsset loadedScript = Resources.Load<TextAsset>($"NovelScripts/{NextScriptPath}");
|
||||||
|
if (loadedScript != null)
|
||||||
|
{
|
||||||
|
_currentScript = ScriptParser.Parse(loadedScript.text);
|
||||||
|
NextScriptPath = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"ScriptManager :: Cannot find script: {NextScriptPath}");
|
||||||
|
_currentScript = ScriptParser.Parse(scriptFile.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_currentScript = ScriptParser.Parse(scriptFile.text);
|
||||||
|
}
|
||||||
|
|
||||||
NextStep();
|
NextStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +165,7 @@ public class ScriptManager : MonoBehaviour
|
|||||||
if (speaker == "")
|
if (speaker == "")
|
||||||
speakerSprite.SetActive(false);
|
speakerSprite.SetActive(false);
|
||||||
|
|
||||||
|
speaker = VariableManager.Instance.ReplaceVariables(speaker);
|
||||||
speakerText.SetText(speaker);
|
speakerText.SetText(speaker);
|
||||||
speakerText.ForceMeshUpdate(true);
|
speakerText.ForceMeshUpdate(true);
|
||||||
NextStep();
|
NextStep();
|
||||||
@@ -152,6 +174,7 @@ public class ScriptManager : MonoBehaviour
|
|||||||
if (action.Type == "msg")
|
if (action.Type == "msg")
|
||||||
{
|
{
|
||||||
string dialogue = action.GetParam("content");
|
string dialogue = action.GetParam("content");
|
||||||
|
dialogue = VariableManager.Instance.ReplaceVariables(dialogue);
|
||||||
DisplayDialogue(dialogue);
|
DisplayDialogue(dialogue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,7 +197,7 @@ public class ScriptManager : MonoBehaviour
|
|||||||
|
|
||||||
foreach (var choice in action.Choices)
|
foreach (var choice in action.Choices)
|
||||||
{
|
{
|
||||||
string text = choice["content"];
|
string text = VariableManager.Instance.ReplaceVariables(choice["content"]);
|
||||||
string target = choice["goto"];
|
string target = choice["goto"];
|
||||||
GameObject buttonObj = Instantiate(choiceButtonPrefab, choiceButtonContainer);
|
GameObject buttonObj = Instantiate(choiceButtonPrefab, choiceButtonContainer);
|
||||||
buttonObj.GetComponentInChildren<TextMeshProUGUI>().text = text;
|
buttonObj.GetComponentInChildren<TextMeshProUGUI>().text = text;
|
||||||
@@ -196,6 +219,34 @@ public class ScriptManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (action.Type == "var")
|
||||||
|
{
|
||||||
|
foreach (var entry in action.Params)
|
||||||
|
{
|
||||||
|
VariableManager.Instance.SetVariable(entry.Key, entry.Value.ToString());
|
||||||
|
}
|
||||||
|
NextStep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (action.Type == "add")
|
||||||
|
{
|
||||||
|
foreach (var entry in action.Params)
|
||||||
|
{
|
||||||
|
VariableManager.Instance.AddVariable(entry.Key, entry.Value.ToString());
|
||||||
|
}
|
||||||
|
NextStep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (action.Type == "scene")
|
||||||
|
{
|
||||||
|
string sceneName = action.GetParam("file");
|
||||||
|
string nextScript = action.GetParam("script");
|
||||||
|
Debug.Log($"ScriptManager :: Load Scene: {sceneName}, Next Script: {nextScript}");
|
||||||
|
|
||||||
|
NextScriptPath = nextScript;
|
||||||
|
SceneManager.LoadScene(sceneName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DebugReload()
|
public void DebugReload()
|
||||||
@@ -210,11 +261,11 @@ public class ScriptManager : MonoBehaviour
|
|||||||
|
|
||||||
private bool IsPointerOverInteractiveUI()
|
private bool IsPointerOverInteractiveUI()
|
||||||
{
|
{
|
||||||
PointerEventData eventData = new(EventSystem.current)
|
PointerEventData eventData = new(EventSystem.current)
|
||||||
{
|
{
|
||||||
position = Input.mousePosition
|
position = Input.mousePosition
|
||||||
};
|
};
|
||||||
List<RaycastResult> results = new();
|
List<RaycastResult> results = new();
|
||||||
EventSystem.current.RaycastAll(eventData, results);
|
EventSystem.current.RaycastAll(eventData, results);
|
||||||
|
|
||||||
foreach (RaycastResult result in results)
|
foreach (RaycastResult result in results)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class ScriptParser
|
public class ScriptParser
|
||||||
{
|
{
|
||||||
@@ -32,7 +31,6 @@ public class ScriptParser
|
|||||||
{
|
{
|
||||||
string tagName = tagMatch.Groups[1].Value;
|
string tagName = tagMatch.Groups[1].Value;
|
||||||
string attrString = tagMatch.Groups[2].Value;
|
string attrString = tagMatch.Groups[2].Value;
|
||||||
Debug.Log($"ScriptParser :: Tag: {tagName} {attrString}");
|
|
||||||
|
|
||||||
var scriptAction = new ScriptAction { Type = tagName };
|
var scriptAction = new ScriptAction { Type = tagName };
|
||||||
|
|
||||||
|
|||||||
73
Assets/_MAIN/Scripts/Core/VariableManager.cs
Normal file
73
Assets/_MAIN/Scripts/Core/VariableManager.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class VariableManager
|
||||||
|
{
|
||||||
|
private static VariableManager _instance;
|
||||||
|
public static VariableManager Instance => _instance ??= new VariableManager();
|
||||||
|
|
||||||
|
private Dictionary<string, object> _variables = new();
|
||||||
|
|
||||||
|
public void SetVariable(string name, string value)
|
||||||
|
{
|
||||||
|
// Try to parse as int or float, otherwise string
|
||||||
|
if (int.TryParse(value, out int intVal))
|
||||||
|
_variables[name] = intVal;
|
||||||
|
else if (float.TryParse(value, out float floatVal))
|
||||||
|
_variables[name] = floatVal;
|
||||||
|
else
|
||||||
|
_variables[name] = value;
|
||||||
|
|
||||||
|
|
||||||
|
Debug.Log($"VariableManager :: Set {name} = {_variables[name]} ({_variables[name].GetType()})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetVariable(string name)
|
||||||
|
{
|
||||||
|
return _variables.ContainsKey(name) ? _variables[name] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddVariable(string name, string valueStr)
|
||||||
|
{
|
||||||
|
if (!_variables.ContainsKey(name))
|
||||||
|
{
|
||||||
|
SetVariable(name, valueStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
object current = _variables[name];
|
||||||
|
|
||||||
|
|
||||||
|
if (current is int currentInt && int.TryParse(valueStr, out int addInt))
|
||||||
|
{
|
||||||
|
_variables[name] = currentInt + addInt;
|
||||||
|
}
|
||||||
|
else if (current is float currentFloat && float.TryParse(valueStr, out float addFloat))
|
||||||
|
{
|
||||||
|
_variables[name] = currentFloat + addFloat;
|
||||||
|
}
|
||||||
|
else if (current is string currentStr)
|
||||||
|
{
|
||||||
|
_variables[name] = currentStr + valueStr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"VariableManager :: Cannot add {valueStr} to {name} (Type: {current.GetType()})");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Debug.Log($"VariableManager :: Add {name} += {valueStr} -> {_variables[name]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ReplaceVariables(string text)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(text)) return text;
|
||||||
|
|
||||||
|
foreach (var kvp in _variables)
|
||||||
|
{
|
||||||
|
text = text.Replace($"{{{kvp.Key}}}", kvp.Value.ToString());
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/_MAIN/Scripts/Core/VariableManager.cs.meta
Normal file
2
Assets/_MAIN/Scripts/Core/VariableManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 309802f724fb94846a7b453b40357e1d
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using PrimeTween;
|
using PrimeTween;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@@ -19,8 +18,6 @@ public class VisualNovelLayoutDirector : MonoBehaviour
|
|||||||
public float defaultDuration = 0.5f;
|
public float defaultDuration = 0.5f;
|
||||||
public float moveDistance = 800f;
|
public float moveDistance = 800f;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ========================= [1. 등장 (Entry)] =========================
|
// ========================= [1. 등장 (Entry)] =========================
|
||||||
public void AddCharacter(string fileName, EntranceType type)
|
public void AddCharacter(string fileName, EntranceType type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ EditorBuildSettings:
|
|||||||
- enabled: 1
|
- enabled: 1
|
||||||
path: Assets/_MAIN/Scenes/VisualNovel.unity
|
path: Assets/_MAIN/Scenes/VisualNovel.unity
|
||||||
guid: 199e3baed267a4c4fb4665bdaf82e49c
|
guid: 199e3baed267a4c4fb4665bdaf82e49c
|
||||||
|
- enabled: 1
|
||||||
|
path: Assets/_MAIN/Scenes/Scene01.unity
|
||||||
|
guid: ab7661506d731e6428485450843b0c2c
|
||||||
m_configObjects:
|
m_configObjects:
|
||||||
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
|
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
|
||||||
m_UseUCBPForAssetBundles: 0
|
m_UseUCBPForAssetBundles: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user