制作粒子光环
概述
粒子光环由内外两层粒子构成。外层粒子分布范围更广,旋转速度更快。内层粒子分布范围窄,旋转速度更慢。
对象制作
创建一个空对象Halo,附加两个子对象Inner和Outer,分别给两个子对象添加Particle System 组件。设置如下
代码设计
HaloParticleData.cs
粒子的数据类,记录粒子距离圆心的半径和角度
public class HaloParticleData {
public HaloParticleData(float r = 0, float a = 0) {
radius = r;
angle = a;
}
public float radius {
get;
set;
}
public float angle {
get;
set;
}
}
InnerHalo.cs
- 初始化粒子系统
设置每个粒子的半径和角度值,确定粒子的位置。
用一个布尔值标记当前粒子的缩放方向,两个半径数组规定缩放范围。
public class InnerHalo : MonoBehaviour
{
public ParticleSystem particleSystem;// 粒子系统
private ParticleSystem.Particle[] particleArray;// 粒子数组
private int haloResolution = 3500;// 粒子数量
private float minRadius = 2.5F;// 最小半径
private float maxRadius = 4F;// 最大半径
private HaloParticleData[] haloParticledata;//粒子数据
private float shrinkSpeed = 0.5f;//缩放速度
private float[] max;// 扩张后粒子半径
private float[] min;// 收缩后粒子半径
private bool direction = true; //T-收缩 F-扩张
// Start is called before the first frame update
void Start()
{
particleSystem = this.GetComponent<ParticleSystem>();
particleArray = new ParticleSystem.Particle[haloResolution];
haloParticledata = new HaloParticleData[haloResolution];
max = new float[haloResolution];
min = new float[haloResolution];
particleSystem.Emit(haloResolution);
particleSystem.GetParticles(particleArray);
for (int i = 0; i < haloResolution; ++i)
{
float shiftMinRadius = Random.Range(1, (maxRadius + minRadius) / 2 / minRadius);
float shiftMaxRadius = Random.Range((maxRadius + minRadius) / 2 / maxRadius, 1);
float radius = Random.Range(minRadius * shiftMinRadius, maxRadius * shiftMaxRadius);
max[i] = radius+1;
min[i] = radius-1;
float angle = Random.Range(0, Mathf.PI * 2);
haloParticledata[i] = new HaloParticleData(radius, angle);
particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
}
particleSystem.SetParticles(particleArray, particleArray.Length);
}
}
- 粒子系统运动
在update函数中更新粒子角度值和半径,重新计算粒子位置,实现粒子的圆周运动以及循环缩放。
到达缩放限值后调转方向。
void Update()
{
for (int i = 0; i < haloResolution; ++i)
{
haloParticledata[i].angle -= Random.Range(0, 1F / 360) / 2;
if (direction)
{
if (haloParticledata[i].radius > min[i]) haloParticledata[i].radius -= shrinkSpeed * Time.deltaTime;
else direction = false;
}
else
{
if (haloParticledata[i].radius < max[i]) haloParticledata[i].radius += shrinkSpeed * Time.deltaTime;
else direction = true;
}
float angle = haloParticledata[i].angle;
float radius = haloParticledata[i].radius;
particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
}
particleSystem.SetParticles(particleArray, particleArray.Length);
}
OuterHalo.cs
外层的代码和内层基本相同,只需修改几个参数,修改粒子数目,半径范围和旋转速度即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OuterHalo : MonoBehaviour
{
public ParticleSystem particleSystem;// 粒子系统
private ParticleSystem.Particle[] particleArray;// 粒子数组
private int haloResolution = 3000;// 粒子数量
private float minRadius = 2F;// 最小半径
private float maxRadius = 4.5F;// 最大半径
private HaloParticleData[] haloParticledata;//粒子数据
private float shrinkSpeed = 0.5f;//缩放速度
private float[] max;// 扩张后粒子半径
private float[] min;// 收缩后粒子半径
private bool direction = true; //T-收缩 F-扩张
// Start is called before the first frame update
void Start()
{
particleSystem = this.GetComponent<ParticleSystem>();
particleArray = new ParticleSystem.Particle[haloResolution];
haloParticledata = new HaloParticleData[haloResolution];
max = new float[haloResolution];
min = new float[haloResolution];
particleSystem.Emit(haloResolution);
particleSystem.GetParticles(particleArray);
for (int i = 0; i < haloResolution; ++i)
{
float shiftMinRadius = Random.Range(1, (maxRadius + minRadius) / 2 / minRadius);
float shiftMaxRadius = Random.Range((maxRadius + minRadius) / 2 / maxRadius, 1);
float radius = Random.Range(minRadius * shiftMinRadius, maxRadius * shiftMaxRadius);
max[i] = radius+1;
min[i] = radius-1;
float angle = Random.Range(0, Mathf.PI * 2);
haloParticledata[i] = new HaloParticleData(radius, angle);
particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
}
particleSystem.SetParticles(particleArray, particleArray.Length);
}
// Update is called once per frame
void Update()
{
for (int i = 0; i < haloResolution; ++i)
{
haloParticledata[i].angle -= Random.Range(0, 1F / 360);
if (direction)
{
if (haloParticledata[i].radius > min[i]) haloParticledata[i].radius -= shrinkSpeed * Time.deltaTime;
else direction = false;
}
else
{
if (haloParticledata[i].radius < max[i]) haloParticledata[i].radius += shrinkSpeed * Time.deltaTime;
else direction = true;
}
float angle = haloParticledata[i].angle;
float radius = haloParticledata[i].radius;
particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
}
particleSystem.SetParticles(particleArray, particleArray.Length);
}
}
效果展示
(建议屏幕亮度调高)
代码传送门