效果更新
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Shapes;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[ExecuteAlways]
|
||||
[RequireComponent(typeof(MeshCollider))]
|
||||
public class LakeLineDrawer : ImmediateModeShapeDrawer
|
||||
{
|
||||
[Header("场设置")]
|
||||
@@ -19,92 +18,122 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
|
||||
public float timeScale = 1f;
|
||||
|
||||
[Header("涟漪参数")]
|
||||
public float rippleStrength = 1.5f;
|
||||
public float rippleRadius = 2f;
|
||||
public float rippleDuration = 2f;
|
||||
public float rippleStrength = 2f;
|
||||
public float rippleDuration = 1.5f;
|
||||
public float rippleSpreadSpeed = 6f;
|
||||
public float rippleSharpness = 2f;
|
||||
public float rippleDelay = 0.25f; // ⏱️ 新增:扩散延迟(秒)
|
||||
|
||||
private Vector3[] points;
|
||||
private float time;
|
||||
|
||||
// 涟漪记录
|
||||
private List<Vector2> rippleCenters = new List<Vector2>();
|
||||
private List<float> rippleTimes = new List<float>();
|
||||
private struct Ripple
|
||||
{
|
||||
public Vector2 position;
|
||||
public float startTime;
|
||||
public float delay;
|
||||
}
|
||||
|
||||
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 localPos = transform.InverseTransformPoint(hit.point);
|
||||
rippleCenters.Add(new Vector2(localPos.x, localPos.z));
|
||||
rippleTimes.Add(time);
|
||||
Vector3 hitPos = hit.point;
|
||||
ripples.Add(new Ripple
|
||||
{
|
||||
position = new Vector2(hitPos.x, hitPos.z),
|
||||
startTime = Time.time,
|
||||
delay = rippleDelay
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 清除过时涟漪
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
for (int i = rippleCenters.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (time - rippleTimes[i] > rippleDuration)
|
||||
{
|
||||
rippleCenters.RemoveAt(i);
|
||||
rippleTimes.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
ripples.RemoveAll(r => Time.time - r.startTime > rippleDuration + rippleDelay);
|
||||
}
|
||||
|
||||
private float GetNoise(float x, float z, float t)
|
||||
private RippleResult GetRippleEffect(float x, float z, float currentTime)
|
||||
{
|
||||
float noise = 0f;
|
||||
float rippleOffset = 0f;
|
||||
float brightness = 0f;
|
||||
|
||||
foreach (var ripple in ripples)
|
||||
{
|
||||
float elapsed = currentTime - ripple.startTime;
|
||||
|
||||
if (elapsed < ripple.delay)
|
||||
{
|
||||
// 尖刺阶段,不扩散,只在中心显示尖刺
|
||||
float dist = Vector2.Distance(new Vector2(x, z), ripple.position);
|
||||
float spike = Mathf.Exp(-dist * rippleSharpness); // 尖锐程度
|
||||
float ease = Mathf.Sin((elapsed / ripple.delay) * Mathf.PI * 0.5f); // easeIn
|
||||
|
||||
rippleOffset += spike * rippleStrength * ease;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 扩散阶段
|
||||
float spreadElapsed = elapsed - ripple.delay;
|
||||
float spread = spreadElapsed * rippleSpreadSpeed;
|
||||
float dist2 = Vector2.Distance(new Vector2(x, z), ripple.position);
|
||||
float t = Mathf.Clamp01(spreadElapsed / rippleDuration);
|
||||
float ease2 = Mathf.Sin(t * Mathf.PI);
|
||||
|
||||
float spike2 = Mathf.Exp(-Mathf.Pow(dist2 - spread, 2f) * rippleSharpness);
|
||||
rippleOffset += spike2 * rippleStrength * ease2;
|
||||
|
||||
float bright = Mathf.Exp(-Mathf.Pow((dist2 - spread) * 0.5f, 2f));
|
||||
brightness += bright * ease2;
|
||||
}
|
||||
|
||||
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 = t * waveSpeed * freq;
|
||||
float nt = currentTime * waveSpeed * freq;
|
||||
noise += Mathf.PerlinNoise(nx + nt, nz + nt) * amp;
|
||||
amp *= 0.5f;
|
||||
freq *= 2f;
|
||||
}
|
||||
|
||||
float ripple = 0f;
|
||||
for (int i = 0; i < rippleCenters.Count; i++)
|
||||
{
|
||||
Vector2 center = rippleCenters[i];
|
||||
float rippleTime = t - rippleTimes[i];
|
||||
if (rippleTime > rippleDuration) continue;
|
||||
|
||||
float dist = Vector2.Distance(new Vector2(x, z), center);
|
||||
if (dist > rippleRadius) continue;
|
||||
|
||||
float nd = dist / rippleRadius;
|
||||
float rippleVal = Mathf.Sin((1f - nd) * Mathf.PI * 2f - rippleTime * 4f) * (1f - nd);
|
||||
ripple += rippleVal * rippleStrength * (1f - rippleTime / rippleDuration);
|
||||
}
|
||||
|
||||
return (noise + ripple) * waveHeight;
|
||||
return noise * waveHeight;
|
||||
}
|
||||
|
||||
public override void DrawShapes(Camera cam)
|
||||
{
|
||||
using (Draw.Command(cam))
|
||||
{
|
||||
time = Application.isPlaying ? Time.time * timeScale : 0f;
|
||||
|
||||
Draw.ResetAllDrawStates();
|
||||
Draw.LineGeometry = LineGeometry.Volumetric3D;
|
||||
Draw.Thickness = lineWidth;
|
||||
Draw.Color = Color.cyan;
|
||||
|
||||
float step = fieldSize / (pointCount - 1);
|
||||
float half = fieldSize * 0.5f;
|
||||
float halfSize = fieldSize * 0.5f;
|
||||
|
||||
if (points == null || points.Length != pointCount * pointCount)
|
||||
points = new Vector3[pointCount * pointCount];
|
||||
@@ -113,10 +142,26 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
|
||||
{
|
||||
for (int j = 0; j < pointCount; j++)
|
||||
{
|
||||
float x = -half + j * step;
|
||||
float z = -half + i * step;
|
||||
float y = GetNoise(x, z, time);
|
||||
points[i * pointCount + j] = new Vector3(x, y, z);
|
||||
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;
|
||||
|
||||
// float shake = ripple.brightnessBoost > 0.01f ? Mathf.Sin(Time.time * 30f + x + z) * 0.02f : 0f;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,12 +172,6 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
|
||||
int index = i * pointCount + j;
|
||||
Vector3 current = points[index];
|
||||
|
||||
float depth = (current.y + waveHeight) / (waveHeight * 2f);
|
||||
float scale = pointSize * (1f - depth * 0.5f);
|
||||
Color pointColor = Color.Lerp(new Color(0.5f, 1f, 1f), new Color(0f, 0.3f, 1f, 0.5f), depth);
|
||||
|
||||
Draw.Sphere(current, scale, pointColor);
|
||||
|
||||
if (j < pointCount - 1)
|
||||
{
|
||||
Vector3 next = points[index + 1];
|
||||
|
||||
Reference in New Issue
Block a user