Files
ichni_Official/Assets/Scripts/NewStorySystem/UI/StoryMessageBoxUIPage.cs
SoulliesOfficial 7b7d069b84 StorySystem
2026-07-07 01:28:27 -04:00

144 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using Ichni.Menu.UI;
using Ichni.UI;
using UnityEngine;
namespace Ichni.Story.UI
{
/// <summary>
/// 用于在剧情系统中管理并顺序展示 MessageBox 的独立 UI 页面。
/// 支持动态实例化给定的 MessageBox Prefab并在所有消息展示完毕后进行大页面的 FadeOut。
/// </summary>
public class StoryMessageBoxUIPage : UIPageBase
{
public static StoryMessageBoxUIPage instance;
[Header("Prefabs & Containers")]
[Tooltip("默认使用的 MessageBox 预制体(请从 Project 中拖拽,而非场景中的实例)")]
public MessageBox defaultMessageBoxPrefab;
[Tooltip("生成的 MessageBox 挂载在哪?如果不填,默认挂载在自己身上")]
public Transform messageContainer;
// 用于排队的内部消息数据结构
private struct PendingMessage
{
public string title;
public string content;
public MessageBox customPrefab; // 支持未来传入不同种类的 Prefab
}
private Queue<PendingMessage> _messageQueue = new Queue<PendingMessage>();
private MessageBox _currentActiveBox;
private bool _isPageActive = false;
protected override void Awake()
{
base.Awake();
if (instance == null)
{
instance = this;
}
else
{
Debug.LogWarning("[StoryMessageBoxUIPage] 场景中存在多个实例,正在销毁多余的实例。");
Destroy(gameObject);
return;
}
if (messageContainer == null)
{
messageContainer = this.transform;
}
}
/// <summary>
/// 将歌曲解锁提示加入弹窗队列。
/// </summary>
public void ShowUnlockMessage(string songUnlockKey)
{
string title = "New Song Unlocked!";
string content = $"You have unlocked the song: {songUnlockKey}!";
EnqueueMessage(title, content, defaultMessageBoxPrefab);
}
/// <summary>
/// 将自定义文本提示加入弹窗队列。
/// </summary>
public void ShowCustomMessage(string title, string content)
{
EnqueueMessage(title, content, defaultMessageBoxPrefab);
}
/// <summary>
/// 将指定消息入队。如果是空闲状态,则唤醒大页面并开始处理队列。
/// </summary>
private void EnqueueMessage(string title, string content, MessageBox prefab)
{
if (prefab == null)
{
Debug.LogError("[StoryMessageBoxUIPage] 没有可用的 MessageBox 预制体!");
return;
}
_messageQueue.Enqueue(new PendingMessage
{
title = title,
content = content,
customPrefab = prefab
});
// 如果当前页面没有在显示中,则开始整体流程
if (!_isPageActive)
{
_isPageActive = true;
// 唤醒大页面(执行 UIPageBase 的渐入并拦截底层射线)
this.FadeIn(0.5f, false, ShowNextInQueue);
}
}
/// <summary>
/// 从队列中取出一个并实例化显示。
/// </summary>
private void ShowNextInQueue()
{
if (_messageQueue.Count == 0)
{
// 队列处理完毕,大页面整体退场
_currentActiveBox = null;
_isPageActive = false;
this.FadeOut();
return;
}
PendingMessage msg = _messageQueue.Dequeue();
// 实例化预制体
_currentActiveBox = Instantiate(msg.customPrefab, messageContainer);
// 订阅“当这个消息框彻底结束关闭时”的事件
_currentActiveBox.onAllMessagesClosed.AddListener(() =>
{
// 销毁旧实例
if (_currentActiveBox != null)
{
Destroy(_currentActiveBox.gameObject);
}
// 检查并显示下一个
ShowNextInQueue();
});
// 配置并启动 MessageBox
_currentActiveBox.Clear();
_currentActiveBox.AddInfo(msg.title, msg.content, null);
// MessageBox.SetUp() 内部会激活自己并执行自己的 FadeIn
_currentActiveBox.gameObject.SetActive(true);
_currentActiveBox.SetUp();
}
}
}