Command Option 增强及示例
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user