参考网站首页的光环效果:http://i-remember.fr/en
用unity3d的粒子系统做一个粒子光环
向上效果图
可以看到该粒子效果由两部分组成,一部分是粒子光环,另一部分是粒子海洋
设计方法:
粒子的运动由程序来控制
光环的粒子使用cos,sin以及圆环半径来确定位置
粒子海洋中的粒子运动使用柏林噪声来控制
步骤一
新建一个空对象(ParticleHalo),在空对象下载新建两个空对象(Ring, SeaParticle),两个空对象都添加上粒子系统
步骤二
新建脚本RingParticle来控制光环中的粒子的运动
public class RingParticle : MonoBehaviour{
void Start(){}
void Update(){}
}
为RingParticle添加一些必要的参数
private ParticleSystem ps; //粒子系统(必须)
private ParticleSystem.Particle[] particles; //粒子系统中的粒子(必须)
public int count = 1000; //粒子数量
public float size = 0.3f; //粒子大小,非必须,可在inspector视图中的粒子系统中设置
public float maxRadius = 12f;//圆环的最大半径
public float minRadius = 5f;//圆谎的最小半径
public Gradient gradient; //用来给粒子添加颜色特效
private float[] radiuses; //粒子的半径
private float[] angles; //粒子的角度
在start函数中初始化粒子
void Start()
{
particles = new ParticleSystem.Particle[count];
radiuses = new float[count];
angles = new float[count];
ps = GetComponent<ParticleSystem>();
ps.maxParticles = count; //设置粒子的数目
ps.loop = false;//让粒子不循环播放
ps.startSpeed = 0; //设置粒子的速度
ps.startSize = size; //设置粒子的数量
ps.Emit(count); //发射粒子
ps.GetParticles(particles);
for (int i = 0; i < count; ++i)
{ // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近
float midRadius = (maxRadius + minRadius) / 2;
float minRate = Random.Range(1.0f, midRadius / minRadius);
float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);
// 随机每个粒子的角度
float angle = Random.Range(0.0f, 360.0f);
float theta = angle / 180 * Mathf.PI;
radiuses[i] = radius;
angles[i] = angle;
particles[i].position = new Vector3(radius * Mathf.Cos(theta), radius * Mathf.Sin(theta), 0);
}
ps.SetParticles(particles, particles.Length);
}
完成后运行,大致效果
在update函数中是粒子运动起来
void Update () {
for (int i = 0; i < count; ++i)
{
//将粒子的旋转速度分成10个不同的速度,让不同的粒子有不同的速度
angles[i] -= (i / 100 + 1) / radiuses[i] * Random.Range(1, 3);
angles[i] = (360.0f + angles[i]) % 360.0f;
float theta = angles[i] / 180 * Mathf.PI;
//让粒子的半径在一定范围内波动,产生有利效果
radiuses[i] += Random.Range(-0.01f, 0.01f);
particles[i].position = new Vector3(radiuses[i] * Mathf.Cos(theta), radiuses[i] * Mathf.Sin(theta), 0);
//给粒子加上颜色特效
particles[i].color = gradient.Evaluate(0.5f);
}
ps.SetParticles(particles, particles.Length);
}
在inspector视图中设置gradient
再次运行,就可以看到旋转的粒子光环了
制作粒子海洋
可先参考博文unity制作神奇的粒子海洋
新建SeaPaticle脚本控制粒子运动
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;
初始化粒子
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);
}
让粒子运动起来
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;
}
在inspector视图中调整参数,让粒子海洋的运动符合我们的要求
最后的静态效果
完整代码:
RingParticle
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Particle : MonoBehaviour {
private ParticleSystem ps; //粒子系统(必须)
private ParticleSystem.Particle[] particles; //粒子系统中的粒子(必须)
public int count = 1000; //粒子数量
public float size = 0.3f; //粒子大小,非必须,可在inspector视图中的粒子系统中设置
public float maxRadius = 12f;//圆环的最大半径
public float minRadius = 5f;//圆谎的最小半径
public Gradient gradient; //用来给粒子添加颜色特效
private float[] radiuses; //粒子的半径
private float[] angles; //粒子的角度
// Use this for initialization
void Start()
{
particles = new ParticleSystem.Particle[count];
radiuses = new float[count];
angles = new float[count];
ps = GetComponent<ParticleSystem>();
ps.maxParticles = count; //设置粒子的数目
ps.loop = false;//让粒子不循环播放
ps.startSpeed = 0; //设置粒子的速度
ps.startSize = size; //设置粒子的数量
ps.Emit(count); //发射粒子
ps.GetParticles(particles);
for (int i = 0; i < count; ++i)
{ // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近
float midRadius = (maxRadius + minRadius) / 2;
float minRate = Random.Range(1.0f, midRadius / minRadius);
float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);
// 随机每个粒子的角度
float angle = Random.Range(0.0f, 360.0f);
float theta = angle / 180 * Mathf.PI;
radiuses[i] = radius;
angles[i] = angle;
particles[i].position = new Vector3(radius * Mathf.Cos(theta), radius * Mathf.Sin(theta), 0);
}
ps.SetParticles(particles, particles.Length);
}
// Update is called once per frame
void Update () {
for (int i = 0; i < count; ++i)
{
//将粒子的旋转速度分成10个不同的速度,让不同的粒子有不同的速度
angles[i] -= (i / 100 + 1) / radiuses[i] * Random.Range(1, 3);
angles[i] = (360.0f + angles[i]) % 360.0f;
float theta = angles[i] / 180 * Mathf.PI;
//让粒子的半径在一定范围内波动,产生有利效果
radiuses[i] += Random.Range(-0.01f, 0.01f);
particles[i].position = new Vector3(radiuses[i] * Mathf.Cos(theta), radiuses[i] * Mathf.Sin(theta), 0);
//给粒子加上颜色特效
particles[i].color = gradient.Evaluate(0.5f);
}
ps.SetParticles(particles, particles.Length);
}
}
SeaParticel
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;
}
}