boxmoe_header_banner_img

菜就多练喵

文章导读

[C#][Unity][Ib_Core]Ib_Dialogue——简易对话系统设计


avatar
Ib_Mccf 2026年3月5日 35

功能:简易单分支多角色对话

特点:各功能模块解耦,通过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)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码