96 lines
4.1 KiB
C#
96 lines
4.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[ExecuteInEditMode] // 让脚本在编辑器模式下也能执行
|
|
public class ParticleAttractionPoint : MonoBehaviour
|
|
{
|
|
[Header("吸附参数")]
|
|
[Tooltip("粒子吸附目标点")]
|
|
public Transform attractionPoint; // 吸附目标点
|
|
[Tooltip("粒子生成多久后开始进行吸附")]
|
|
[Range(0.0f, 100.0f)]
|
|
public float delayTime = 0.0f; // 延迟时间
|
|
[Tooltip("粒子开始进行吸附计算后的大小变化曲线")]
|
|
public AnimationCurve SizeCurve = new AnimationCurve(); // 控制移动的曲线
|
|
[Tooltip("是否使用距离比例计算")]
|
|
public bool UseDistance = false;
|
|
|
|
[Header("逐帧计算")]
|
|
public float attractionSpeed=50.0f;
|
|
|
|
[Header("距离比例计算")]
|
|
[Range(0.001f, 2.0f)] // 限制时间缩放的最大值和最小值
|
|
public float timeScale = 1.0f; // 时间缩放
|
|
|
|
private ParticleSystem particleSystemComponent;
|
|
private ParticleSystem.Particle[] particles;
|
|
|
|
void OnEnable() // 改用OnEnable替代Start,这样在编辑器中也能初始化
|
|
{
|
|
particleSystemComponent = GetComponent<ParticleSystem>();
|
|
particles = new ParticleSystem.Particle[particleSystemComponent.main.maxParticles];
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if(!particleSystemComponent) return; // 添加空检查
|
|
|
|
int particleCount = particleSystemComponent.GetParticles(particles);
|
|
|
|
if(attractionPoint == null) return; // 添加目标点空检查
|
|
|
|
for (int i = 0; i < particleCount; i++)
|
|
{
|
|
float lifePercent = 1.0f - (particles[i].remainingLifetime / particles[i].startLifetime);
|
|
|
|
// 只有当粒子存在时间超过延迟时间才开始移动
|
|
if(particles[i].startLifetime - particles[i].remainingLifetime >= delayTime)
|
|
{
|
|
//暂存粒子位置
|
|
Vector3 startPos=particles[i].position;
|
|
|
|
if (UseDistance)
|
|
{
|
|
// 位置计算方法1 重新计算剩余的距离比例
|
|
float adjustedLifePercent = (particles[i].startLifetime - particles[i].remainingLifetime - delayTime) /
|
|
(particles[i].startLifetime - delayTime);
|
|
// 根据距离比例计算位置
|
|
particles[i].position = Vector3.Lerp(particles[i].position, attractionPoint.position, adjustedLifePercent*timeScale);
|
|
} else
|
|
{
|
|
// 位置计算方法2 朝向吸附点移动
|
|
Vector3 direction = (attractionPoint.position - particles[i].position).normalized;
|
|
particles[i].position += direction * attractionSpeed * Time.deltaTime;
|
|
}
|
|
|
|
// 修正粒子size
|
|
float distancePercent=Vector3.Distance(startPos, particles[i].position) / Vector3.Distance(startPos, attractionPoint.position);
|
|
particles[i].startSize = particles[i].startSize * SizeCurve.Evaluate(distancePercent);
|
|
|
|
// 当粒子到达目标点时立即消失,可能会有大量粒子,引起优化问题
|
|
// if(Vector3.Distance(particles[i].position, attractionPoint.position) <= 0.9f)
|
|
// {
|
|
// particles[i].remainingLifetime = 0.0f;
|
|
// }
|
|
|
|
// // 优化方法1 通过使用SqrMagnitude,可以避免开方运算
|
|
// if (Vector3.SqrMagnitude(particles[i].position - attractionPoint.position) <= 0.9f * 0.9f)
|
|
// {
|
|
// particles[i].remainingLifetime = 0.0f;
|
|
// }
|
|
|
|
// 优化方法2 使用Mathf.Approximately进行比较
|
|
if (Mathf.Approximately(Vector3.Distance(particles[i].position, attractionPoint.position), 0.0f) ||
|
|
Vector3.Distance(particles[i].position, attractionPoint.position) <= 0.9f)
|
|
{
|
|
particles[i].remainingLifetime = 0.0f;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
particleSystemComponent.SetParticles(particles, particleCount);
|
|
}
|
|
} |