? ? 耗时两天半终于完成了这个功能!先来看看最终效果!
? ??

? ? 其中粒子速度,粒子数量,?扩散效果等参数都可以在粒子系统参数里调整~总之就是都是可控的!美术想要啥效果让他们自己调去!
? ? 首先来讲一下用粒子系统来做这个的好处!首先就是效果好,其次就是参数可控,并且效率极高,粒子是有自己独立线程的,由unity自己进行优化,如果不用粒子系统用ugui来写这个效果的话就要面临网格重建,打破批处理而且效果不好,所以我还是选择粒子系统来完成这个需求。
? ? 好了现在来讲一下具体实现步骤!
? ? 首先要把粒子系统显示在UI上,此处我参考了博文如何让粒子系统显示在UI上,跟着步骤来就行了没啥难度。然后就需要去控制粒子的运动轨迹啦。思路大概就是在粒子发射后去获取这些粒子,再在update里去更新粒子位置,使其朝着目标位置靠拢。以下是具体的实现代码:
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(ParticleSystem))]
public class ParticleTargetMove : MonoBehaviour
{
private ParticleSystem par;
private ParticleSystem.Particle[] arrPar;
private int arrCount;
public float speed = 0.1f;
public float delayTime = 1f;
public float originEmissionRate;
public bool isActive;
//public Vector3 pos = Vector3.zero;
public float speedAdd;
public float speedAddDelta = 2f;
public bool oncePar = false;
private Vector3 wPos;
private void Awake()
{
par = this.GetComponent<ParticleSystem>();
arrPar = new ParticleSystem.Particle[par.main.maxParticles];
speedAdd = 0f;
if (oncePar)
{
originEmissionRate = par.emission.GetBurst(0).count.curveMultiplier;
}
else
{
originEmissionRate = par.emission.rateOverTimeMultiplier;//par.emissionRate;
}
}
private void setActive()
{
isActive = true;
}
//Dictionary<int, List<Vector3>> pointDic = new Dictionary<int, List<Vector3>>();
private void Update()
{
if (!isActive || !par)
{
return;
}
arrCount = par.GetParticles(arrPar);
if (arrCount < 1)
{
isActive = false;
par.Stop();
speedAdd = 0f;
}
else
{
speedAdd += Time.unscaledDeltaTime * speedAddDelta;
}
for (int i = 0; i < arrCount; i++)
{
Vector3 vector = wPos - arrPar[i].position;
if (vector.magnitude <= (speed + speedAdd) * Time.unscaledDeltaTime)
{
arrPar[i].position = wPos;
arrPar[i].remainingLifetime = 0f;
//par.emissionRate = 0f;
var emis = par.emission;
emis.rateOverTimeMultiplier = 0;
}
else
{
arrPar[i].position += vector.normalized * (speed + speedAdd) * Time.unscaledDeltaTime;
//arrPar[i].position = Vector3.Lerp(arrPar[i].position, Vector3.zero, this.speed * Time.unscaledDeltaTime);
}
}
par.SetParticles(arrPar, arrCount);
}
public void Play(Vector3 _pos, int emit_count)
{
//if (par.isStopped)
//{
wPos = _pos;
Invoke("setActive", delayTime + 0.01f);
if (par == null)
{
par = this.GetComponent<ParticleSystem>();
}
if (oncePar)
{
var b = par.emission.GetBurst(0);
b.count = new ParticleSystem.MinMaxCurve(originEmissionRate);
//b.minCount = (short)originEmissionRate;
//b.maxCount = (short)originEmissionRate;
par.emission.SetBurst(0, b);
}
else
{
//par.emissionRate = originEmissionRate;
var emis = par.emission;
emis.rateOverTimeMultiplier = originEmissionRate;
}
speedAdd = 0;
isActive = false;
par.Stop();
//par.Play(withChildren: true);
//par.Play();
par.Emit(emit_count);
//pointDic.Clear();
//}
}
}
? ? 也没啥需要解释的,就是按照这个思路写的代码,需要播放这个粒子系统的时候就调用Play方法就行了。对粒子系统参数不熟悉的可以查阅官方手册或者查看这篇博客https://blog.csdn.net/m0_37679113/article/details/75893700
? ? 此处附上我的粒子系统参数


? ? 啊差点忘了,材质记得选择有透明通道的材质,我这儿选择的是

? ? 最后,为了使动画效果好一些,我这边还给粒子增添了序列帧动画。具体怎么给粒子增添序列帧动画可以参考这篇博文https://blog.csdn.net/ys5773477/article/details/53323985。此处附上我序列帧动画相关参数:

? ? 这样用粒子系统去实现金币或者其他资源的飞入资源条的动画效果就完成了!谢谢大家观看!谢谢!
|