Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/Emo/LakeLineDrawer.cs
T
2025-05-08 12:23:51 +08:00

180 lines
5.9 KiB
C#

using UnityEngine;
using Shapes;
using System.Collections.Generic;
[ExecuteAlways]
public class LakeLineDrawer : ImmediateModeShapeDrawer
{
[Header("场设置")]
public float fieldSize = 20f;
public int pointCount = 30;
public float pointSize = 0.15f;
public float lineWidth = 0.03f;
[Header("波动参数")]
public float noiseScale = 0.3f;
public float waveHeight = 1.5f;
public float waveSpeed = 1f;
public float timeScale = 1f;
[Header("涟漪参数")]
public float rippleStrength = 2f; // 尖刺强度
public float rippleDuration = 1.5f; // 持续时间
public float rippleSpreadSpeed = 6f; // 扩散速度
public float rippleSharpness = 2f; // 尖刺锐度
private Vector3[] points;
private float time;
private struct Ripple
{
public Vector2 position;
public float startTime;
}
private struct RippleResult
{
public float heightOffset;
public float brightnessBoost;
}
private List<Ripple> ripples = new List<Ripple>();
private void Update()
{
time = Application.isPlaying ? Time.time * timeScale : 0f;
if (Application.isPlaying && Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Vector3 hitPos = hit.point;
ripples.Add(new Ripple
{
position = new Vector2(hitPos.x, hitPos.z),
startTime = Time.time
});
}
}
ripples.RemoveAll(r => Time.time - r.startTime > rippleDuration);
}
private RippleResult GetRippleEffect(float x, float z, float currentTime)
{
float rippleOffset = 0f;
float brightness = 0f;
foreach (var ripple in ripples)
{
float elapsed = currentTime - ripple.startTime;
float spread = elapsed * rippleSpreadSpeed;
float dist = Vector2.Distance(new Vector2(x, z), ripple.position);
float t = Mathf.Clamp01(elapsed / rippleDuration);
float ease = Mathf.Sin(t * Mathf.PI);
float spike = Mathf.Exp(-Mathf.Pow(dist - spread, 2f) * rippleSharpness);
rippleOffset += spike * rippleStrength * ease;
float bright = Mathf.Exp(-Mathf.Pow((dist - spread) * 0.5f, 2f));
brightness += bright * ease;
}
return new RippleResult
{
heightOffset = rippleOffset,
brightnessBoost = brightness
};
}
private float GetHeight(float x, float z, float currentTime)
{
float noise = 0;
float amp = 1f;
float freq = 1f;
for (int i = 0; i < 3; i++)
{
float nx = x * freq * noiseScale;
float nz = z * freq * noiseScale;
float nt = currentTime * waveSpeed * freq;
noise += Mathf.PerlinNoise(nx + nt, nz + nt) * amp;
amp *= 0.5f;
freq *= 2f;
}
return noise * waveHeight;
}
public override void DrawShapes(Camera cam)
{
using (Draw.Command(cam))
{
Draw.ResetAllDrawStates();
Draw.LineGeometry = LineGeometry.Volumetric3D;
Draw.Thickness = lineWidth;
float step = fieldSize / (pointCount - 1);
float halfSize = fieldSize * 0.5f;
if (points == null || points.Length != pointCount * pointCount)
points = new Vector3[pointCount * pointCount];
for (int i = 0; i < pointCount; i++)
{
for (int j = 0; j < pointCount; j++)
{
float x = -halfSize + j * step;
float z = -halfSize + i * step;
float baseHeight = GetHeight(x, z, time);
RippleResult ripple = GetRippleEffect(x, z, Time.time);
float finalY = baseHeight + ripple.heightOffset;
Vector3 pos = new Vector3(x, finalY, z);
points[i * pointCount + j] = pos;
float depth = (finalY + waveHeight) / (waveHeight * 2f);
float brightness = Mathf.Clamp01(1f + ripple.brightnessBoost);
float pointScale = pointSize * (1f - depth * 0.5f);
Color baseColor = Color.Lerp(new Color(0.5f, 1f, 1f), new Color(0f, 0.5f, 1f), depth);
baseColor *= brightness;
Draw.Sphere(pos, pointScale, baseColor);
}
}
for (int i = 0; i < pointCount; i++)
{
for (int j = 0; j < pointCount; j++)
{
int index = i * pointCount + j;
Vector3 current = points[index];
if (j < pointCount - 1)
{
Vector3 next = points[index + 1];
float avgY = (current.y + next.y) * 0.5f;
float lineDepth = (avgY + waveHeight) / (waveHeight * 2f);
Color lineColor = Color.Lerp(Color.cyan, new Color(0, 0.5f, 1f, 0.3f), lineDepth);
Draw.Line(current, next, lineWidth * (1f - lineDepth * 0.5f), lineColor);
}
if (i < pointCount - 1)
{
Vector3 next = points[index + pointCount];
float avgY = (current.y + next.y) * 0.5f;
float lineDepth = (avgY + waveHeight) / (waveHeight * 2f);
Color lineColor = Color.Lerp(Color.cyan, new Color(0, 0.5f, 1f, 0.3f), lineDepth);
Draw.Line(current, next, lineWidth * (1f - lineDepth * 0.5f), lineColor);
}
}
}
}
}
}