using UnityEngine; using System.Collections.Generic; using Shapes; namespace AibisDream.MiniGame.Language { /// /// 连接线渲染器:使用Shapes绘制粒子间的连接线 /// 注意:sortingOrder 设置为 0,确保低于文字(文字 sortingOrder = 10) /// [ExecuteAlways] public class ConnectionRenderer : ImmediateModeShapeDrawer { [Header("引用")] public LanguageParticleManager manager; [Header("连接线设置")] public float connectionDistance = 2f; private Color nonTargetConnectionColor = new Color(0.39f, 0.78f, 1f, 0.7f); // 非目标粒子连线颜色 private Color targetConnectionColor = new Color(1f, 0.39f, 0.39f, 1f); // 目标粒子连线颜色 private float nonTargetLineThickness = 0.02f; private float targetLineThickness = 0.04f; [Header("效果传播设置")] private Color propagationColor = new Color(1f, 0.59f, 0.2f, 1f); private float propagationLineThickness = 0.03f; [Header("发光设置(Bloom)")] [SerializeField] private bool enableGlow = true; [SerializeField, Range(1f, 5f)] private float targetGlowIntensity = 2f; // 目标线发光强度 [SerializeField, Range(1f, 3f)] private float nonTargetGlowIntensity = 1.2f; // 非目标线发光强度 [SerializeField, Range(1f, 5f)] private float propagationGlowIntensity = 3f; // 传播效果发光强度 private List candidateParticles; private List effectPropagations; private CompletionPhase completionPhase; private float fadeOutAlpha; private float nonTargetAlphaScale = 1f; private float targetAlphaScale = 1f; public float NonTargetAlphaScale { get => nonTargetAlphaScale; set => nonTargetAlphaScale = Mathf.Clamp01(value); } public float TargetAlphaScale { get => targetAlphaScale; set => targetAlphaScale = Mathf.Clamp(value, 0f, 1.5f); } public void SetData( List candidates, List propagations, CompletionPhase phase, float fadeAlpha) { candidateParticles = candidates; effectPropagations = propagations; completionPhase = phase; fadeOutAlpha = fadeAlpha; } public override void DrawShapes(Camera cam) { if (candidateParticles == null || candidateParticles.Count == 0) return; using (Draw.Command(cam)) { Draw.BlendMode = ShapesBlendMode.Transparent; Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always; // 注意:连接线默认在底层,文字的 sortingOrder = 10 会显示在上层 // 绘制蓝色粒子间的连线 if (completionPhase == CompletionPhase.None || completionPhase == CompletionPhase.Completed) { DrawBlueConnections(); } // 绘制红色粒子间的连线 if (completionPhase == CompletionPhase.None || completionPhase == CompletionPhase.Completed || completionPhase == CompletionPhase.Focusing) { DrawRedConnections(); } // 绘制效果传播线 if (effectPropagations != null && effectPropagations.Count > 0) { DrawPropagationEffects(); } } } private void DrawBlueConnections() { Draw.LineGeometry = LineGeometry.Flat2D; Draw.Thickness = nonTargetLineThickness; for (int i = 0; i < candidateParticles.Count; i++) { for (int j = i + 1; j < candidateParticles.Count; j++) { var p1 = candidateParticles[i]; var p2 = candidateParticles[j]; // 跳过红色粒子 if (p1.isRed && p2.isRed) continue; float distance = Vector3.Distance(p1.transform.position, p2.transform.position); if (distance < connectionDistance) { float alpha = Mathf.Lerp(0.7f, 0f, distance / connectionDistance) * fadeOutAlpha; Color lineColor = ApplyGlow(nonTargetConnectionColor, nonTargetGlowIntensity); lineColor.a = alpha * nonTargetAlphaScale; Draw.Line(p1.transform.position, p2.transform.position, lineColor); } } } } private void DrawRedConnections() { Draw.LineGeometry = LineGeometry.Flat2D; Draw.Thickness = targetLineThickness; var redParticles = new List(); foreach (var p in candidateParticles) { if (p.isRed) redParticles.Add(p); } for (int i = 0; i < redParticles.Count; i++) { for (int j = i + 1; j < redParticles.Count; j++) { float distance = Vector3.Distance( redParticles[i].transform.position, redParticles[j].transform.position ); if (distance < connectionDistance) { float alpha = Mathf.Lerp(1f, 0.4f, distance / connectionDistance); Color lineColor = ApplyGlow(targetConnectionColor, targetGlowIntensity); lineColor.a = alpha * targetAlphaScale; Draw.Line(redParticles[i].transform.position, redParticles[j].transform.position, lineColor); } } } } private void DrawPropagationEffects() { Draw.LineGeometry = LineGeometry.Flat2D; Draw.Thickness = propagationLineThickness; foreach (var propagation in effectPropagations) { if (propagation.PropagatedParticles == null) continue; foreach (var info in propagation.PropagatedParticles) { if (info.source == null || info.particle == null) continue; // 绘制连接线(应用发光) Color lineColor = ApplyGlow(propagationColor, propagationGlowIntensity); lineColor.a = 0.3f; Draw.Line(info.source.transform.position, info.particle.transform.position, lineColor); // 绘制脉冲光点 if (info.pulseProgress < 1f) { Vector3 pulsePos = Vector3.Lerp( info.source.transform.position, info.particle.transform.position, info.pulseProgress ); float pulseSize = Mathf.Lerp(0.03f, 0.08f, info.pulseProgress); float pulseAlpha = Mathf.Lerp(1f, 0f, info.pulseProgress); // 脉冲光点使用更强的 HDR 发光 Color pulseColor = ApplyGlow(new Color(1f, 0.78f, 0.39f, pulseAlpha), propagationGlowIntensity * 1.5f); Draw.Ring(pulsePos, pulseSize, pulseSize * 0.5f, pulseColor); // 光晕 pulseColor.a = pulseAlpha * 0.5f; Draw.Disc(pulsePos, pulseSize * 1.5f, pulseColor); } // 绘制箭头 if (info.pulseProgress > 0.5f && info.pulseProgress < 1f) { Vector3 arrowPos = Vector3.Lerp( info.source.transform.position, info.particle.transform.position, 0.5f ); Vector3 direction = (info.particle.transform.position - info.source.transform.position).normalized; float angle = Mathf.Atan2(direction.y, direction.x); Color arrowColor = ApplyGlow(new Color(1f, 0.78f, 0.39f, 0.8f), propagationGlowIntensity); DrawArrow(arrowPos, angle, 0.1f, arrowColor); } } } } private void DrawArrow(Vector3 position, float angle, float size, Color color) { Vector3 tip = position + new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0) * size; Vector3 left = position + new Vector3( Mathf.Cos(angle + 2.5f), Mathf.Sin(angle + 2.5f), 0 ) * size * 0.5f; Vector3 right = position + new Vector3( Mathf.Cos(angle - 2.5f), Mathf.Sin(angle - 2.5f), 0 ) * size * 0.5f; Draw.Triangle(tip, left, right, color); } /// /// 设置连接线样式 /// public void SetConnectionStyles( Color targetColor, Color nonTargetColor, Color propColor, float targetThickness, float nonTargetThickness, float propThickness) { targetConnectionColor = targetColor; nonTargetConnectionColor = nonTargetColor; propagationColor = propColor; targetLineThickness = targetThickness; nonTargetLineThickness = nonTargetThickness; propagationLineThickness = propThickness; } /// /// 设置发光参数 /// public void SetGlowSettings(bool enabled, float targetIntensity, float nonTargetIntensity, float propagationIntensity) { enableGlow = enabled; targetGlowIntensity = Mathf.Clamp(targetIntensity, 1f, 5f); nonTargetGlowIntensity = Mathf.Clamp(nonTargetIntensity, 1f, 3f); propagationGlowIntensity = Mathf.Clamp(propagationIntensity, 1f, 5f); } /// /// 将颜色转换为 HDR 颜色以支持 Bloom 发光 /// private Color ApplyGlow(Color baseColor, float intensity) { if (!enableGlow || intensity <= 1f) return baseColor; // HDR 颜色:将 RGB 值乘以强度系数,保留 Alpha return new Color( baseColor.r * intensity, baseColor.g * intensity, baseColor.b * intensity, baseColor.a ); } } }