Command Option 增强及示例

This commit is contained in:
2024-08-22 01:23:16 +08:00
parent f490b897fe
commit 8a5f0b5846
6 changed files with 153 additions and 39 deletions
@@ -2,19 +2,45 @@
---
<<character_init Art/Character/Express_1>>
我: 这是选项测试文件 #line:069537f
<<character_move_to_fix>>
<<fade_in 1>>
我: 点击不同按钮可以执行不同命令 #line:00147c3
<<fade_out 1>>
<<load_scene OptionTestScene>>
我: 加载测试场景 #line:0a67910
我: 提供两个按钮进行点击 #line:0cb2011
我: 代码部分在Asset->Scripts->Test->OptionTest #line:0344182
<<declare $visitedState1 = false>>
<<declare $visitedState2 = false>>
[command name=show_buttons /] #line:006eeaa
<<jump OptionButton>>
===
title: OptionButton
position: -42,237
---
[options /] // 如果选项需要跳转回来重复选择,需要加这行,不然会出问题
-> 按钮1 #line:0db0f08
<<if !$visitedState1>>
我: 按下了按钮1 #line:0d84460
<<set $visitedState1 to true>>
<<change_button_name Canvas 0 点击进入深度1>> // 这里可以添加其他功能,比如按钮打开
<<else>>
我: 已经按过按钮1了 #line:0f6f363
<<endif>>
<<jump OptionButton>>
-> 按钮2 #line:0556913
<<if !$visitedState2>>
我: 按下了按钮2 #line:0b552f4
<<set $visitedState2 to true>>
<<change_button_name Canvas 1 点击进入深度2>> // 这里可以添加其他功能,比如按钮打开
<<else>>
我: 已经按过按钮2了 #line:09081bc
<<endif>>
<<jump OptionButton>>
-> 点击进入深度1 #line:0b33abc // 在代码里判断选项是否可用
我: 已进入深度1 #line:00ffa7f
-> 点击进入深度2 #line:02d1695
我: 已进入深度2 #line:072a4b9
我: 测试完成 #line:011c95f
===
@@ -11,12 +11,19 @@ namespace AibisDream
public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished)
{
// 判断选项选项行
if (dialogueLine.Text.IsOptionAttrLine())
{
isInCommand = true;
base.RunLine(dialogueLine, onDialogueLineFinished);
return;
}
// 判断是否进入Command状态
isInCommand = dialogueLine.Text.TryGetCommandAttr(out var name);
isInCommand = dialogueLine.Text.TryGetCommandAttr(out var curCommandName);
if (isInCommand)
{
// 保存指令
commandName = name;
commandName = curCommandName;
// 进入下一步
onDialogueLineFinished.Invoke();
}
@@ -10,6 +10,8 @@ namespace AibisDream
{
private DialogueRunner dialogueRunner;
private VariableStorageBehaviour _variableStorage;
private Dictionary<string, Action<YarnOption[]>> commandMap = new();
public bool quickRunMode;
@@ -17,8 +19,33 @@ namespace AibisDream
private void Start()
{
dialogueRunner = GetComponentInChildren<DialogueRunner>();
_variableStorage = GetComponentInChildren<InMemoryVariableStorage>();
}
#region
public bool TryGetVariable<T>(string variableName, out T result)
{
return _variableStorage.TryGetValue(variableName, out result);
}
public void SetVariable(string variableName, string value)
{
_variableStorage.SetValue(variableName, value);
}
public void SetVariable(string variableName, bool value)
{
_variableStorage.SetValue(variableName, value);
}
public void SetVariable(string variableName, float value)
{
_variableStorage.SetValue(variableName, value);
}
#endregion
/// <summary>
/// 开启对话
/// </summary>
@@ -158,7 +185,6 @@ namespace AibisDream
[YarnCommand("fade_in")]
public static IEnumerator FadeIn(float duration = 1)
{
Debug.Log("fade_in");
return MainUIController.Instance.FadeInSync(duration);
}
+30 -23
View File
@@ -8,25 +8,26 @@ namespace AibisDream
{
public class YarnOption
{
private DialogueOption dialogueOption;
private Action<int> onOptionSelected;
public YarnOption(DialogueOption dialogueOption, Action<int> onOptionSelected)
{
this.dialogueOption = dialogueOption;
this.onOptionSelected = onOptionSelected;
}
private int _idx;
private readonly DialogueOption _dialogueOption;
private Action<int> _onOptionSelected;
/// <summary>
/// 选项中的文字
/// </summary>
public string Text
public string Text => _dialogueOption.Line.TextWithoutCharacterName.Text;
public bool IsAvailable => _dialogueOption.IsAvailable;
public int Index => _idx;
public YarnOption(int idx, DialogueOption dialogueOption, Action<int> onOptionSelected)
{
get
{
return dialogueOption.Line.TextWithoutCharacterName.Text;
}
_dialogueOption = dialogueOption;
_onOptionSelected = onOptionSelected;
_idx = idx;
}
/// <summary>
@@ -34,15 +35,21 @@ namespace AibisDream
/// </summary>
public void SelectOption()
{
if (onOptionSelected == null)
if (!IsAvailable)
{
Debug.LogWarning($"选项 {Text} 不可用");
return;
}
if (_onOptionSelected == null)
{
Debug.LogWarning($"选项 {Text} 已经执行过了");
return;
}
else
{
onOptionSelected.Invoke(dialogueOption.DialogueOptionID);
onOptionSelected = null;
}
// 执行选项
_onOptionSelected.Invoke(_dialogueOption.DialogueOptionID);
_onOptionSelected = null;
}
/// <summary>
@@ -53,10 +60,10 @@ namespace AibisDream
/// <returns>包装选项</returns>
public static YarnOption[] GeneOptions(DialogueOption[] options, Action<int> onOptionSelected)
{
YarnOption[] yarnOptions = new YarnOption[options.Length];
for (int i = 0; i < options.Length; i++)
var yarnOptions = new YarnOption[options.Length];
for (var i = 0; i < options.Length; i++)
{
yarnOptions[i] = new YarnOption(options[i], onOptionSelected);
yarnOptions[i] = new YarnOption(i, options[i], onOptionSelected);
}
return yarnOptions;
+47 -7
View File
@@ -1,8 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using Yarn.Unity;
namespace AibisDream.Test
{
@@ -10,6 +12,8 @@ namespace AibisDream.Test
{
private GameObject panel;
private GameObject prefab;
private GameObject[] buttonGroup;
private YarnOption[] _options;
void Start()
{
@@ -29,18 +33,32 @@ namespace AibisDream.Test
/// <param name="options">触发时提供的选择项</param>
public void ShowButtons(YarnOption[] options)
{
foreach (YarnOption option in options)
{
var instance = Instantiate(prefab, panel.transform, true);
instance.GetComponentInChildren<TextMeshProUGUI>().text = option.Text;
instance.GetComponent<Button>().onClick.AddListener(() => {
// 将前两个选项生成清单
buttonGroup = InstantiateButtons(options);
_options = options;
}
private GameObject[] InstantiateButtons(YarnOption[] options)
{
// 这里默认是前两个选项生成按钮,你也可以利用Text或Index来判断哪些是需要生成按钮的选项
GameObject[] res = new GameObject[2];
for (int i = 0; i < 2; i++)
{
var option = options[i];
var instance = Instantiate(prefab, panel.transform, true);
var textMesh = instance.GetComponentInChildren<TextMeshProUGUI>();
textMesh.text = option.Text;
instance.GetComponent<Button>().onClick.AddListener(() => {
// 执行SelectOption(), 对话就会从对应的选项往下继续执行
option.SelectOption();
panel.SetActive(false);
});
res[i] = instance;
}
return res;
}
public void OnDestroy()
@@ -48,6 +66,28 @@ namespace AibisDream.Test
// 注意在合适的时机移除命令
DialogController.Instance.RemoveOptionCommand("show_buttons");
}
[YarnCommand("change_button_name")]
public void ChangeButtonName(float idx, string buttonName)
{
var realIdx = Mathf.RoundToInt(idx);
GameObject targetButton = buttonGroup[realIdx];
var textMesh = targetButton.GetComponentInChildren<TextMeshProUGUI>();
textMesh.text = buttonName;
var button = targetButton.GetComponentInChildren<Button>();
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() =>
{
var option = _options[realIdx + 2];
DialogController.Instance.TryGetVariable($"$visitedState{realIdx + 1}", out bool visitedState);
if (visitedState)
{
option.SelectOption();
}
});
}
}
}
+11 -3
View File
@@ -9,11 +9,14 @@ namespace AibisDream
{
private const string COMMAND_ATTR = "command";
private const string OptionAttr = "options";
private const string COMMAND_PROP = "name";
public static bool HasCommandAttr(this MarkupParseResult text)
{
return text.TryGetAttributeWithName(COMMAND_ATTR, out var attribute);
return text.TryGetAttributeWithName(COMMAND_ATTR, out var attribute1) ||
text.TryGetAttributeWithName(OptionAttr, out var attribute2);
}
public static bool TryGetCommandAttr(this MarkupParseResult text, out string commandName)
@@ -22,5 +25,10 @@ namespace AibisDream
commandName = res ? attribute.Properties[COMMAND_PROP].StringValue : null;
return res;
}
public static bool IsOptionAttrLine(this MarkupParseResult text)
{
return text.TryGetAttributeWithName(OptionAttr, out var outStr);
}
}
}
}