啊啊啊FE你这需求真难做啊啊啊

This commit is contained in:
SoulliesOfficial
2025-07-03 18:14:17 -04:00
parent ffb97c6d28
commit 6533997d59
21 changed files with 22026 additions and 16139 deletions

View File

@@ -25,6 +25,9 @@ namespace Dreamteck.Splines
public enum MotionType { None, UseParticleSystem, FollowForward, FollowBackward, ByNormal, ByNormalRandomized }
public enum Wrap { Default, Loop }
public float width = 10f;
public Vector3 extendDirection = Vector3.right;
[HideInInspector]
public bool pauseWhenNotVisible = false;
[HideInInspector]
@@ -47,9 +50,11 @@ namespace Dreamteck.Splines
public float minCycles = 1f;
[HideInInspector]
public float maxCycles = 1f;
private Dictionary<uint, Particle> _particleDataMap = new Dictionary<uint, Particle>();
private ParticleSystem.Particle[] _particles = new ParticleSystem.Particle[0];
private Particle[] _controllers = new Particle[0];
//private float[] _initialOffset = new float[0];
//private Particle[] _controllers = new Particle[0];
private int _particleCount = 0;
private int _birthIndex = 0;
private List<Vector4> _customParticleData = new List<Vector4>();
@@ -67,43 +72,52 @@ namespace Dreamteck.Splines
}
int maxParticles = _particleSystem.main.maxParticles;
if (_particles.Length != maxParticles)
{
_particles = new ParticleSystem.Particle[maxParticles];
_customParticleData = new List<Vector4>(maxParticles);
Particle[] newControllers = new Particle[maxParticles];
for (int i = 0; i < newControllers.Length; i++)
if (maxParticles > _particleDataMap.Count)
{
if (i >= _controllers.Length) break;
newControllers[i] = _controllers[i];
_particleDataMap = new Dictionary<uint, Particle>(maxParticles);
}
_controllers = newControllers;
}
_particleCount = _particleSystem.GetParticles(_particles);
_particleSystem.GetCustomParticleData(_customParticleData, ParticleSystemCustomData.Custom1);
HashSet<uint> activeSeeds = new HashSet<uint>();
bool isLocal = _particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local;
Transform particleSystemTransform = _particleSystem.transform;
for (int i = 0; i < _particleCount; i++)
{
if (_controllers[i] == null)
uint seed = _particles[i].randomSeed; // 获取粒子的唯一ID
activeSeeds.Add(seed); // 记录存活的粒子
if (isLocal) TransformParticle(ref _particles[i], particleSystemTransform);
// 使用字典来检查粒子是否是新生儿这是100%可靠的
if (!_particleDataMap.ContainsKey(seed))
{
_controllers[i] = new Particle();
OnParticleBorn(i, seed);
}
if (isLocal)
HandleParticle(i, seed);
if (isLocal) InverseTransformParticle(ref _particles[i], particleSystemTransform);
}
// 清理字典中已经死亡的粒子数据,防止内存无限增长
if (activeSeeds.Count < _particleDataMap.Count)
{
List<uint> keysToRemove = new List<uint>();
foreach (var key in _particleDataMap.Keys)
{
TransformParticle(ref _particles[i], particleSystemTransform);
if (!activeSeeds.Contains(key)) keysToRemove.Add(key);
}
if (_customParticleData[i].w < 1f)
foreach (var key in keysToRemove)
{
OnParticleBorn(i);
}
HandleParticle(i);
if (isLocal)
{
InverseTransformParticle(ref _particles[i], particleSystemTransform);
_particleDataMap.Remove(key);
}
}
@@ -134,39 +148,45 @@ namespace Dreamteck.Splines
if (_particleSystem == null) _particleSystem = GetComponent<ParticleSystem>();
}
void HandleParticle(int index)
void HandleParticle(int index, uint seed)
{
if (!_particleDataMap.TryGetValue(seed, out Particle particleData)) return; // 安全检查
float lifePercent = _particles[index].remainingLifetime / _particles[index].startLifetime;
if (motionType == MotionType.FollowBackward || motionType == MotionType.FollowForward || motionType == MotionType.None)
{
Evaluate(_controllers[index].GetSplinePercent(wrapMode, _particles[index], motionType), ref evalResult);
Evaluate(particleData.GetSplinePercent(wrapMode, _particles[index], motionType), ref evalResult);
Vector3 resultRight = evalResult.right;
_particles[index].position = evalResult.position;
_particles[index].position = evalResult.position + extendDirection * particleData.initialOffset;
if (apply3DRotation)
{
_particles[index].rotation3D = evalResult.rotation.eulerAngles;
}
Vector2 finalOffset = offset;
if (volumetric)
{
if (motionType != MotionType.None)
{
finalOffset += Vector2.Lerp(_controllers[index].startOffset, _controllers[index].endOffset, 1f - lifePercent);
finalOffset += Vector2.Lerp(particleData.startOffset, particleData.endOffset, 1f - lifePercent);
finalOffset.x *= scale.x;
finalOffset.y *= scale.y;
} else
{
finalOffset += _controllers[index].startOffset;
finalOffset += particleData.startOffset;
}
}
_particles[index].position += resultRight * (finalOffset.x * evalResult.size) + evalResult.up * (finalOffset.y * evalResult.size);
_particles[index].position += resultRight * (finalOffset.x * evalResult.size)
+ evalResult.up * (finalOffset.y * evalResult.size);
_particles[index].velocity = evalResult.forward;
_particles[index].startColor = _controllers[index].startColor * evalResult.color;
_particles[index].startColor = particleData.startColor * evalResult.color;
}
}
private void OnParticleBorn(int index)
private void OnParticleBorn(int index, uint seed)
{
Particle newParticleData = new Particle();
Vector4 custom = _customParticleData[index];
custom.w = 1;
_customParticleData[index] = custom;
@@ -187,22 +207,29 @@ namespace Dreamteck.Splines
case EmitPoint.Ordered: percent = expectedParticleCount > 0 ? (float)_birthIndex / expectedParticleCount : 0f; break;
}
Evaluate(percent, ref evalResult);
_controllers[index].startColor = _particles[index].startColor;
_controllers[index].startPercent = percent;
newParticleData.startColor = _particles[index].startColor;
newParticleData.startPercent = percent;
_controllers[index].cycleSpeed = Random.Range(minCycles, maxCycles);
newParticleData.cycleSpeed = Random.Range(minCycles, maxCycles);
Vector2 circle = Vector2.zero;
if (volumetric)
{
if (emitFromShell) circle = Quaternion.AngleAxis(Random.Range(0f, 360f), Vector3.forward) * Vector2.right;
else circle = Random.insideUnitCircle;
}
_controllers[index].startOffset = circle * 0.5f;
_controllers[index].endOffset = Random.insideUnitCircle * 0.5f;
Vector3 right = Vector3.Cross(evalResult.forward, evalResult.up);
_particles[index].position = evalResult.position + right * _controllers[index].startOffset.x * evalResult.size * scale.x + evalResult.up * _controllers[index].startOffset.y * evalResult.size * scale.y;
newParticleData.initialOffset = Random.Range(-width, width);
newParticleData.startOffset = circle * 0.5f;
newParticleData.endOffset = Random.insideUnitCircle * 0.5f;
_particleDataMap.Add(seed, newParticleData);
if (!(motionType == MotionType.FollowForward || motionType == MotionType.FollowBackward))
{
Vector3 right = Vector3.Cross(evalResult.forward, evalResult.up);
_particles[index].position = evalResult.position +
right * newParticleData.startOffset.x * evalResult.size * scale.x +
evalResult.up * newParticleData.startOffset.y * evalResult.size * scale.y;
}
float forceX = _particleSystem.forceOverLifetime.x.constantMax;
float forceY = _particleSystem.forceOverLifetime.y.constantMax;
@@ -232,11 +259,12 @@ namespace Dreamteck.Splines
_particles[index].position += forceDistance;
_particles[index].velocity = normal * startSpeed + new Vector3(forceX, forceY, forceZ) * time;
}
HandleParticle(index);
//HandleParticle(index);
}
public class Particle
{
internal float initialOffset;
internal Vector2 startOffset = Vector2.zero;
internal Vector2 endOffset = Vector2.zero;
internal float cycleSpeed = 0f;