对话系统第一次修改
This commit is contained in:
@@ -19,9 +19,6 @@ namespace AibisDream
|
||||
|
||||
# endregion
|
||||
|
||||
public static UnityAction OnDialogueStart;
|
||||
public static UnityAction OnDialogueComplete;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_dialogueRunner = GetComponentInChildren<DialogueRunner>();
|
||||
@@ -29,16 +26,16 @@ namespace AibisDream
|
||||
|
||||
_dialogueRunner.onDialogueStart.AddListener(() =>
|
||||
{
|
||||
EnumEventSystem.Global.Send(InteractionEventEnum.End);
|
||||
OnDialogueStart?.Invoke();
|
||||
EnumEventSystem.Global.Send(InteractionEventEnum.DialogEnd);
|
||||
});
|
||||
_dialogueRunner.onDialogueComplete.AddListener(() =>
|
||||
{
|
||||
EnumEventSystem.Global.Send(InteractionEventEnum.Start);
|
||||
OnDialogueComplete?.Invoke();
|
||||
EnumEventSystem.Global.Send(InteractionEventEnum.DialogStart);
|
||||
});
|
||||
}
|
||||
|
||||
#region Yarn控制
|
||||
|
||||
/// <summary>
|
||||
/// 开启对话
|
||||
/// </summary>
|
||||
@@ -49,12 +46,7 @@ namespace AibisDream
|
||||
_lineProvider.InitStringTable(yarnProject.name);
|
||||
_dialogueRunner.StartDialogue("Start");
|
||||
}
|
||||
|
||||
public string GetCurLocalizedTableName()
|
||||
{
|
||||
return _lineProvider.GetStringTableName();
|
||||
}
|
||||
|
||||
|
||||
public void StopDialog()
|
||||
{
|
||||
_dialogueRunner.Stop();
|
||||
@@ -84,7 +76,7 @@ namespace AibisDream
|
||||
_dialogueRunner.StartDialogue(nodeName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool CheckIfNodeExistInCurrentYarnProject(string nodeName)
|
||||
{
|
||||
YarnProject currentProject = _dialogueRunner.yarnProject;
|
||||
@@ -100,6 +92,8 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 跳到下一句
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class LineAdvanceInput : MonoBehaviour
|
||||
{
|
||||
#region 状态
|
||||
|
||||
private bool _inGame;
|
||||
private bool _isDialog;
|
||||
private LineSyncToken _curSyncToken;
|
||||
|
||||
#endregion
|
||||
|
||||
[SerializeField] private KeyCode advanceKey;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
RegisterEvents();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UnRegisterEvents();
|
||||
}
|
||||
|
||||
public void RunLine(LineSyncToken lineSyncEvent)
|
||||
{
|
||||
_curSyncToken = lineSyncEvent;
|
||||
}
|
||||
|
||||
private bool IsInputAvailable()
|
||||
{
|
||||
return _inGame && _isDialog && _curSyncToken != null && _curSyncToken.state != LineSyncState.Advanced;
|
||||
}
|
||||
|
||||
private void OnAdvanceInput()
|
||||
{
|
||||
if (!IsInputAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_curSyncToken.state)
|
||||
{
|
||||
case LineSyncState.PlayText:
|
||||
_curSyncToken.TrySkip();
|
||||
break;
|
||||
case LineSyncState.WaitForAdvance:
|
||||
_curSyncToken.TryAdvance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
OnAdvanceInput();
|
||||
}
|
||||
}
|
||||
|
||||
#region 事件处理
|
||||
|
||||
private IUnRegister[] _unRegisters;
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
_unRegisters = new IUnRegister[6];
|
||||
|
||||
_unRegisters[0] = EnumEventSystem.Global.Register(GameLoopEnum.GameStart, () => _inGame = true);
|
||||
_unRegisters[1] = EnumEventSystem.Global.Register(GameLoopEnum.UnPauseGame, () => _inGame = true);
|
||||
|
||||
_unRegisters[2] = EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, () => _inGame = false);
|
||||
_unRegisters[3] = EnumEventSystem.Global.Register(GameLoopEnum.PauseGame, () => _inGame = false);
|
||||
|
||||
_unRegisters[4] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => _isDialog = true);
|
||||
_unRegisters[5] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => _isDialog = true);
|
||||
}
|
||||
|
||||
private void UnRegisterEvents()
|
||||
{
|
||||
foreach (var unRegister in _unRegisters)
|
||||
{
|
||||
unRegister.UnRegister();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4269da1f8c364e319da84b5fee61bafe
|
||||
timeCreated: 1761032421
|
||||
@@ -6,6 +6,9 @@ using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
/// <summary>
|
||||
/// 对话View,仅用于处理对话文本
|
||||
/// </summary>
|
||||
public class LineView : DialogueViewBase
|
||||
{
|
||||
public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using AibisDream.Kit;
|
||||
using AibisDream.Utility;
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class LineViewNew : DialogueViewBase
|
||||
{
|
||||
[SerializeField] private LineAdvanceInput advanceInput;
|
||||
// [SerializeField] private BubbleCenter bubbleCenter;
|
||||
|
||||
public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished)
|
||||
{
|
||||
// 预处理Line和Event
|
||||
var lineSyncEvent = new LineSyncToken(dialogueLine, onDialogueLineFinished);
|
||||
// bubbleCenter.RunLine(lineSyncEvent);
|
||||
advanceInput.RunLine(lineSyncEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public class LineSyncToken
|
||||
{
|
||||
public LineInfo lineInfo;
|
||||
public LineSyncState state;
|
||||
|
||||
public Action nextStep;
|
||||
public event Action SkipTextAnima;
|
||||
|
||||
public LineSyncToken(LocalizedLine lineInfo, Action nextStep)
|
||||
{
|
||||
this.lineInfo = LineInfo.Generate(lineInfo);
|
||||
this.nextStep = nextStep;
|
||||
state = LineSyncState.PlayText;
|
||||
}
|
||||
|
||||
public bool TrySkip()
|
||||
{
|
||||
if (state == LineSyncState.PlayText)
|
||||
{
|
||||
SkipTextAnima?.Invoke();
|
||||
SkipTextAnima = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能跳过文本");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryAdvance()
|
||||
{
|
||||
if (state == LineSyncState.WaitForAdvance)
|
||||
{
|
||||
nextStep?.Invoke();
|
||||
state = LineSyncState.Advanced;
|
||||
Dispose();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能向前推进");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Dispose()
|
||||
{
|
||||
nextStep = null;
|
||||
SkipTextAnima = null;
|
||||
}
|
||||
|
||||
public void TextStart()
|
||||
{
|
||||
state = LineSyncState.PlayText;
|
||||
}
|
||||
|
||||
public void TextShown()
|
||||
{
|
||||
state = LineSyncState.AdvanceDelay;
|
||||
// 延时
|
||||
|
||||
state = LineSyncState.WaitForAdvance;
|
||||
}
|
||||
}
|
||||
|
||||
public struct LineInfo
|
||||
{
|
||||
public string lineId;
|
||||
public string lineText;
|
||||
public CharacterVo character;
|
||||
public bool isAutoSkip;
|
||||
|
||||
public static LineInfo Generate(LocalizedLine dialogueLine)
|
||||
{
|
||||
return new LineInfo
|
||||
{
|
||||
lineId = dialogueLine.TextID,
|
||||
lineText = dialogueLine.TextWithoutCharacterName.Text,
|
||||
character = dialogueLine.GetCharacterVo(),
|
||||
isAutoSkip = dialogueLine.IsAutoSkipLine()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum LineSyncState
|
||||
{
|
||||
PlayText,
|
||||
AdvanceDelay,
|
||||
WaitForAdvance,
|
||||
Advanced
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0d1630fcebe4fb38afd0a2bc7b3112b
|
||||
timeCreated: 1761032402
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class OptionView : DialogueViewBase
|
||||
{
|
||||
[SerializeField] private DefaultOptions defaultOptions;
|
||||
[SerializeField] private CenterOptions centerOptions;
|
||||
|
||||
public override void RunOptions(DialogueOption[] dialogueOptions, Action<int> onOptionSelected)
|
||||
{
|
||||
EnumEventSystem.Global.Send(DialogEventEnum.OptionShow);
|
||||
var options = DialogOption.GeneOptions(dialogueOptions, onOptionSelected);
|
||||
var viewType = options[0].Character.dialogViewType;
|
||||
|
||||
switch (viewType)
|
||||
{
|
||||
case DialogViewType.Default:
|
||||
defaultOptions.ShowOptions(options);
|
||||
break;
|
||||
case DialogViewType.CenterOption:
|
||||
centerOptions.ShowOptions(options);
|
||||
break;
|
||||
default:
|
||||
Debug.Log($"选项{options[0].Character.key}没有找到选项框");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56ee480f25a146839afa8ff058ddfc7a
|
||||
timeCreated: 1761032377
|
||||
@@ -221,7 +221,7 @@ namespace AibisDream
|
||||
private void RegisterDialogEvents()
|
||||
{
|
||||
// 监听对话结束事件
|
||||
DialogController.OnDialogueComplete += OnDialogueComplete;
|
||||
EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, OnDialogueComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -251,10 +251,7 @@ namespace AibisDream
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (DialogController.Instance != null)
|
||||
{
|
||||
DialogController.OnDialogueComplete -= OnDialogueComplete;
|
||||
}
|
||||
EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogStart, OnDialogueComplete);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine;
|
||||
using DG.Tweening;
|
||||
using AibisDream.Kit;
|
||||
|
||||
@@ -50,14 +51,14 @@ namespace AibisDream.FixSystem
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
DialogController.OnDialogueStart += HandleDialogueStart;
|
||||
DialogController.OnDialogueComplete += HandleDialogueComplete;
|
||||
EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, HandleDialogueStart);
|
||||
EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HandleDialogueComplete);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
DialogController.OnDialogueStart -= HandleDialogueStart;
|
||||
DialogController.OnDialogueComplete -= HandleDialogueComplete;
|
||||
EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogEnd, HandleDialogueStart);
|
||||
EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogStart, HandleDialogueComplete);
|
||||
}
|
||||
|
||||
private void InitComponentRefs()
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace AibisDream.Kit
|
||||
{
|
||||
Aside,
|
||||
Player,
|
||||
MainActor
|
||||
MainActor,
|
||||
Center
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ namespace AibisDream
|
||||
|
||||
public enum InteractionEventEnum
|
||||
{
|
||||
Start,
|
||||
End
|
||||
DialogStart,
|
||||
DialogEnd
|
||||
}
|
||||
|
||||
public struct DialogText
|
||||
|
||||
@@ -68,8 +68,8 @@ namespace AibisDream
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var unRegister1 = EnumEventSystem.Global.Register(InteractionEventEnum.Start, () => _isInteractive = true);
|
||||
var unRegister2 = EnumEventSystem.Global.Register(InteractionEventEnum.End, () => _isInteractive = false);
|
||||
var unRegister1 = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => _isInteractive = true);
|
||||
var unRegister2 = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => _isInteractive = false);
|
||||
_evtUnRegisters = new[] { unRegister1, unRegister2 };
|
||||
}
|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@ namespace AibisDream
|
||||
private void RegisterTriggerEvent()
|
||||
{
|
||||
// 交互相关
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.Start, OnInteractiveStart));
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.End, OnInteractiveEnd));
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, OnInteractiveStart));
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, OnInteractiveEnd));
|
||||
|
||||
_unRegisters.Add(
|
||||
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerEnter, OnPointerEnter));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.Kit;
|
||||
using AibisDream.Utility;
|
||||
@@ -10,7 +9,7 @@ using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class Bubble : MonoBehaviour
|
||||
public class Bubble : MonoBehaviour, IBubble
|
||||
{
|
||||
private TypewriterCore _typewriter;
|
||||
private TMP_Text _actorName;
|
||||
@@ -24,16 +23,18 @@ namespace AibisDream
|
||||
|
||||
#region 参数
|
||||
|
||||
[SerializeField] public ActorRole role;
|
||||
[SerializeField] public int idx;
|
||||
[SerializeField] private ActorRole role;
|
||||
[SerializeField] private int idx;
|
||||
[SerializeField] private int maxWidth;
|
||||
[SerializeField] private int minWidth;
|
||||
|
||||
public ActorRole Role => role;
|
||||
public int Idx => idx;
|
||||
|
||||
#endregion
|
||||
|
||||
public event Action<Bubble> OnDisposed;
|
||||
|
||||
public bool IsShowingText => _typewriter.isShowingText;
|
||||
public event Action OnLineShown;
|
||||
|
||||
public void LoadConfig(BubbleSlotData data)
|
||||
{
|
||||
@@ -47,6 +48,14 @@ namespace AibisDream
|
||||
rect.localPosition = UIManager.GetDialogUIPos(data.slotPosition);
|
||||
// 设置style
|
||||
SetStyle(data.bubbleStyle, data.pivotType);
|
||||
// 注册事件
|
||||
_typewriter.onTextShowed.AddListener(InvokeLineShown);
|
||||
}
|
||||
|
||||
private void InvokeLineShown()
|
||||
{
|
||||
OnLineShown?.Invoke();
|
||||
OnLineShown = null;
|
||||
}
|
||||
|
||||
private void SetStyle(BubbleStyle bubbleStyle, PivotType pivotType)
|
||||
@@ -93,7 +102,7 @@ namespace AibisDream
|
||||
? string.Empty
|
||||
: characterVo.GetActorName();
|
||||
}
|
||||
|
||||
|
||||
public void ShowLine(string line)
|
||||
{
|
||||
_typewriter.TextAnimator.SetText("");
|
||||
@@ -102,11 +111,16 @@ namespace AibisDream
|
||||
_typewriter.ShowText(line);
|
||||
}
|
||||
|
||||
public void SkipLine()
|
||||
public bool SkipLine()
|
||||
{
|
||||
if (_typewriter.isShowingText)
|
||||
{
|
||||
_typewriter.SkipTypewriter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +132,7 @@ namespace AibisDream
|
||||
public void Dispose()
|
||||
{
|
||||
Hide();
|
||||
_typewriter.onTextShowed.RemoveAllListeners();
|
||||
OnDisposed?.Invoke(this);
|
||||
OnDisposed = null;
|
||||
}
|
||||
@@ -125,8 +140,7 @@ namespace AibisDream
|
||||
private void HandleLayout(string line)
|
||||
{
|
||||
// 先去除富文本标签
|
||||
line = Regex.Replace(line.Replace("<br>", "\n"), "[<|{].*?[>|}]", string.Empty);
|
||||
var width = DialogCanvasManager.Instance.EstimateTextWidth(line, _lineText.fontSize);
|
||||
var width = DialogCanvasManager.Instance.EstimateTextWidth(line.RemoveRichTextTags(), _lineText.fontSize);
|
||||
if (width > maxWidth)
|
||||
{
|
||||
_layoutElement.preferredWidth = maxWidth;
|
||||
@@ -172,4 +186,16 @@ namespace AibisDream
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public interface IBubble
|
||||
{
|
||||
public ActorRole Role { get; }
|
||||
public int Idx { get; }
|
||||
|
||||
public event Action OnLineShown;
|
||||
public void ShowActorName(CharacterVo characterVo);
|
||||
public void ShowLine(string line);
|
||||
public bool SkipLine();
|
||||
public void Hide();
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,15 @@ namespace AibisDream
|
||||
{
|
||||
public class BubbleGroup : Singleton<BubbleGroup>, IDialogView
|
||||
{
|
||||
private BubbleOption[] _options;
|
||||
[SerializeField] private CenterBubble centerBubble;
|
||||
|
||||
private Dictionary<ActorRole, Bubble[]> _bubbleDict;
|
||||
public DialogViewType CurDialogType { get; private set; }
|
||||
|
||||
private BubbleFactory _bubbleFactory;
|
||||
|
||||
private SimpleObjectPool<Bubble> _bubblePool;
|
||||
private SimpleObjectPool<BubbleOption> _optionPool;
|
||||
|
||||
#region 一些索引
|
||||
|
||||
|
||||
private Action _nextStep;
|
||||
private Bubble _curBubble;
|
||||
private IBubble _curBubble;
|
||||
|
||||
private IUnRegister _unRegister;
|
||||
|
||||
@@ -31,12 +27,8 @@ namespace AibisDream
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
// 注册泡泡
|
||||
_unRegister =
|
||||
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(DialogEventEnum.OptionSelected,
|
||||
_ => HideOptions());
|
||||
// 工厂
|
||||
_bubbleFactory = new BubbleFactory(transform.Find("Bubbles"));
|
||||
_bubbleFactory = new BubbleFactory(transform);
|
||||
// 加载选项
|
||||
InitOptions();
|
||||
}
|
||||
@@ -53,7 +45,6 @@ namespace AibisDream
|
||||
|
||||
public void LoadBubbles(BubbleSlotGroupData groupData)
|
||||
{
|
||||
CurDialogType = groupData.dialogViewType;
|
||||
// 回收旧泡泡
|
||||
foreach (var oldBubble in _bubbleDict.Values.SelectMany(item => item))
|
||||
{
|
||||
@@ -63,35 +54,18 @@ namespace AibisDream
|
||||
// 加载新泡泡
|
||||
_bubbleDict = groupData.bubbleSlots
|
||||
.Select(item => _bubbleFactory.Create(item))
|
||||
.GroupBy(item => item.role)
|
||||
.GroupBy(item => item.Role)
|
||||
.ToDictionary(group => group.Key, group => group.ToArray());
|
||||
|
||||
// 更新选项的位置
|
||||
if (groupData.bubbleOptionSlots is { Length: 0 })
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var optionSlotData in groupData.bubbleOptionSlots)
|
||||
{
|
||||
if (optionSlotData.optionIdx >= _options.Length) continue;
|
||||
_options[optionSlotData.optionIdx].LoadData(optionSlotData);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitOptions()
|
||||
{
|
||||
_options = transform.Find("Options")
|
||||
.GetComponentsInChildren<BubbleOption>(true)
|
||||
.OrderBy(item => item.optionIdx)
|
||||
.ToArray();
|
||||
|
||||
_bubbleDict = new Dictionary<ActorRole, Bubble[]>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对话框功能实现
|
||||
#region 旧对话框功能实现
|
||||
|
||||
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId,
|
||||
bool isAutoSkip = false)
|
||||
@@ -121,48 +95,24 @@ namespace AibisDream
|
||||
Debug.Log($"[BubbleGroup] ShowLine - 设置完成,_nextStep是否为null: {_nextStep == null}");
|
||||
}
|
||||
|
||||
public void ShowOptions(DialogOption[] dialogueOptions)
|
||||
{
|
||||
HideDialog();
|
||||
var availableOptions = dialogueOptions.Where(item => item.IsAvailable).ToArray();
|
||||
// 如果仅由一个选项
|
||||
if (availableOptions.Length == 1)
|
||||
{
|
||||
_options[0].ShowOption(availableOptions[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < availableOptions.Length; i++)
|
||||
{
|
||||
_options[i + 1].ShowOption(availableOptions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HideDialog()
|
||||
{
|
||||
foreach (var textBubble in _bubbleDict.Values.SelectMany(inner => inner))
|
||||
{
|
||||
textBubble.Hide();
|
||||
}
|
||||
|
||||
HideOptions();
|
||||
|
||||
centerBubble.Hide();
|
||||
}
|
||||
|
||||
public bool TrySkipLine(bool isForceSkip = false)
|
||||
{
|
||||
if (!_curBubble)
|
||||
if (_curBubble == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_curBubble && _curBubble.IsShowingText)
|
||||
{
|
||||
_curBubble.SkipLine();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return _curBubble.SkipLine();
|
||||
}
|
||||
|
||||
public void NextStep()
|
||||
@@ -174,8 +124,6 @@ namespace AibisDream
|
||||
Debug.Log("[BubbleGroup] NextStep - _nextStep为null,提前返回");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("[BubbleGroup] NextStep - 发送LineEnd事件");
|
||||
|
||||
var next = _nextStep;
|
||||
_nextStep = null;
|
||||
@@ -183,35 +131,40 @@ namespace AibisDream
|
||||
_curBubble?.Hide();
|
||||
_curBubble = null;
|
||||
|
||||
Debug.Log("[BubbleGroup] NextStep - 调用回调");
|
||||
next?.Invoke();
|
||||
Debug.Log("[BubbleGroup] NextStep - 回调调用完成");
|
||||
}
|
||||
|
||||
public void OnLocalizationChanged(string value)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void HideDialog(Bubble activeBubble)
|
||||
|
||||
private void HideDialog(IBubble activeBubble)
|
||||
{
|
||||
foreach (var textBubble in _bubbleDict.Values.SelectMany(inner => inner))
|
||||
{
|
||||
if (activeBubble != textBubble)
|
||||
if (activeBubble != (IBubble)textBubble)
|
||||
{
|
||||
textBubble.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
HideOptions();
|
||||
if (activeBubble != (IBubble)centerBubble)
|
||||
{
|
||||
centerBubble.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetBubble(ActorRole role, int idx, out Bubble bubble)
|
||||
private bool TryGetBubble(ActorRole role, int idx, out IBubble bubble)
|
||||
{
|
||||
if (role == ActorRole.Center)
|
||||
{
|
||||
bubble = centerBubble;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_bubbleDict.TryGetValue(role, out var bubbles))
|
||||
{
|
||||
bubble = bubbles.FirstOrDefault(item => item.idx == idx);
|
||||
bubble = bubbles.FirstOrDefault(item => item.Idx == idx);
|
||||
return bubble != null;
|
||||
}
|
||||
|
||||
@@ -219,12 +172,32 @@ namespace AibisDream
|
||||
return false;
|
||||
}
|
||||
|
||||
private void HideOptions()
|
||||
#endregion
|
||||
|
||||
#region 新对话框功能实现
|
||||
|
||||
public void RunLine(LineSyncToken syncToken)
|
||||
{
|
||||
foreach (var option in _options)
|
||||
var character = syncToken.lineInfo.character;
|
||||
|
||||
if (TryGetBubble(character.role, character.bubbleIdx, out var bubble))
|
||||
{
|
||||
option.Hide();
|
||||
// 注册事件
|
||||
bubble.OnLineShown += syncToken.TextShown;
|
||||
syncToken.SkipTextAnima += () => bubble.SkipLine();
|
||||
// 播放文字
|
||||
bubble.ShowActorName(character);
|
||||
bubble.ShowLine(syncToken.lineInfo.lineText);
|
||||
// 将非选定的Bubble隐藏
|
||||
HideDialog(bubble);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"{character.GetActorName()}的Role {character.role}没有对应Bubble");
|
||||
HideDialog();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using TMPro;
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@@ -17,12 +18,7 @@ namespace AibisDream
|
||||
_button = GetComponent<Button>();
|
||||
}
|
||||
|
||||
public void LoadData(BubbleOptionSlotData data)
|
||||
{
|
||||
((RectTransform)transform).localPosition = UIManager.GetDialogUIPos(data.slotPosition);
|
||||
}
|
||||
|
||||
public void ShowOption(DialogOption dialogOption)
|
||||
public void ShowOption(DialogOption dialogOption, Action hide)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
_button.onClick.RemoveAllListeners();
|
||||
@@ -32,6 +28,7 @@ namespace AibisDream
|
||||
_text.text = dialogOption.Line;
|
||||
_button.onClick.AddListener(() =>
|
||||
{
|
||||
hide?.Invoke();
|
||||
dialogOption.Select();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using AibisDream.Kit;
|
||||
using Febucci.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class CenterBubble : MonoBehaviour, IBubble
|
||||
{
|
||||
[SerializeField] private TypewriterByCharacter dialogText;
|
||||
|
||||
public ActorRole Role => ActorRole.Center;
|
||||
public int Idx => 0;
|
||||
public event Action OnLineShown;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
dialogText.onTextShowed.AddListener(InvokeLineShown);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
dialogText.onTextShowed.RemoveAllListeners();
|
||||
}
|
||||
|
||||
private void InvokeLineShown()
|
||||
{
|
||||
OnLineShown?.Invoke();
|
||||
OnLineShown = null;
|
||||
}
|
||||
|
||||
public void ShowActorName(CharacterVo characterVo)
|
||||
{
|
||||
// 不显示名称
|
||||
}
|
||||
|
||||
public void ShowLine(string line)
|
||||
{
|
||||
dialogText.TextAnimator.SetText("");
|
||||
gameObject.SetActive(true);
|
||||
dialogText.ShowText(line);
|
||||
}
|
||||
|
||||
public bool SkipLine()
|
||||
{
|
||||
if (dialogText.isShowingText)
|
||||
{
|
||||
dialogText.SkipTypewriter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67e53e476f874efd9d847b50dc16d6c8
|
||||
timeCreated: 1761206826
|
||||
@@ -0,0 +1,42 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class CenterOptions : MonoBehaviour
|
||||
{
|
||||
public GameObject choiceButtonPrefab;
|
||||
|
||||
public void ShowOptions(DialogOption[] dialogOptions)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
|
||||
// 销毁原来的按钮
|
||||
foreach (Transform child in transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// 生成新按钮
|
||||
foreach (var option in dialogOptions)
|
||||
{
|
||||
if (!option.IsAvailable) continue;
|
||||
|
||||
var choiceInstance = Instantiate(choiceButtonPrefab, transform);
|
||||
var optionText = choiceInstance.GetComponentInChildren<TextMeshProUGUI>();
|
||||
optionText.text = option.Line;
|
||||
choiceInstance.GetComponent<Button>().onClick.AddListener(() =>
|
||||
{
|
||||
HideOptions();
|
||||
option.Select();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void HideOptions()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b56b42b68f74c719dd5f36a4696d61b
|
||||
timeCreated: 1761218547
|
||||
@@ -14,7 +14,6 @@ namespace AibisDream
|
||||
#region 索引
|
||||
|
||||
private TypewriterByCharacter _dialogText;
|
||||
private Image _panel;
|
||||
private Action _nextStep;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class DefaultOptions : MonoBehaviour
|
||||
{
|
||||
private BubbleOption[] _options;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_options = transform.Find("Options")
|
||||
.GetComponentsInChildren<BubbleOption>(true)
|
||||
.OrderBy(item => item.optionIdx)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public void ShowOptions(DialogOption[] dialogueOptions)
|
||||
{
|
||||
HideOptions();
|
||||
var availableOptions = dialogueOptions.Where(item => item.IsAvailable).ToArray();
|
||||
// 如果仅由一个选项
|
||||
if (availableOptions.Length == 1)
|
||||
{
|
||||
_options[0].ShowOption(availableOptions[0], HideOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < availableOptions.Length; i++)
|
||||
{
|
||||
_options[i + 1].ShowOption(availableOptions[i], HideOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HideOptions()
|
||||
{
|
||||
foreach (var option in _options)
|
||||
{
|
||||
option.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14d86fd6c1664941a0c693acb51c6b4b
|
||||
timeCreated: 1761217326
|
||||
@@ -8,7 +8,7 @@ using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class DialogCanvasManager : Singleton<DialogCanvasManager>, IDialogView
|
||||
public class DialogCanvasManager : Singleton<DialogCanvasManager>
|
||||
{
|
||||
#region 引用
|
||||
|
||||
@@ -140,12 +140,12 @@ namespace AibisDream
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
DialogController.OnDialogueComplete += HideDialog;
|
||||
EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
DialogController.OnDialogueComplete -= HideDialog;
|
||||
EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -382,8 +382,6 @@ namespace AibisDream
|
||||
public enum DialogViewType
|
||||
{
|
||||
Default,
|
||||
Bubble,
|
||||
OldBox,
|
||||
Screen,
|
||||
CenterText,
|
||||
CenterOption,
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AibisDream
|
||||
{
|
||||
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId ,bool isAutoSkip = false);
|
||||
|
||||
public void ShowOptions(DialogOption[] dialogueOptions);
|
||||
public void ShowOptions(DialogOption[] dialogueOptions) {}
|
||||
|
||||
public void HideDialog();
|
||||
|
||||
|
||||
@@ -282,5 +282,10 @@ namespace AibisDream.Utility
|
||||
.Where(t => t.GetCustomAttributes(typeof(TAttribute), false).Length > 0)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static string RemoveRichTextTags(this string str)
|
||||
{
|
||||
return Regex.Replace(str.Replace("<br>", "\n"), "[<|{].*?[>|}]", string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user