气泡组件和配置项
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using AibisDream.Config;
|
||||
using AibisDream.Utility;
|
||||
using Febucci.UI;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public abstract class DialogBoxBase : MonoBehaviour, IDialogView
|
||||
{
|
||||
#region box组件名称
|
||||
|
||||
private const string ActorName = "Actor Name";
|
||||
private const string DialogText = "Dialog Text";
|
||||
private const string NextArray = "Next Array";
|
||||
private const string ChoiceBox = "Choice Box";
|
||||
|
||||
#endregion
|
||||
|
||||
#region box组件
|
||||
|
||||
protected TypewriterByCharacter dialogText;
|
||||
protected TextMeshProUGUI actorName;
|
||||
protected GameObject nextArray;
|
||||
protected GameObject choiceBox;
|
||||
|
||||
#endregion
|
||||
|
||||
private bool _skipLineDelay;
|
||||
[Header("跳过阻塞延迟时间/ms")]
|
||||
[SerializeField] private int delayTime = 300;
|
||||
|
||||
protected GameObject choiceButtonPrefab;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
LoadChoiceButton();
|
||||
InitComponents();
|
||||
AddSomeListener();
|
||||
}
|
||||
|
||||
private void AddSomeListener()
|
||||
{
|
||||
// 对话显示后有一段延时不可跳过
|
||||
dialogText.onTypewriterStart.AddListener(() =>
|
||||
{
|
||||
_skipLineDelay = true;
|
||||
CommonUtil.Delay(delayTime, () => { _skipLineDelay = false; });
|
||||
});
|
||||
}
|
||||
|
||||
#region 初始化
|
||||
|
||||
protected virtual void LoadChoiceButton()
|
||||
{
|
||||
Debug.Log("无选项对话框");
|
||||
}
|
||||
|
||||
private void InitComponents()
|
||||
{
|
||||
actorName = transform.Find(ActorName)?.gameObject.GetComponent<TextMeshProUGUI>();
|
||||
dialogText = transform.Find(DialogText)?.gameObject.GetComponent<TypewriterByCharacter>();
|
||||
nextArray = transform.Find(NextArray)?.gameObject;
|
||||
choiceBox = transform.Find(ChoiceBox)?.gameObject;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏对话盒
|
||||
/// </summary>
|
||||
public void HideDialog()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示对话
|
||||
/// </summary>
|
||||
/// <param name="dialogLine">对话内容</param>
|
||||
/// <param name="character">角色内容</param>
|
||||
/// <param name="nextStep">下一步</param>
|
||||
/// <param name="isAutoSkip">是否自动跳过,默认为false</param>
|
||||
public virtual void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
// 没有dialogText说明不能显示对话,直接跳过
|
||||
if (!dialogText)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 把原有对话清掉
|
||||
ClearBox();
|
||||
dialogText.gameObject.SetActive(true);
|
||||
choiceBox?.SetActive(false);
|
||||
|
||||
// 显示内容
|
||||
ShowActorName(character);
|
||||
dialogText.ShowText(dialogLine);
|
||||
|
||||
// TODO 如果有头像的对话框要加入头像处理
|
||||
|
||||
// 自动跳过的回调很难独立Remove,只能全部清空再注册,下策
|
||||
dialogText.onTextShowed.RemoveAllListeners();
|
||||
dialogText.onTextShowed.AddListener(() => nextArray.gameObject.SetActive(true));
|
||||
|
||||
// 执行自动跳过结局
|
||||
if (isAutoSkip)
|
||||
{
|
||||
dialogText.onTextShowed.AddListener(() => CommonUtil.Delay(200, nextStep));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 展示选项
|
||||
/// </summary>
|
||||
/// <param name="dialogueOptions">对话选项</param>
|
||||
/// <param name="onOptionSelected">选项选择</param>
|
||||
public virtual void ShowOptions(DialogueOption[] dialogueOptions, Action<int> onOptionSelected)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
// 没有选择框直接不显示选项
|
||||
if (!choiceBox)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 把原有对话清掉
|
||||
ClearBox();
|
||||
choiceBox.SetActive(true);
|
||||
dialogText.gameObject.SetActive(false);
|
||||
|
||||
// 销毁原来的按钮
|
||||
foreach (Transform child in choiceBox.transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// 生成新按钮
|
||||
foreach (DialogueOption option in dialogueOptions)
|
||||
{
|
||||
if (!option.IsAvailable) continue;
|
||||
|
||||
var choiceInstance = Instantiate(choiceButtonPrefab, choiceBox.transform);
|
||||
choiceInstance.GetComponentInChildren<TextMeshProUGUI>().text =
|
||||
option.Line.TextWithoutCharacterName.Text;
|
||||
choiceInstance.GetComponent<Button>().onClick
|
||||
.AddListener(() => onOptionSelected.Invoke(option.DialogueOptionID));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试跳过对话
|
||||
/// true说明成功快进了对话显示
|
||||
/// false说明对话已经显示完成了,可以跳过
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool TrySkipLine()
|
||||
{
|
||||
if (_skipLineDelay)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dialogText.isShowingText)
|
||||
{
|
||||
dialogText.SkipTypewriter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextArray.gameObject.SetActive(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearBox()
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
dialogText?.ShowText("");
|
||||
nextArray?.SetActive(false);
|
||||
if (!actorName) actorName.text = "";
|
||||
}
|
||||
|
||||
private void ShowActorName(CharacterVo character)
|
||||
{
|
||||
if (!actorName) return;
|
||||
|
||||
if (string.IsNullOrEmpty(character.nameColor))
|
||||
{
|
||||
actorName.text = character.cn;
|
||||
}
|
||||
else
|
||||
{
|
||||
var showStr = $"<color={character.nameColor}>{character.cn}</color>";
|
||||
actorName.text = showStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user