剧情+对话完善

This commit is contained in:
SoulliesOfficial
2026-07-21 15:24:42 -04:00
parent 8f230831e9
commit 810d019619
161 changed files with 7271 additions and 1893 deletions

View File

@@ -0,0 +1,102 @@
using System;
using DG.Tweening;
using TMPro;
using UnityEngine;
namespace Ichni.Story
{
/// <summary>
/// 由 <see cref="StoryHelperController"/> 按需实例化的 Helper 专属对话气泡。
/// <para>每个实例只显示一条文本:淡入、停留、淡出后自动销毁,因此场景中不需要常驻气泡,
/// 也不会与通用 MessageBox 队列产生耦合。</para>
/// </summary>
[RequireComponent(typeof(CanvasGroup))]
public class StoryHelperTalk : MonoBehaviour
{
[SerializeField, Tooltip("显示 Helper 名称的文本。")]
private TMP_Text speakerText;
[SerializeField, Tooltip("显示随机 Helper 对话的文本。")]
private TMP_Text contentText;
[Header("Animation")]
[SerializeField, Min(0.01f), Tooltip("淡入与缩放入场时间。")]
private float showDuration = 0.18f;
[SerializeField, Min(0f), Tooltip("气泡完整显示后的停留时间。")]
private float visibleDuration = 4.5f;
[SerializeField, Min(0.01f), Tooltip("淡出与缩放退场时间。")]
private float hideDuration = 0.16f;
[SerializeField, Range(0.5f, 1f), Tooltip("入场与退场时相对原始大小的缩放比例。")]
private float initialScaleMultiplier = 0.92f;
/// <summary>气泡结束显示并准备销毁时触发,供创建者清理当前实例引用。</summary>
public event Action<StoryHelperTalk> Closed;
private CanvasGroup _canvasGroup;
private RectTransform _rectTransform;
private Sequence _sequence;
private Vector3 _baseScale;
private bool _isClosed;
private void Awake()
{
_canvasGroup = GetComponent<CanvasGroup>();
_rectTransform = transform as RectTransform;
_baseScale = _rectTransform != null ? _rectTransform.localScale : Vector3.one;
}
/// <summary>
/// 写入文本并播放完整的出现、停留与收回流程。
/// 所有 DOTween Sequence 均先 Pause再手动调用 Play符合项目约定。
/// </summary>
public void Show(string speaker, string content)
{
if (speakerText == null || contentText == null || _rectTransform == null)
{
Debug.LogWarning("[StoryHelperTalk] Prefab 未配置 Speaker Text、Content Text 或 RectTransform已取消显示。", this);
CloseImmediately();
return;
}
speakerText.text = speaker;
contentText.text = content;
_canvasGroup.alpha = 0f;
_rectTransform.localScale = _baseScale * initialScaleMultiplier;
_sequence?.Kill();
_sequence = DOTween.Sequence()
.Pause()
.SetUpdate(true)
.Append(_canvasGroup.DOFade(1f, showDuration))
.Join(_rectTransform.DOScale(_baseScale, showDuration).SetEase(Ease.OutBack))
.AppendInterval(visibleDuration)
.Append(_canvasGroup.DOFade(0f, hideDuration))
.Join(_rectTransform.DOScale(_baseScale * initialScaleMultiplier, hideDuration).SetEase(Ease.InQuad))
.OnComplete(CloseImmediately);
_sequence.Play();
}
/// <summary>
/// 立即关闭并销毁该运行时实例。再次点击 Helper 时会调用它,使旧文本不会与新文本叠加。
/// </summary>
public void CloseImmediately()
{
if (_isClosed)
return;
_isClosed = true;
_sequence?.Kill();
_sequence = null;
Closed?.Invoke(this);
Destroy(gameObject);
}
private void OnDestroy()
{
_sequence?.Kill();
}
}
}