功能:简易单分支多角色对话
特点:各功能模块解耦,通过Ib_Event事件通信,UI使用MVC思想设计,逻辑与数据分离。并保留足够的拓展性。

Event
public class OnShowDialogue : Ib_Event<OnShowDialogue,DialogueConfig> { }
public class OnHideDialogue : Ib_Event<OnHideDialogue> { }
public class OnPushDialogueIndices : Ib_Event<OnPushDialogueIndices,List<string>> { }
public class OnClearDialogueIndices : Ib_Event<OnClearDialogueIndices> { }
Model
public struct DialoguePanelViewModel
{
public string Icon;
public string Name;
public string Content;
public float TextEffectDuration;
public DialoguePanelViewModel(string icon, string name, string content, float textEffectDuration)
{
Icon = icon;
Name = name;
Content = content;
TextEffectDuration = textEffectDuration;
}
}
View
public class DialoguePanelView : MonoBehaviour
{
[SerializeField] private GameObject dialoguePanel;
[SerializeField] private Image icon;
[SerializeField] private TextMeshProUGUI nameText;
[SerializeField] private TextMeshProUGUI contentText;
private Tween textTween;
public void Render(DialoguePanelViewModel viewModel)
{
if(icon != null)icon.SetSprite(viewModel.Icon);
if(nameText != null)nameText.text = viewModel.Name;
if(dialoguePanel != null)dialoguePanel.SafeSetActive(true);
if (contentText != null)
{
textTween?.Kill();
textTween = contentText.DOText(viewModel.Content, viewModel.TextEffectDuration);
}
}
public void Clear()
{
if(dialoguePanel != null)dialoguePanel.SafeSetActive(false);
textTween?.Kill();
textTween = null;
if(contentText != null)contentText.text = "";
}
}
Controller
public class DialoguePanelController : MonoBehaviour
{
[BoxGroup("view")][SerializeField] private DialoguePanelView dialoguePanelView;
public void Start()
{
if(dialoguePanelView == null) return;
OnShowDialogue.Register(Render);
OnHideDialogue.Register(Clear);
dialoguePanelView.Clear();
}
public void OnDestroy()
{
if(dialoguePanelView == null) return;
OnShowDialogue.Deregister(Render);
OnHideDialogue.Deregister(Clear);
}
private void Render(DialogueConfig config)
{
if(dialoguePanelView == null) return;
var viewModel = new DialoguePanelViewModel(
string.IsNullOrEmpty(config.Icon) ? GlobalCfg.kUnknownIcon : config.Icon,
XLanguage.Get(config.Name)??XLanguage.Get(GlobalCfg.kUnknownName),
XLanguage.Get(config.Content)??XLanguage.Get(GlobalCfg.kUnknownDesc),
config.TextEffectDuration);
dialoguePanelView.Render(viewModel);
}
private void Clear() => dialoguePanelView?.Clear();
}
UI

System
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Ib_Core;
using UnityEngine;
public class DialogueSystem : SingletonBehaviour<DialogueSystem>,IUpdate
{
public void OnEnable()
{
this.RegisterOrUpdateManagedUpdate(Ib_UpdatePriority.Normal, 0f,this.GetCancellationTokenOnDestroy());
OnPushDialogueIndices.Register(SetDialogueConfigIndeices);
OnClearDialogueIndices.Register(ClearDialogueConfigIndeices);
}
public void OnDisable()
{
this.DeregisterManagedUpdate();
OnPushDialogueIndices.Deregister(SetDialogueConfigIndeices);
OnClearDialogueIndices.Deregister(ClearDialogueConfigIndeices);
}
private List<string> dialogueConfigIndeices = new List<string>();
private void SetDialogueConfigIndeices(List<string> indices)
{
if(indices == null || indices.Count == 0)return;
dialogueConfigIndeices.Clear();
for (int i = 0; i < indices.Count; i++)
dialogueConfigIndeices.Add(indices[i]);
currentIndex = -1;
}
private void ClearDialogueConfigIndeices()
{
dialogueConfigIndeices.Clear();
currentIndex = -1;
}
private int currentIndex = -1;
private float lastClickTimer = -1f;
private DialogueConfig GetDialogueConfig(string configID)
{
return ContentData.Default.GetDialogueConfig(configID);
}
private void ShowDialogue(DialogueConfig config)
{
if(config == null) return;
lastClickTimer = Time.realtimeSinceStartup;
OnHideDialogue.Invoke();
OnShowDialogue.Invoke(config);
}
private void HideDialogue()
{
dialogueConfigIndeices.Clear();
lastClickTimer = -1f;
OnHideDialogue.Invoke();
}
public void ManagedUpdate(float deltaTime)
{
if(dialogueConfigIndeices.Count == 0) return;
if (currentIndex == -1)
{
currentIndex = 0;
var config = GetDialogueConfig(dialogueConfigIndeices[currentIndex]);
if (config != null) OnShowDialogue.Invoke(config);
return;
}else if (currentIndex >= dialogueConfigIndeices.Count)
{
HideDialogue();
currentIndex = -1;
return;
}
if (Input.GetMouseButtonDown(0))
{
//防止快速点击
if(Time.realtimeSinceStartup - lastClickTimer < 0.5f) return;
currentIndex++;
if(currentIndex >= 0 && currentIndex < dialogueConfigIndeices.Count)
{
ShowDialogue(GetDialogueConfig(dialogueConfigIndeices[currentIndex]));
}
}
}
}
评论(0)
暂无评论