剧情+对话完善
This commit is contained in:
102
Assets/Scripts/NewStorySystem/Helper/StoryHelperTalk.cs
Normal file
102
Assets/Scripts/NewStorySystem/Helper/StoryHelperTalk.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user