使用Unity 3d 制作粒子光环和海洋
效果图
共有三个粒子系统对象和对应的脚本,图中有两个光环和粒子海洋,期中红色圈是内环,外环的颜色是不断变化的且成顺时针方向转动,海洋在两个光环靠后的位置进行运动。
光环的思路:如何让粒子呈环状分布? 使用三角函数,对特定的圆心位置和半径,,rsin(弧度)就是该粒子的y轴坐标,rcos(弧度)为x轴坐标,z轴就置零。因为这是一个环,有最小半径和最大半径,因此r要在这之间取随机数,而角度就360内都行(最后要转换成弧度制)。然后在里面的特效中的粒子应该是有顺时针也有逆时针的,这个我用奇偶数来实现,偶数顺时针,奇数逆时针。
两个光环的参数附图:
外渐变环:
内部红环:
粒子海洋的思路:
创建粒子系统和储存粒子海洋的数组,分配粒子的位置并创建柏林噪声,柏林噪声可以基于x轴和y轴产生对应的z轴输出,用于控制粒子海洋中的柏林噪声,是使所有元素流畅的做循环运动很重要的一环,最后设置颜色等参数,
粒子海洋参数如下:
具体制作步骤:
1.生成对应的粒子系统对象
2.调整颜色和位置等参数,以及Particle System中三个重要模块的参数如Duration和Emission Rate over time等粒子的存活时间和生成速率等。
(参数图已在上面展示)
3.新建脚本来控制三个粒子系统中粒子运动,先是对两个光环运动控制的脚本particleRing和Particle 。
外渐变颜色的光环
Start 用 GetComponent()获取粒子系统对象部件ps并初始化x,y 方向,然后Update运动函数判断现在ps的位置和方向来进行调整运动方向矢量,做圆周循环运动。代码如下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class particleRing : MonoBehaviour
{
public ParticleSystem ps;
int directionx,directiony;
void Start() {
ps= GetComponent<ParticleSystem>();
directionx = 0;
directiony = 0;
}
void Update() {
int minX = -10, maxX = 10 ;
if (directionx == 0 && ps.transform.position.x > minX){
ps.transform.position += Vector3.left * Time.deltaTime * 50;
Vector3 tmp=ps.transform.position;
double numy=100.0f-(ps.transform.position.x*ps.transform.position.x);
if(numy<0) numy=0;
else numy=Math.Sqrt(numy);
if(directiony==0) numy=numy*-1;
tmp.y=(float)numy;
ps.transform.position=tmp;
} else if (directionx == 1 && ps.transform.position.x < maxX){
ps.transform.position += Vector3.right * Time.deltaTime * 50;
Vector3 tmp=ps.transform.position;
double numy=100.0f-(ps.transform.position.x*ps.transform.position.x);
if(numy<0) numy=0;
else numy=Math.Sqrt(numy);
if(directiony==0) numy=numy*-1;
tmp.y=(float)numy;
ps.transform.position=tmp;
} else{
directionx=1-directionx;
directiony=1-directiony;
}
}
}
内环设置不同速度档次和方向的粒子,并且设置在最大半径和最小半径之间的随机半径,从而表现光环的伸缩趋势。Start初始化梭鱼要 的一众参数,如数组和最大数量等,并且为每个粒子设置其位置,随机化生成角度和半径,且在Update中通过鼠标点击事件move可以调整运动速度,代码逻辑如下:
using UnityEngine;
using System.Collections;
public class Particle : MonoBehaviour
{
ParticleSystem particleSystem;
private ParticleSystem.Particle[] particlesArray;
public int particleNumber = 700;
public float radius = 2.0f;
public float midR = 5.5f;
public float maxR = 8.5f;
public float free = 1.5f;//设置游动的范围
public float[] particleAngle;
public float[] particleRadius;
public float time = 0;
GameObject gameObject_;
bool move = true;
public float speed = 0.15f;
void Start()
{
particleSystem = GetComponent<ParticleSystem>();
particlesArray = new ParticleSystem.Particle[particleNumber];//将储存粒子的数组初始化
particleSystem.maxParticles = particleNumber;//设置粒子发射的最大数量
particleAngle = new float[particleNumber];
particleRadius = new float[particleNumber];
particleSystem.Emit(particleNumber);//将刚刚初始化的particleNumber个粒子发射出去
particleSystem.GetParticles(particlesArray);
for (int i = 0; i < particleNumber; i++)
{//为每个粒子设置其位置
//最小半径随机扩大
float rate1 = Random.Range(1.0f, midR / radius);
//最大半径随机缩小
float rate2 = Random.Range(midR / maxR, 1.0f);
float r = Random.Range(radius * rate1, maxR * rate2);
//float r = Random.Range(radius, 6.0f);
float angle = Random.Range(0.0f, 360.0f);//位置为0 - 360度的随机一个角度
float rad = angle / 180 * Mathf.PI;//角度变换成弧度
particleRadius[i] += Mathf.PingPong(time, free) - free / 2.0f;
time += Time.deltaTime;
particleAngle[i] = angle;
particleRadius[i] = r;
particlesArray[i].position = new Vector3(r * Mathf.Cos(rad), r * Mathf.Sin(rad), 0.0f);//为每个粒子坐标赋值
}
particleSystem.SetParticles(particlesArray, particlesArray.Length);//设置该粒子系统的粒子。前面数组的长度是设置粒子的数量
}
void Update()
{
// Debug.Log(move);
if (move)
{
for (int i = 0; i < particleNumber; i++)
{
//设置速度为五个不同的档次
if (i % 2 == 0)
{
particleAngle[i] += speed * (i % 80 + 1);
}
else
{
particleAngle[i] -= speed * (i % 80 + 1);
}
if (particleAngle[i] > 360)
particleAngle[i] -= 360;
if (particleAngle[i] < 0)
particleAngle[i] += 360;
float rad = particleAngle[i] / 180 * Mathf.PI;
particlesArray[i].position = new Vector3(particleRadius[i] * Mathf.Cos(rad), particleRadius[i] * Mathf.Sin(rad), 0f);
}
particleSystem.SetParticles(particlesArray, particleNumber);
}
//Debug.Log("111");
}
private void OnMouseDown()
{
if (move)
{
move = false;
}
else
{
move = true;
}
}
}
粒子海洋
SeaParticle.cs
创建粒子数组particleArray ,设置颜色变量Gradient和粒子海洋
每行的数目以及粒子之间的间隔还有柏林噪声的参数。
Start 函数中对这些变量进行初始化并且分布位置,其中中关键点 zPos(通过柏林噪声函数赋值)Update让粒子运动起来,让粒子在x,z 方向上进行波动,并且重新设置x,y 的值从而实现波动,然后更信位置和参数。
在这里插入代码片
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SeaParticle : MonoBehaviour
{
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particlesArray;
public Gradient colorGradient;
public int seaResolution = 50; //每行粒子的数目
public float spacing = 0.5f;//粒子之间的间隔
public float noiseScale = 0.2f; //
public float heightScale = 3f;
public float noiseX;
public float noiseY;
// Use this for initialization
void Start()
{
particleSystem = GetComponent<ParticleSystem>();
particleSystem.loop = false;
particlesArray = new ParticleSystem.Particle[seaResolution * seaResolution];
particleSystem.maxParticles = seaResolution * seaResolution;
particleSystem.Emit(seaResolution * seaResolution);
particleSystem.GetParticles(particlesArray);
for (int i = 0; i < seaResolution; i++)
{
for (int j = 0; j < seaResolution; j++)
{
float zPos = Mathf.PerlinNoise(i * noiseScale, j * noiseScale) * heightScale;
particlesArray[i * seaResolution + j].position = new Vector3(i * spacing, zPos, j * spacing);
}
}
particleSystem.SetParticles(particlesArray, particlesArray.Length);
}
// Update is called once per frame
void Update()
{
for (int i = 0; i < seaResolution; i++)
{
for (int j = 0; j < seaResolution; j++)
{
float zPos = Mathf.PerlinNoise(i * noiseScale + noiseX, j * noiseScale + noiseY);
//让粒子在x、z方向上波动
float r = Random.Range(5, 10);
particlesArray[i * seaResolution + j].color = colorGradient.Evaluate(zPos);
//重新设置x,y的原因是为了让粒子波动起来
particlesArray[i * seaResolution + j].position = new Vector3((i + zPos * r) * spacing, zPos * heightScale, (j + zPos * r) * spacing);
}
}
particleSystem.SetParticles(particlesArray, particlesArray.Length);
noiseX += Time.deltaTime;
noiseY += Time.deltaTime;
}
}
演示效果视频
https://www.bilibili.com/video/BV1o3411m7FT/?spm_id_from=333.999.0.0&vd_source=66cc21f92131571125d69a5f24344dcd
项目地址
https://github.com/circle-fish/particle-system