283 lines
11 KiB
C#
283 lines
11 KiB
C#
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
using Shapes;
|
||
|
||
namespace AibisDream.MiniGame.Language
|
||
{
|
||
/// <summary>
|
||
/// 连接线渲染器:使用Shapes绘制粒子间的连接线
|
||
/// 注意:sortingOrder 设置为 0,确保低于文字(文字 sortingOrder = 10)
|
||
/// </summary>
|
||
[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<CandidateParticle> candidateParticles;
|
||
private List<EffectPropagation> 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<CandidateParticle> candidates,
|
||
List<EffectPropagation> 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<CandidateParticle>();
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置连接线样式
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置发光参数
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将颜色转换为 HDR 颜色以支持 Bloom 发光
|
||
/// </summary>
|
||
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
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|