提交
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
using UnityEngine;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(LineRenderer))]
|
||||
public class RobotECGWave : MonoBehaviour
|
||||
{
|
||||
public enum WaveType
|
||||
{
|
||||
RobotECG,
|
||||
Sine,
|
||||
Triangle,
|
||||
Square,
|
||||
HumanECG
|
||||
}
|
||||
|
||||
[Header("波形设置")]
|
||||
public WaveType waveType = WaveType.RobotECG;
|
||||
|
||||
public float waveHeight = 1f;
|
||||
public float waveWidth = 10f;
|
||||
public float waveStretch = 1f;
|
||||
public float speed = 2f;
|
||||
|
||||
[Header("绘图设置")]
|
||||
public int resolution = 300;
|
||||
public float updateInterval = 0.02f;
|
||||
|
||||
private LineRenderer lineRenderer;
|
||||
private Vector3[] points;
|
||||
private float timer = 0f;
|
||||
|
||||
private float lastWidth = -1f;
|
||||
private int lastResolution = -1;
|
||||
|
||||
private float phaseOffset = 0f;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (lineRenderer == null)
|
||||
lineRenderer = GetComponent<LineRenderer>();
|
||||
|
||||
lineRenderer.useWorldSpace = true;
|
||||
|
||||
if (points == null || resolution != lastResolution || waveWidth != lastWidth)
|
||||
{
|
||||
points = new Vector3[resolution];
|
||||
lineRenderer.positionCount = resolution;
|
||||
lastResolution = resolution;
|
||||
lastWidth = waveWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
Init();
|
||||
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
if (timer >= updateInterval)
|
||||
{
|
||||
timer = 0f;
|
||||
phaseOffset += updateInterval * speed;
|
||||
UpdateWave();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseOffset = Time.realtimeSinceStartup * speed;
|
||||
UpdateWave();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWave()
|
||||
{
|
||||
Vector3 origin = transform.position;
|
||||
Quaternion rotation = transform.rotation;
|
||||
|
||||
for (int i = 0; i < resolution; i++)
|
||||
{
|
||||
float x = ((float)i / resolution) * waveWidth;
|
||||
float timeOffset = (x / waveWidth) * waveStretch + phaseOffset;
|
||||
float waveValue = GetWaveValue(timeOffset % 1.0f);
|
||||
|
||||
Vector3 localPos = new Vector3(x, waveValue * waveHeight, 0f);
|
||||
points[i] = origin + rotation * localPos;
|
||||
}
|
||||
|
||||
if (lineRenderer != null)
|
||||
lineRenderer.SetPositions(points);
|
||||
}
|
||||
|
||||
float GetWaveValue(float time)
|
||||
{
|
||||
switch (waveType)
|
||||
{
|
||||
|
||||
case WaveType.Sine:
|
||||
return Mathf.Sin(time * Mathf.PI * 2f);
|
||||
|
||||
case WaveType.Triangle:
|
||||
return 2f * Mathf.Abs(2f * (time - Mathf.Floor(time + 0.5f))) - 1f;
|
||||
|
||||
case WaveType.Square:
|
||||
return Mathf.Sign(Mathf.Sin(time * Mathf.PI * 2f));
|
||||
|
||||
case WaveType.HumanECG:
|
||||
return GenerateHumanECGShape(time);
|
||||
|
||||
case WaveType.RobotECG:
|
||||
default:
|
||||
return GenerateRobotECGShape(time);
|
||||
}
|
||||
}
|
||||
|
||||
float GenerateRobotECGShape(float time)
|
||||
{
|
||||
float t = time % 1.0f;
|
||||
|
||||
float baseValue = 0f;
|
||||
|
||||
if (t < 0.10f)
|
||||
{
|
||||
// 上升锯齿:锯齿线性上升
|
||||
baseValue = (t / 0.10f) + Mathf.PingPong(t * 80f, 0.1f);
|
||||
}
|
||||
else if (t < 0.20f)
|
||||
{
|
||||
// 高电平方波 + 高频扰动
|
||||
baseValue = 1f + Mathf.PingPong(t * 120f, 0.1f);
|
||||
}
|
||||
else if (t < 0.30f)
|
||||
{
|
||||
// 快速下降:线性下降带锯齿
|
||||
baseValue = Mathf.Lerp(1f, -0.8f, (t - 0.20f) / 0.10f) + Mathf.PingPong(t * 100f, 0.05f);
|
||||
}
|
||||
else if (t < 0.40f)
|
||||
{
|
||||
// 低电平方波 + 微扰动
|
||||
baseValue = -0.8f + Mathf.PingPong(t * 60f, 0.05f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 平缓底噪,锯齿叠加轻扰动
|
||||
baseValue = Mathf.Sin(t * 80f) * 0.05f + Mathf.PingPong(t * 10f, 0.02f);
|
||||
}
|
||||
|
||||
return baseValue;
|
||||
}
|
||||
|
||||
|
||||
float GenerateHumanECGShape(float time)
|
||||
{
|
||||
float t = time % 1.0f;
|
||||
|
||||
if (t < 0.1f)
|
||||
return Mathf.Lerp(0f, 0.1f, t / 0.1f); // P 波上升
|
||||
|
||||
else if (t < 0.2f)
|
||||
return Mathf.Lerp(0.1f, 0f, (t - 0.1f) / 0.1f); // P 波下降
|
||||
|
||||
else if (t < 0.22f)
|
||||
return Mathf.Lerp(0f, -0.15f, (t - 0.2f) / 0.02f); // Q 波
|
||||
|
||||
else if (t < 0.26f)
|
||||
return Mathf.Lerp(-0.15f, 1f, (t - 0.22f) / 0.04f); // R 波快速上升
|
||||
|
||||
else if (t < 0.30f)
|
||||
return Mathf.Lerp(1f, -0.3f, (t - 0.26f) / 0.04f); // S 波下降
|
||||
|
||||
else if (t < 0.35f)
|
||||
return Mathf.Lerp(-0.3f, 0f, (t - 0.30f) / 0.05f); // 回到0线
|
||||
|
||||
else if (t < 0.5f)
|
||||
return Mathf.Lerp(0f, 0.4f, (t - 0.35f) / 0.15f); // T 波上升
|
||||
|
||||
else if (t < 0.65f)
|
||||
return Mathf.Lerp(0.4f, 0f, (t - 0.5f) / 0.15f); // T 波下降
|
||||
|
||||
else
|
||||
return 0f; // 静息段
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 255e27a83db9041409f9a2deb08fcc9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user