382 lines
11 KiB
C#
382 lines
11 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace AibisDream.MiniGame.HuoShan
|
|
{
|
|
/// <summary>
|
|
/// 火山剧情 - 波形显示系统
|
|
/// 负责管理波形的显示、变换和比对
|
|
/// </summary>
|
|
public class WaveformDisplaySystem : MonoBehaviour
|
|
{
|
|
#region 单例
|
|
|
|
private static WaveformDisplaySystem _instance;
|
|
public static WaveformDisplaySystem Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null)
|
|
{
|
|
_instance = FindObjectOfType<WaveformDisplaySystem>();
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 序列化字段
|
|
|
|
[Header("波形显示容器")]
|
|
[SerializeField] private RectTransform waveformContainer;
|
|
[SerializeField] private CanvasGroup waveformCanvasGroup;
|
|
|
|
[Header("波形图像")]
|
|
[SerializeField] private Image primaryWaveformImage;
|
|
[SerializeField] private Image secondaryWaveformImage; // 用于比对模式
|
|
|
|
[Header("步进进度")]
|
|
[SerializeField] private GameObject stepProgressPanel;
|
|
[SerializeField] private Text stepProgressText;
|
|
[SerializeField] private Slider stepProgressSlider;
|
|
|
|
[Header("报错效果")]
|
|
[SerializeField] private RectTransform errorContainer;
|
|
[SerializeField] private GameObject errorPrefab;
|
|
[SerializeField] private int maxErrorCount = 10;
|
|
|
|
[Header("波形资源")]
|
|
[SerializeField] private WaveformData[] waveformDataList;
|
|
|
|
#endregion
|
|
|
|
#region 私有字段
|
|
|
|
private Dictionary<string, WaveformData> _waveformDict;
|
|
private List<GameObject> _activeErrors = new List<GameObject>();
|
|
private Coroutine _currentAnimation;
|
|
|
|
#endregion
|
|
|
|
#region 生命周期
|
|
|
|
private void Awake()
|
|
{
|
|
_instance = this;
|
|
InitializeWaveformDictionary();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (_instance == this)
|
|
{
|
|
_instance = null;
|
|
}
|
|
}
|
|
|
|
private void InitializeWaveformDictionary()
|
|
{
|
|
_waveformDict = new Dictionary<string, WaveformData>();
|
|
if (waveformDataList != null)
|
|
{
|
|
foreach (var data in waveformDataList)
|
|
{
|
|
if (!string.IsNullOrEmpty(data.waveformId))
|
|
{
|
|
_waveformDict[data.waveformId] = data;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 波形显示
|
|
|
|
/// <summary>
|
|
/// 显示波形
|
|
/// </summary>
|
|
public IEnumerator ShowWaveform(string waveformType, float duration)
|
|
{
|
|
if (_waveformDict.TryGetValue(waveformType, out var data))
|
|
{
|
|
primaryWaveformImage.sprite = data.waveformSprite;
|
|
primaryWaveformImage.color = data.waveformColor;
|
|
|
|
if (waveformContainer != null)
|
|
{
|
|
waveformContainer.gameObject.SetActive(true);
|
|
}
|
|
|
|
// 淡入动画
|
|
yield return FadeWaveform(0f, 1f, duration);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"WaveformDisplaySystem: 未找到波形类型 '{waveformType}'");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 隐藏波形
|
|
/// </summary>
|
|
public IEnumerator HideWaveform(float duration)
|
|
{
|
|
yield return FadeWaveform(1f, 0f, duration);
|
|
|
|
if (waveformContainer != null)
|
|
{
|
|
waveformContainer.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 波形淡入淡出
|
|
/// </summary>
|
|
private IEnumerator FadeWaveform(float from, float to, float duration)
|
|
{
|
|
if (waveformCanvasGroup == null) yield break;
|
|
|
|
float elapsed = 0f;
|
|
while (elapsed < duration)
|
|
{
|
|
elapsed += Time.deltaTime;
|
|
waveformCanvasGroup.alpha = Mathf.Lerp(from, to, elapsed / duration);
|
|
yield return null;
|
|
}
|
|
waveformCanvasGroup.alpha = to;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 波形变换
|
|
|
|
/// <summary>
|
|
/// 波形变换动画
|
|
/// </summary>
|
|
public IEnumerator TransformWaveform(string fromType, string toType, float duration)
|
|
{
|
|
if (!_waveformDict.TryGetValue(fromType, out var fromData) ||
|
|
!_waveformDict.TryGetValue(toType, out var toData))
|
|
{
|
|
Debug.LogWarning($"WaveformDisplaySystem: 波形变换失败,未找到波形类型");
|
|
yield break;
|
|
}
|
|
|
|
// 显示原始波形
|
|
primaryWaveformImage.sprite = fromData.waveformSprite;
|
|
primaryWaveformImage.color = fromData.waveformColor;
|
|
|
|
if (waveformContainer != null)
|
|
{
|
|
waveformContainer.gameObject.SetActive(true);
|
|
}
|
|
yield return FadeWaveform(0f, 1f, duration * 0.2f);
|
|
|
|
// 变换动画
|
|
float elapsed = 0f;
|
|
float transformDuration = duration * 0.6f;
|
|
while (elapsed < transformDuration)
|
|
{
|
|
elapsed += Time.deltaTime;
|
|
float t = elapsed / transformDuration;
|
|
|
|
// 颜色插值
|
|
primaryWaveformImage.color = Color.Lerp(fromData.waveformColor, toData.waveformColor, t);
|
|
|
|
// 可以添加更多变换效果,如缩放、抖动等
|
|
float shake = Mathf.Sin(t * Mathf.PI * 10) * (1 - t) * 5f;
|
|
if (primaryWaveformImage.rectTransform != null)
|
|
{
|
|
primaryWaveformImage.rectTransform.localPosition = new Vector3(shake, 0, 0);
|
|
}
|
|
|
|
yield return null;
|
|
}
|
|
|
|
// 切换到目标波形
|
|
primaryWaveformImage.sprite = toData.waveformSprite;
|
|
primaryWaveformImage.color = toData.waveformColor;
|
|
if (primaryWaveformImage.rectTransform != null)
|
|
{
|
|
primaryWaveformImage.rectTransform.localPosition = Vector3.zero;
|
|
}
|
|
|
|
yield return new WaitForSeconds(duration * 0.2f);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 波形比对
|
|
|
|
/// <summary>
|
|
/// 波形比对显示
|
|
/// </summary>
|
|
public IEnumerator CompareWaveforms(string waveform1, string waveform2)
|
|
{
|
|
if (!_waveformDict.TryGetValue(waveform1, out var data1) ||
|
|
!_waveformDict.TryGetValue(waveform2, out var data2))
|
|
{
|
|
Debug.LogWarning($"WaveformDisplaySystem: 波形比对失败,未找到波形类型");
|
|
yield break;
|
|
}
|
|
|
|
primaryWaveformImage.sprite = data1.waveformSprite;
|
|
primaryWaveformImage.color = data1.waveformColor;
|
|
|
|
if (secondaryWaveformImage != null)
|
|
{
|
|
secondaryWaveformImage.gameObject.SetActive(true);
|
|
secondaryWaveformImage.sprite = data2.waveformSprite;
|
|
secondaryWaveformImage.color = data2.waveformColor;
|
|
}
|
|
|
|
if (waveformContainer != null)
|
|
{
|
|
waveformContainer.gameObject.SetActive(true);
|
|
}
|
|
|
|
yield return FadeWaveform(0f, 1f, 0.3f);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 步进进度
|
|
|
|
/// <summary>
|
|
/// 显示步进进度
|
|
/// </summary>
|
|
public void ShowStepProgress(int currentStep, int totalSteps)
|
|
{
|
|
if (stepProgressPanel != null)
|
|
{
|
|
stepProgressPanel.SetActive(true);
|
|
}
|
|
|
|
UpdateStepProgress(currentStep);
|
|
|
|
if (stepProgressSlider != null)
|
|
{
|
|
stepProgressSlider.maxValue = totalSteps;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新步进进度
|
|
/// </summary>
|
|
public void UpdateStepProgress(int currentStep)
|
|
{
|
|
if (stepProgressText != null)
|
|
{
|
|
stepProgressText.text = $"Step {currentStep}";
|
|
}
|
|
|
|
if (stepProgressSlider != null)
|
|
{
|
|
stepProgressSlider.value = currentStep;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 隐藏步进进度
|
|
/// </summary>
|
|
public void HideStepProgress()
|
|
{
|
|
if (stepProgressPanel != null)
|
|
{
|
|
stepProgressPanel.SetActive(false);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 报错效果
|
|
|
|
/// <summary>
|
|
/// 显示连续报错
|
|
/// </summary>
|
|
public IEnumerator ShowErrorFlood(string[] errorMessages, int count, float interval)
|
|
{
|
|
for (int i = 0; i < count && i < errorMessages.Length; i++)
|
|
{
|
|
SpawnError(errorMessages[i % errorMessages.Length]);
|
|
yield return new WaitForSeconds(interval);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成单个报错
|
|
/// </summary>
|
|
private void SpawnError(string message)
|
|
{
|
|
if (errorPrefab == null || errorContainer == null) return;
|
|
|
|
// 限制报错数量
|
|
while (_activeErrors.Count >= maxErrorCount)
|
|
{
|
|
var oldest = _activeErrors[0];
|
|
_activeErrors.RemoveAt(0);
|
|
Destroy(oldest);
|
|
}
|
|
|
|
var errorObj = Instantiate(errorPrefab, errorContainer);
|
|
var errorText = errorObj.GetComponentInChildren<Text>();
|
|
if (errorText != null)
|
|
{
|
|
errorText.text = message;
|
|
}
|
|
|
|
// 随机位置偏移
|
|
var rect = errorObj.GetComponent<RectTransform>();
|
|
if (rect != null)
|
|
{
|
|
rect.anchoredPosition = new Vector2(
|
|
Random.Range(-50f, 50f),
|
|
Random.Range(-30f, 30f)
|
|
);
|
|
}
|
|
|
|
_activeErrors.Add(errorObj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清除所有报错
|
|
/// </summary>
|
|
public void ClearErrors()
|
|
{
|
|
foreach (var error in _activeErrors)
|
|
{
|
|
if (error != null)
|
|
{
|
|
Destroy(error);
|
|
}
|
|
}
|
|
_activeErrors.Clear();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// 波形数据
|
|
/// </summary>
|
|
[System.Serializable]
|
|
public class WaveformData
|
|
{
|
|
[Tooltip("波形ID,用于在Yarn脚本中引用")]
|
|
public string waveformId;
|
|
|
|
[Tooltip("波形图像")]
|
|
public Sprite waveformSprite;
|
|
|
|
[Tooltip("波形颜色")]
|
|
public Color waveformColor = Color.cyan;
|
|
|
|
[Tooltip("波形描述")]
|
|
public string description;
|
|
}
|
|
}
|