using UnityEngine; namespace AibisDream.MiniGame.Language { /// /// 波形点:管理单个波形点的状态和动画 /// public class WaveformPoint { // 位置 public float x; // X坐标(跟随文字) public float y; // 当前Y坐标 public float targetY; // 目标Y坐标(规律波形) public float smoothedY; // 平滑后的Y坐标 // 噪声参数 public float noiseOffset; // 噪声偏移 public float noiseScale1; // 噪声缩放1(低频) public float noiseScale2; // 噪声缩放2(中频) public float noiseScale3; // 噪声缩放3(高频) public float noiseAmplitude; // 噪声振幅 public float noiseTime; // 噪声时间偏移 // 抚平状态 public float resistance; // 抵抗力(0-1,越高越难抚平) public float calmAmount; // 当前被抚平的程度(0-1) public bool isBeingCalmed; // 是否正在被抚平 public float calmTimer; // 抚平计时器 // 关联 public CandidateParticle particle; // 关联的文字粒子 public int particleIndex; // 粒子索引 // 脉冲动画 public float pulseProgress; // 脉冲进度(0-1) public WaveformPoint(float x, float baseY, float amplitude, int index, CandidateParticle particle) { this.x = x; this.particle = particle; this.particleIndex = index; // 初始化噪声参数 noiseScale1 = 0.05f; noiseScale2 = 0.15f; noiseScale3 = 0.4f; noiseAmplitude = Random.Range(0.7f, 1f); noiseOffset = Random.Range(-0.2f, 0.2f); noiseTime = Random.Range(0f, 1000f); // 计算初始Y(噪波) float combinedNoise = GenerateNoise(Time.time); y = baseY + combinedNoise * amplitude; smoothedY = y; // 计算目标Y(规律波形) float targetWavePhase = index * 0.3f; float targetWaveAmplitude = amplitude * 0.3f; targetY = baseY + Mathf.Sin(targetWavePhase) * targetWaveAmplitude; // 计算异常程度和抵抗力 float anomalyAmount = Mathf.Abs(y - targetY) / amplitude; resistance = 0.1f + anomalyAmount * 0.25f; calmAmount = 0f; isBeingCalmed = false; calmTimer = 0f; pulseProgress = 0f; } /// /// 生成多层Perlin噪声 /// private float GenerateNoise(float time) { // 使用多层噪声叠加 float noiseValue1 = Mathf.PerlinNoise(x * noiseScale1, time * 0.01f); float noiseValue2 = Mathf.PerlinNoise(x * noiseScale2, time * 0.02f + 100f); float noiseValue3 = Mathf.PerlinNoise(x * noiseScale3, time * 0.03f + 200f); // 映射到[-1, 1]范围 noiseValue1 = (noiseValue1 - 0.5f) * 2f; noiseValue2 = (noiseValue2 - 0.5f) * 2f * 0.6f; noiseValue3 = (noiseValue3 - 0.5f) * 2f * 0.3f; // 叠加 float combinedNoise = noiseValue1 + noiseValue2 + noiseValue3 + noiseOffset; return Mathf.Clamp(combinedNoise * noiseAmplitude, -1.5f, 1.5f); } /// /// 更新波形点(动态噪波、交互、抚平) /// public void Update(float baseY, float amplitude, Vector2 mousePos, bool mousePressed, float mouseDragSpeed, float interactionRadius) { // 同步X位置(跟随文字) if (particle != null) { x = particle.transform.position.x; // 更新目标位置 float targetWavePhase = particleIndex * 0.3f; float targetWaveAmplitude = amplitude * 0.3f; targetY = baseY + Mathf.Sin(targetWavePhase) * targetWaveAmplitude; } // 重置状态 isBeingCalmed = false; // 如果未抚平,添加动态噪波 if (calmAmount < 0.9f) { float currentTime = Time.time + noiseTime * 0.001f; float dynamicNoise = GenerateNoise(currentTime); // 根据抚平程度减少噪波强度 float noiseIntensity = (1 - calmAmount) * amplitude; smoothedY = y + dynamicNoise * noiseIntensity; } // 处理鼠标交互 if (mousePressed) { float distToMouse = Vector2.Distance(mousePos, new Vector2(x, smoothedY)); if (distToMouse < interactionRadius) { // 计算影响强度 float distanceInfluence = Mathf.Lerp(1f, 0f, distToMouse / interactionRadius); float speedBonus = Mathf.Min(1f, mouseDragSpeed / 0.25f); // 拖动速度加成 float influence = distanceInfluence * (0.5f + speedBonus * 0.5f); // 标记为正在被抚平 isBeingCalmed = true; calmTimer += Time.deltaTime; // 需要持续按住才能抚平(抵抗机制) float requiredTime = 0.5f + resistance * 1f; // 需要0.5-1.5秒 float calmProgressLocal = Mathf.Min(1f, calmTimer / requiredTime); // 应用抚平效果(考虑抵抗力) float calmStrength = influence * (1 - resistance) * 0.15f; // 计算目标位置(从噪波位置向规律波形位置过渡) float targetYLerp = Mathf.Lerp(y, targetY, calmProgressLocal); smoothedY = Mathf.Lerp(smoothedY, targetYLerp, calmStrength); // 更新抚平程度(一旦抚平,就不会恢复) if (calmProgressLocal > calmAmount) { calmAmount = calmProgressLocal; } // 如果完全抚平 if (calmAmount >= 0.95f) { calmAmount = 1f; smoothedY = targetY; } } } // 如果calmAmount接近1,强制向目标位置靠拢 if (calmAmount > 0.8f) { float forceStrength = Mathf.Lerp(0.1f, 0.5f, (calmAmount - 0.8f) / 0.2f); smoothedY = Mathf.Lerp(smoothedY, targetY, forceStrength); } // 如果完全抚平,直接设置为目标位置 if (calmAmount >= 1f) { smoothedY = targetY; } // 限制波形点不会完全超出范围 float maxDeviation = amplitude * (1 - calmAmount * 0.8f); smoothedY = Mathf.Clamp(smoothedY, baseY - maxDeviation, baseY + maxDeviation); // 同步更新对应文字粒子的平静进度 if (particle != null) { particle.calmProgress = calmAmount; // 如果完全抚平,标记为已稳定 if (calmAmount >= 0.95f && !particle.isCalmed) { particle.isCalmed = true; particle.isStatic = true; particle.changeSpeedMultiplier = 0; particle.dissolveProgress = 0; } // 如果已抚平,检查波形是否完全稳定 if (particle.isCalmed) { float distanceToTarget = Mathf.Abs(smoothedY - targetY); float stabilityThreshold = amplitude * 0.05f; if (distanceToTarget < stabilityThreshold) { // 波形已稳定,开始消散 float dissolveSpeed = 0.02f + (calmAmount - 0.95f) * 0.15f; particle.dissolveProgress = Mathf.Min(1f, particle.dissolveProgress + dissolveSpeed * Time.deltaTime * 50f); } } } } } }