中间版本存档

This commit is contained in:
2025-05-08 16:17:49 +08:00
parent d3d400d75b
commit 552955f3d4
19 changed files with 1401 additions and 635 deletions
@@ -0,0 +1,59 @@
using UnityEngine;
using System.Collections.Generic;
using Shapes;
public class GridGenerator
{
private float fieldSize;
private int pointCount;
private float pointSize;
private float lineWidth;
private float edgeLineLength;
public GridGenerator(float fieldSize, int pointCount, float pointSize, float lineWidth, float edgeLineLength)
{
this.fieldSize = fieldSize;
this.pointCount = pointCount;
this.pointSize = pointSize;
this.lineWidth = lineWidth;
this.edgeLineLength = edgeLineLength;
}
public List<Vector3> GenerateGridPoints()
{
List<Vector3> points = new List<Vector3>();
float step = fieldSize / (pointCount - 1);
float halfSize = fieldSize / 2f;
for (int i = 0; i < pointCount; i++)
{
for (int j = 0; j < pointCount; j++)
{
float x = j * step - halfSize;
float z = i * step - halfSize;
points.Add(new Vector3(x, 0f, z));
}
}
return points;
}
public void DrawGridPoint(Vector3 position, float size, Color color)
{
Draw.Sphere(position, size, color);
}
public void DrawGridLine(Vector3 start, Vector3 end, float width, Color color)
{
Draw.Line(start, end, width, color);
}
public void DrawEdgeLine(Vector3 start, Vector3 end, float width, Color color)
{
Vector3 direction = (end - start).normalized;
Vector3 normal = Vector3.Cross(direction, Vector3.up).normalized;
Vector3 offset = normal * edgeLineLength;
Draw.Line(start + offset, end + offset, width, color);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 98172966e69290c4d9bd44ac3ee8b2d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,30 +1,77 @@
using UnityEngine;
using Shapes;
using System.Collections.Generic;
using UnityEngine.UI;
[ExecuteAlways]
public class LakeLineDrawer : ImmediateModeShapeDrawer
{
[Header("场设置")]
public float fieldSize = 20f;
public int pointCount = 30;
public float pointSize = 0.15f;
public float fieldSize = 80f;
public Vector2 fieldOffset = Vector2.zero;
public int pointCount = 80;
public float pointSize = 0.1f;
public float lineWidth = 0.03f;
[Header("波动参数")]
[Header("颜色设置")]
public Color lakeDarkColor = new Color(0f, 0.5f, 1f); // 湖面低处颜色
public Color lakeLightColor = new Color(0.5f, 1f, 1f, 0.3f); // 湖面高处颜色
public Color edgeDarkColor = new Color(0f, 0.5f, 1f); // 边缘低处颜色
public Color edgeLightColor = new Color(0.5f, 1f, 1f, 0.3f); // 边缘高处颜色
public float edgeLineLength = 1f; // 边缘线的长度
[Header("UI控制")]
public Slider xOffsetSlider;
public Slider zOffsetSlider;
public float maxOffset = 20f;
[Header("目标点设置")]
public List<TargetPoint> targetPoints = new List<TargetPoint>();
public float targetSize = 0.5f;
public float rotationSpeed = 30f; // 旋转速度(度/秒)
public float floatAmplitude = 0.2f; // 起伏幅度
public float floatFrequency = 2f; // 起伏频率
public float targetLineWidth = 0.02f; // 目标点线框的宽度
public float targetHeightOffset = 0.5f; // 目标点距离湖面的高度偏移
public Color targetFillColor = Color.red; // 目标点实体颜色
public Color targetWireColor = Color.white; // 目标点线框颜色
public float wireScale = 1.05f; // 线框相对于实体的大小比例
[Header("可视区域")]
public float visibleAreaSize = 20f;
// 波动参数,用于生成波动效果
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; // 尖刺锐度
public float rippleStrength = 2f; // 恢复原来的强度
public float rippleDuration = 0.8f; // 适中的持续时间
public float rippleSpreadSpeed = 4f; // 适中的传播速度
public float rippleSharpness = 4f; // 适中的锐度
public float rippleMaxRadius = 3f; // 新增:涟漪最大半径
private Vector3[] points;
// 存储每个点是否在可视区域内的标记
private bool[] validPoints;
private float time;
private List<Ripple> ripples = new List<Ripple>();
[System.Serializable]
public class TargetPoint
{
public Vector2 gridPosition; // 网格位置(0到pointCount-1
public TargetType type;
public Color color = Color.white;
}
public enum TargetType
{
Sphere,
Cube,
Torus
}
private struct Ripple
{
@@ -38,18 +85,38 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
public float brightnessBoost;
}
private List<Ripple> ripples = new List<Ripple>();
private void Update()
{
// 如果是播放状态,则更新时间;否则设为0
time = Application.isPlaying ? Time.time * timeScale : 0f;
HandleMouseInput();
HandleUIInput();
CleanExpiredRipples();
}
private void HandleUIInput()
{
if (xOffsetSlider != null && zOffsetSlider != null)
{
fieldOffset = new Vector2(
xOffsetSlider.value * maxOffset,
zOffsetSlider.value * maxOffset
);
}
}
// 处理鼠标点击,触发新的涟漪
private void HandleMouseInput()
{
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),
@@ -57,57 +124,74 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
});
}
}
}
private void CleanExpiredRipples()
{
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 spread = elapsed * rippleSpreadSpeed; // 涟漪扩展的距离
float dist = Vector2.Distance(new Vector2(x, z), ripple.position); // 当前点与涟漪中心的距离
// 如果距离超过最大半径,跳过这个涟漪的影响
if (dist > rippleMaxRadius)
continue;
// 计算涟漪的时间影响,t表示涟漪的衰减程度
float t = Mathf.Clamp01(elapsed / rippleDuration);
float ease = Mathf.Sin(t * Mathf.PI);
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
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;
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))
@@ -117,63 +201,246 @@ public class LakeLineDrawer : ImmediateModeShapeDrawer
Draw.Thickness = lineWidth;
float step = fieldSize / (pointCount - 1);
float halfSize = fieldSize * 0.5f;
float halfField = fieldSize * 0.5f;
float halfVisible = visibleAreaSize * 0.5f;
if (points == null || points.Length != pointCount * pointCount)
points = new Vector3[pointCount * pointCount];
if (validPoints == null || validPoints.Length != pointCount * pointCount)
validPoints = new bool[pointCount * pointCount];
for (int i = 0; i < pointCount; i++)
CalculatePointPositions(step, halfField, halfVisible);
DrawPointsAndLines(step, halfField, halfVisible);
DrawEdgeLines(halfField, halfVisible);
DrawTargetPoints(); // 添加目标点的绘制
}
}
// 计算每个点的位置和涟漪效果
private void CalculatePointPositions(float step, float halfField, float halfVisible)
{
// 遍历每个点,计算其位置和涟漪影响
for (int i = 0; i < pointCount; i++)
{
for (int j = 0; j < pointCount; j++)
{
for (int j = 0; j < pointCount; j++)
{
float x = -halfSize + j * step;
float z = -halfSize + i * step;
// 计算当前点的位置(xz
float x = -halfField + j * step + fieldOffset.x;
float z = -halfField + i * step + fieldOffset.y;
float baseHeight = GetHeight(x, z, time);
RippleResult ripple = GetRippleEffect(x, z, Time.time);
float finalY = baseHeight + ripple.heightOffset;
// 判断该点是否在可视区域内
bool inside = Mathf.Abs(x) <= halfVisible && Mathf.Abs(z) <= halfVisible;
int index = i * pointCount + j; // 计算当前点的索引
validPoints[index] = inside; // 设置该点是否有效
Vector3 pos = new Vector3(x, finalY, z);
if (!inside)
continue;
points[i * pointCount + j] = pos;
// 获取基础波浪高度,并计算涟漪影响
float baseHeight = GetHeight(x, z, time);
RippleResult ripple = GetRippleEffect(x, z, Time.time);
float finalY = baseHeight + ripple.heightOffset;
float depth = (finalY + waveHeight) / (waveHeight * 2f);
float brightness = Mathf.Clamp01(1f + ripple.brightnessBoost);
float pointScale = pointSize * (1f - depth * 0.5f);
// 创建点的坐标
Vector3 pos = new Vector3(x, finalY, z);
points[index] = pos; // 存储计算得到的点
Color baseColor = Color.Lerp(new Color(0.5f, 1f, 1f), new Color(0f, 0.5f, 1f), depth);
baseColor *= brightness;
// 计算亮度:基于高度,越高越亮
float heightT = Mathf.InverseLerp(-waveHeight, waveHeight, finalY);
float brightness = Mathf.Clamp01(1f + ripple.brightnessBoost); // 计算亮度,防止超出范围
Color baseColor = Color.Lerp(lakeDarkColor, lakeLightColor, heightT);
baseColor *= brightness;
Draw.Sphere(pos, pointScale, baseColor);
}
// 绘制当前点
Draw.Sphere(pos, pointSize * (1f - heightT * 0.5f), baseColor);
}
}
}
for (int i = 0; i < pointCount; i++)
// 绘制点与点之间的连线
private void DrawPointsAndLines(float step, float halfField, float halfVisible)
{
for (int i = 0; i < pointCount; i++)
{
for (int j = 0; j < pointCount; j++)
{
for (int j = 0; j < pointCount; j++)
int index = i * pointCount + j;
if (!validPoints[index])
continue;
Vector3 current = points[index];
if (j < pointCount - 1 && validPoints[index + 1])
{
int index = i * pointCount + j;
Vector3 current = points[index];
Vector3 next = points[index + 1];
DrawLineBetweenPoints(current, next, halfField, halfVisible);
}
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);
}
// 绘制与下边点的连线
if (i < pointCount - 1 && validPoints[index + pointCount])
{
Vector3 next = points[index + pointCount];
DrawLineBetweenPoints(current, next, halfField, halfVisible);
}
}
}
}
// 绘制两点之间的连线,加入深度和颜色的渐变
private void DrawLineBetweenPoints(Vector3 current, Vector3 next, float halfField, float halfVisible)
{
// 计算连线的平均高度
float avgY = (current.y + next.y) * 0.5f;
float heightT = Mathf.InverseLerp(-waveHeight, waveHeight, avgY);
// 计算连线的颜色,依赖于高度
Color lineColor = Color.Lerp(lakeDarkColor, lakeLightColor, heightT);
lineColor.a *= 0.8f; // 设置透明度
// 绘制连线
Draw.Line(current, next, lineWidth * (1f - heightT * 0.5f), lineColor);
}
private void DrawEdgeLine(float x, float z, float halfVisible)
{
// 检查点是否在可视区域内
if (Mathf.Abs(x) > halfVisible || Mathf.Abs(z) > halfVisible)
{
return;
}
// 计算湖面高度作为起始点的Y坐标
float startY = GetHeight(x, z, time); // 获取湖面高度
// 设置边缘线的起始点
Vector3 start = new Vector3(x, startY, z);
// 设置边缘线的终止点,向下延伸一定的长度
Vector3 end = new Vector3(x, startY - edgeLineLength, z); // 向下延伸的线条
// 设置颜色,基于高度
float heightT = Mathf.InverseLerp(-waveHeight, waveHeight, startY);
Color lineColor = Color.Lerp(edgeDarkColor, edgeLightColor, heightT);
lineColor.a *= 0.8f; // 设置透明度
// 绘制边缘线
Draw.Line(start, end, lineWidth * 0.5f, lineColor);
}
private void DrawEdgeLines(float halfField, float halfVisible)
{
// 绘制湖面边缘的向下线条(无扰动)
float step = fieldSize / (pointCount - 1);
float halfEdgeLineLength = edgeLineLength * 0.5f; // 设置边缘线长度
// 只在field边界处绘制线条,且仅当边界在可视区域内时绘制
// 1. 绘制 X 轴的边缘线(左边和右边)
for (float z = -halfField; z <= halfField; z += step)
{
// 检查边界点是否在可视区域内
if (Mathf.Abs(z) <= halfVisible)
{
float x = halfField; // 右边
DrawEdgeLine(x, z, halfVisible);
x = -halfField; // 左边
DrawEdgeLine(x, z, halfVisible);
}
}
// 2. 绘制 Z 轴的边缘线(上边和下边)
for (float x = -halfField; x <= halfField; x += step)
{
// 检查边界点是否在可视区域内
if (Mathf.Abs(x) <= halfVisible)
{
float z = halfField; // 上边
DrawEdgeLine(x, z, halfVisible);
z = -halfField; // 下边
DrawEdgeLine(x, z, halfVisible);
}
}
}
// 绘制目标点
private void DrawTargetPoints()
{
float step = fieldSize / (pointCount - 1);
float halfField = fieldSize * 0.5f;
float halfVisible = visibleAreaSize * 0.5f;
foreach (var target in targetPoints)
{
// 将网格位置转换为世界坐标
float x = -halfField + target.gridPosition.x * step + fieldOffset.x;
float z = -halfField + target.gridPosition.y * step + fieldOffset.y;
// 检查是否在可视区域内
if (Mathf.Abs(x) > halfVisible || Mathf.Abs(z) > halfVisible)
{
continue;
}
// 获取该点的高度
float height = GetHeight(x, z, time);
// 添加额外的起伏效果和高度偏移
float floatOffset = Mathf.Sin(time * floatFrequency) * floatAmplitude;
Vector3 position = new Vector3(x, height + floatOffset + targetHeightOffset, z);
// 计算旋转
float rotation = time * rotationSpeed;
Quaternion rot = Quaternion.Euler(0, rotation, 0);
// 绘制外层立方体线框
DrawWireCube(position, rot, targetSize * wireScale, targetWireColor);
// 根据类型绘制内部形状
switch (target.type)
{
case TargetType.Sphere:
Draw.Sphere(position, targetSize * 0.8f, targetFillColor);
break;
case TargetType.Cube:
Draw.Cube(position, rot, targetSize * 0.8f, targetFillColor);
break;
case TargetType.Torus:
Draw.Torus(position, rot, targetSize * 0.8f, targetSize * 0.3f, targetFillColor);
break;
}
}
}
private void DrawWireCube(Vector3 position, Quaternion rotation, float size, Color color)
{
Vector3[] vertices = new Vector3[]
{
new Vector3(-size, -size, -size),
new Vector3(size, -size, -size),
new Vector3(size, size, -size),
new Vector3(-size, size, -size),
new Vector3(-size, -size, size),
new Vector3(size, -size, size),
new Vector3(size, size, size),
new Vector3(-size, size, size)
};
// 应用旋转
for (int i = 0; i < vertices.Length; i++)
{
vertices[i] = rotation * vertices[i] + position;
}
// 绘制边
int[] edges = new int[]
{
0,1, 1,2, 2,3, 3,0, // 底面
4,5, 5,6, 6,7, 7,4, // 顶面
0,4, 1,5, 2,6, 3,7 // 连接线
};
for (int i = 0; i < edges.Length; i += 2)
{
Draw.Line(vertices[edges[i]], vertices[edges[i+1]], targetLineWidth, color);
}
}
}
@@ -0,0 +1,29 @@
using UnityEngine;
using UnityEngine.UI;
using Shapes;
public class LakeUIController : MonoBehaviour
{
[SerializeField] private LakeLineDrawer lakeDrawer;
public Slider xOffsetSlider;
public Slider zOffsetSlider;
private void Start()
{
// 设置滑动条的初始值
if (xOffsetSlider != null && zOffsetSlider != null)
{
xOffsetSlider.minValue = -1f;
xOffsetSlider.maxValue = 1f;
xOffsetSlider.value = 0f;
zOffsetSlider.minValue = -1f;
zOffsetSlider.maxValue = 1f;
zOffsetSlider.value = 0f;
// 将滑动条引用传递给LakeLineDrawer
lakeDrawer.xOffsetSlider = xOffsetSlider;
lakeDrawer.zOffsetSlider = zOffsetSlider;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6709e527ba5cd1a43802e44a9de467d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,195 @@
using UnityEngine;
using Shapes;
using System.Collections.Generic;
[ExecuteAlways]
public class LakeVisualizer : 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;
[Header("目标设置")]
public Vector2 targetPosition = Vector2.zero;
public float shapeChangeRadius = 4f; // 控制形状混合的范围
private Vector3[] points;
private float time;
private struct Ripple
{
public Vector2 position;
public float startTime;
}
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))
{
ripples.Add(new Ripple
{
position = new Vector2(hit.point.x, hit.point.z),
startTime = Time.time
});
}
}
ripples.RemoveAll(r => Time.time - r.startTime > rippleDuration);
}
private float GetNoiseHeight(float x, float z, float currentTime)
{
float noise = 0f;
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;
Vector2 pos2D = new Vector2(x, z);
float baseY = GetNoiseHeight(x, z, time);
float rippleY = 0f;
float brightness = 0f;
float shapeBlend = 0f;
foreach (var ripple in ripples)
{
float elapsed = Time.time - ripple.startTime;
float spread = elapsed * rippleSpreadSpeed;
float dist = Vector2.Distance(pos2D, ripple.position);
float ease = Mathf.Sin(Mathf.Clamp01(elapsed / rippleDuration) * Mathf.PI);
float spike = Mathf.Exp(-Mathf.Pow(dist - spread, 2f) * rippleSharpness);
float bright = Mathf.Exp(-Mathf.Pow((dist - spread) * 0.5f, 2f));
rippleY += spike * rippleStrength * ease;
brightness += bright * ease;
// 目标点接近程度影响形状混合程度
float targetDist = Vector2.Distance(ripple.position, targetPosition);
float shapeFactor = Mathf.Clamp01(1f - targetDist / shapeChangeRadius);
shapeBlend = Mathf.Max(shapeBlend, shapeFactor * ease);
}
float finalY = baseY + rippleY;
Vector3 worldPos = new Vector3(x, finalY, z);
points[i * pointCount + j] = worldPos;
float depth = (finalY + waveHeight) / (waveHeight * 2f);
float brightnessScale = Mathf.Clamp01(1f + brightness);
Color pointColor = Color.Lerp(new Color(0.5f, 1f, 1f), new Color(0f, 0.5f, 1f), depth);
pointColor *= brightnessScale;
float scale = pointSize * (1f - depth * 0.5f);
// 形状混合逻辑(近似插值)
if (shapeBlend < 0.1f)
{
Draw.Sphere(worldPos, scale, pointColor);
}
else if (shapeBlend < 0.3f)
{
Draw.Torus(worldPos, scale * 0.6f, scale * 0.2f, pointColor); // 环形
}
else if (shapeBlend < 0.6f)
{
Draw.Cube(worldPos, scale * 1.4f, pointColor); // 立方体
}
else if (shapeBlend < 0.9f)
{
Draw.Cone(worldPos, scale * 1.6f, scale * 0.5f, pointColor); // 锥体
}
else
{
Vector3 a = worldPos + Vector3.up * scale;
Vector3 b = worldPos + new Vector3(scale, -scale, 0);
Vector3 c = worldPos + new Vector3(-scale, -scale, 0);
Draw.Triangle(a, b, c, pointColor); // 三角形
}
}
}
// 连接线条(可选)
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];
DrawLine(current, next);
}
if (i < pointCount - 1)
{
Vector3 next = points[index + pointCount];
DrawLine(current, next);
}
}
}
}
}
void DrawLine(Vector3 a, Vector3 b)
{
float avgY = (a.y + b.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(a, b, lineWidth * (1f - lineDepth * 0.5f), lineColor);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 874c4686e7644b74f83e1c0a58b26b34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
using UnityEngine;
using System.Collections.Generic;
public struct Ripple
{
public Vector3 position;
public float startTime;
public float strength;
}
public struct RippleResult
{
public float height;
public float brightness;
}
public class RippleManager
{
private List<Ripple> ripples = new List<Ripple>();
private float rippleStrength;
private float rippleDuration;
private float rippleSpreadSpeed;
private float rippleSharpness;
private float rippleMaxRadius;
public RippleManager(float strength, float duration, float spreadSpeed, float sharpness, float maxRadius)
{
rippleStrength = strength;
rippleDuration = duration;
rippleSpreadSpeed = spreadSpeed;
rippleSharpness = sharpness;
rippleMaxRadius = maxRadius;
}
public void AddRipple(Vector3 position)
{
ripples.Add(new Ripple
{
position = position,
startTime = Time.time,
strength = rippleStrength
});
}
public void CleanupRipples()
{
ripples.RemoveAll(r => Time.time - r.startTime > rippleDuration);
}
public RippleResult GetRippleEffect(Vector3 position, float currentTime)
{
float totalHeight = 0f;
float totalBrightness = 0f;
foreach (var ripple in ripples)
{
float timeSinceStart = currentTime - ripple.startTime;
if (timeSinceStart > rippleDuration) continue;
float distance = Vector3.Distance(position, ripple.position);
float maxDistance = rippleSpreadSpeed * timeSinceStart;
if (distance > maxDistance || distance > rippleMaxRadius) continue;
float distFactor = Mathf.Exp(-distance * rippleSharpness);
float timeFactor = 1f - (timeSinceStart / rippleDuration);
float strength = ripple.strength * distFactor * timeFactor;
totalHeight += strength;
totalBrightness += strength;
}
return new RippleResult
{
height = totalHeight,
brightness = totalBrightness
};
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea17c12f760878e4dadd86d12ad6ca8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,112 @@
using UnityEngine;
using System.Collections.Generic;
using Shapes;
public enum TargetType
{
Sphere,
Cube,
Torus
}
public class TargetPointManager
{
private List<Vector3> targetPoints = new List<Vector3>();
private List<TargetType> targetTypes = new List<TargetType>();
private float targetSize;
private float wireScale;
private float heightOffset;
private Color entityColor;
private Color wireColor;
private float rotationSpeed;
private float floatSpeed;
private float floatHeight;
public TargetPointManager(float size, float wireScale, float height, Color entity, Color wire, float rotSpeed, float floatSpeed, float floatHeight)
{
this.targetSize = size;
this.wireScale = wireScale;
this.heightOffset = height;
this.entityColor = entity;
this.wireColor = wire;
this.rotationSpeed = rotSpeed;
this.floatSpeed = floatSpeed;
this.floatHeight = floatHeight;
}
public void AddTargetPoint(Vector3 position, TargetType type)
{
targetPoints.Add(position);
targetTypes.Add(type);
}
public void ClearTargetPoints()
{
targetPoints.Clear();
targetTypes.Clear();
}
public void DrawTargetPoints(float currentTime)
{
for (int i = 0; i < targetPoints.Count; i++)
{
Vector3 pos = targetPoints[i];
TargetType type = targetTypes[i];
// 计算浮动效果
float floatOffset = Mathf.Sin(currentTime * floatSpeed) * floatHeight;
Vector3 finalPos = pos + Vector3.up * (heightOffset + floatOffset);
// 绘制外框(立方体)
DrawWireCube(finalPos, targetSize * wireScale, wireColor);
// 绘制内部形状
switch (type)
{
case TargetType.Sphere:
Draw.Sphere(finalPos, targetSize * 0.8f, entityColor);
break;
case TargetType.Cube:
Draw.Cube(finalPos, Quaternion.Euler(0, currentTime * rotationSpeed, 0), targetSize * 0.8f, entityColor);
break;
case TargetType.Torus:
Draw.Torus(finalPos, Quaternion.Euler(0, currentTime * rotationSpeed, 0), targetSize * 0.8f, targetSize * 0.2f, entityColor);
break;
}
}
}
private void DrawWireCube(Vector3 position, float size, Color color)
{
float halfSize = size / 2f;
Vector3[] points = new Vector3[]
{
position + new Vector3(-halfSize, -halfSize, -halfSize),
position + new Vector3(halfSize, -halfSize, -halfSize),
position + new Vector3(halfSize, -halfSize, halfSize),
position + new Vector3(-halfSize, -halfSize, halfSize),
position + new Vector3(-halfSize, halfSize, -halfSize),
position + new Vector3(halfSize, halfSize, -halfSize),
position + new Vector3(halfSize, halfSize, halfSize),
position + new Vector3(-halfSize, halfSize, halfSize)
};
// 绘制底面
Draw.Line(points[0], points[1], 0.1f, color);
Draw.Line(points[1], points[2], 0.1f, color);
Draw.Line(points[2], points[3], 0.1f, color);
Draw.Line(points[3], points[0], 0.1f, color);
// 绘制顶面
Draw.Line(points[4], points[5], 0.1f, color);
Draw.Line(points[5], points[6], 0.1f, color);
Draw.Line(points[6], points[7], 0.1f, color);
Draw.Line(points[7], points[4], 0.1f, color);
// 绘制连接线
Draw.Line(points[0], points[4], 0.1f, color);
Draw.Line(points[1], points[5], 0.1f, color);
Draw.Line(points[2], points[6], 0.1f, color);
Draw.Line(points[3], points[7], 0.1f, color);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8d5ffa5489c71c48951644fc2c52117
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using UnityEngine;
public class WaveGenerator
{
private float noiseScale;
private float waveHeight;
private float waveSpeed;
public WaveGenerator(float noiseScale, float waveHeight, float waveSpeed)
{
this.noiseScale = noiseScale;
this.waveHeight = waveHeight;
this.waveSpeed = waveSpeed;
}
public float GetHeight(float x, float z, float time)
{
float noise = Mathf.PerlinNoise(x * noiseScale + time * waveSpeed, z * noiseScale + time * waveSpeed);
return Mathf.Lerp(-waveHeight, waveHeight, noise);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed485db0b6bd66943af4f7b138357992
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: