using UnityEngine; using System.Collections.Generic; using Shapes; namespace AibisDream.MiniGame.Language { /// /// 波形渲染器:使用Shapes绘制波形和交互效果 /// 注意:渲染在底层,确保低于文字(文字 sortingOrder = 10) /// [ExecuteAlways] public class WaveformRenderer : ImmediateModeShapeDrawer { [Header("波形设置")] public Color normalWaveColor = new Color(0.59f, 0.78f, 1f, 0.8f); public Color anxiousWaveColor = new Color(1f, 0.39f, 0.39f, 0.8f); public float waveLineThickness = 0.04f; public float baseY = 0f; [Header("交互设置")] public Color interactionColor = new Color(0.59f, 0.78f, 1f, 0.3f); public Color interactionRingColor = new Color(0.59f, 0.78f, 1f, 0.6f); public float interactionRadius = 0.5f; [Header("粒子效果")] public Color particleColor = new Color(0.59f, 0.78f, 1f, 0.8f); private List waveformPoints; private CompletionPhase completionPhase; private float calmProgress; private Vector2 mouseWorldPos; private bool mousePressed; private float mouseDragSpeed; private List waveParticles = new List(); public void SetData( List points, CompletionPhase phase, float calm, Vector2 mousePos, bool mouseDown, float dragSpeed) { waveformPoints = points; completionPhase = phase; calmProgress = calm; mouseWorldPos = mousePos; mousePressed = mouseDown; mouseDragSpeed = dragSpeed; } private void Update() { // 更新粒子效果 for (int i = waveParticles.Count - 1; i >= 0; i--) { waveParticles[i].Update(Time.deltaTime); if (waveParticles[i].alpha <= 0 || waveParticles[i].size < 0.01f) { waveParticles.RemoveAt(i); } } // 生成新粒子(如果正在交互) if (mousePressed && waveformPoints != null && Random.value > 0.7f) { foreach (var point in waveformPoints) { if (point.isBeingCalmed && Random.value > 0.5f) { waveParticles.Add(new WaveformParticleEffect( new Vector3(point.x, point.smoothedY, 0), Random.Range(-0.1f, 0.1f), Random.Range(-0.2f, -0.05f), Random.Range(0.02f, 0.04f) )); } } } } public override void DrawShapes(Camera cam) { if (waveformPoints == null || waveformPoints.Count == 0) return; if (completionPhase != CompletionPhase.Focusing) return; using (Draw.Command(cam)) { Draw.BlendMode = ShapesBlendMode.Transparent; Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always; // 注意:波形默认在底层,文字的 sortingOrder = 10 会显示在上层 // 绘制粒子效果 DrawWaveformParticles(); // 绘制波形线 DrawWaveformLine(); // 绘制波形点 DrawWaveformPoints(); // 绘制交互反馈 if (mousePressed) { DrawInteractionFeedback(); } // 绘制基准线 if (calmProgress < 0.9f) { DrawBaseline(); } } } private void DrawWaveformParticles() { foreach (var particle in waveParticles) { Color color = particleColor; color.a = particle.alpha; Draw.Disc(particle.position, particle.size, color); // 光晕 color.a = particle.alpha * 0.3f; Draw.Disc(particle.position, particle.size * 2f, color); } } private void DrawWaveformLine() { Draw.LineGeometry = LineGeometry.Flat2D; Draw.Thickness = waveLineThickness; // 使用Polyline绘制波形 var points = new List(); var colors = new List(); foreach (var point in waveformPoints) { // 跳过完全消散的点 float dissolveProgress = point.particle != null ? point.particle.dissolveProgress : 0f; if (dissolveProgress >= 1f) continue; points.Add(new Vector3(point.x, point.smoothedY, 0)); // 根据抚平程度混合颜色 Color waveColor = Color.Lerp(anxiousWaveColor, normalWaveColor, point.calmAmount); waveColor.a *= (1 - dissolveProgress); colors.Add(waveColor); } if (points.Count >= 2) { for (int i = 0; i < points.Count - 1; i++) { Draw.Line(points[i], points[i + 1], colors[i], colors[i + 1]); } } } private void DrawWaveformPoints() { for (int i = 0; i < waveformPoints.Count; i += 3) { var point = waveformPoints[i]; // 跳过完全消散的点 float dissolveProgress = point.particle != null ? point.particle.dissolveProgress : 0f; if (dissolveProgress >= 1f) continue; Vector3 pos = new Vector3(point.x, point.smoothedY, 0); // 如果正在被抚平,显示进度环 if (point.isBeingCalmed && point.calmTimer > 0) { float requiredTime = 0.5f + point.resistance * 1f; float progress = Mathf.Min(1f, point.calmTimer / requiredTime); Color ringColor = interactionRingColor; ringColor.a *= (1 - dissolveProgress); Draw.Ring(pos, 0.08f, 0.06f, ringColor); Draw.Arc(pos, 0.08f, 0.02f, -Mathf.PI / 2f, progress * Mathf.PI * 2f, ringColor); } // 绘制波形点 float pointAlpha = (1 - point.calmAmount) * (1 - calmProgress * 0.5f) * (1 - dissolveProgress) * 0.6f; if (pointAlpha > 0.05f) { Color pointColor = Color.Lerp(anxiousWaveColor, normalWaveColor, point.calmAmount); pointColor.a = pointAlpha; Draw.Disc(pos, 0.03f, pointColor); } } } private void DrawInteractionFeedback() { Vector3 mousePos3D = new Vector3(mouseWorldPos.x, mouseWorldPos.y, 0); // 内圈(交互范围) Color innerColor = interactionColor; Draw.Disc(mousePos3D, interactionRadius, innerColor); // 外圈(视觉反馈) Color outerColor = interactionRingColor; Draw.Ring(mousePos3D, interactionRadius, interactionRadius * 0.95f, outerColor); // 根据拖动速度显示额外反馈 if (mouseDragSpeed > 0.1f) { Color speedColor = interactionRingColor; speedColor.a = 0.4f; Draw.Ring(mousePos3D, interactionRadius * 1.25f, interactionRadius * 1.2f, speedColor); } } private void DrawBaseline() { float alpha = 0.2f * (1 - calmProgress); Color baselineColor = normalWaveColor; baselineColor.a = alpha; Draw.LineGeometry = LineGeometry.Flat2D; Draw.Thickness = 0.015f; // 计算波形范围 if (waveformPoints.Count > 0) { float minX = waveformPoints[0].x; float maxX = waveformPoints[waveformPoints.Count - 1].x; Draw.Line(new Vector3(minX - 0.5f, baseY, 0), new Vector3(maxX + 0.5f, baseY, 0), baselineColor); } } private class WaveformParticleEffect { public Vector3 position; public float vx; public float vy; public float alpha; public float size; public WaveformParticleEffect(Vector3 pos, float velocityX, float velocityY, float initialSize) { position = pos; vx = velocityX; vy = velocityY; alpha = 0.8f; size = initialSize; } public void Update(float deltaTime) { position.x += vx * deltaTime; position.y += vy * deltaTime; vy += 0.1f * deltaTime; // 重力 alpha -= 0.015f; size *= 0.98f; } } } }