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
);
}
}
}