参考http://i-remember.fr/en使用unity3d制作白色光圈效果。这里先附上最终效果图:
首先分析一下该网站中的光圈,它是由内外两个光圈一起构成的。内部光圈有缺口,转的速度比较慢,但确实是在顺时针转动。而外光圈则相反,没有缺口,转动的速度也快很多。所以对于这整个效果,分为内外两个部分,代码大致相同。
第一步:基本框架
首先创建一个新项目,这里命名为Halo。将摄像机背景设为全黑之后。添加空游戏对象Halo,它有两个子对象,分别为InnerHalo和OuterHalo,结果如图:
给两个子对象添加ParticleSystem组件,并设置如下数据:
两个对象设置相同,这里就不重复贴图了。
第二步:设置光圈粒子类
创建C#脚本HaloParticle并实现HaloParticle类,方便后续对光圈粒子的处理
public class HaloParticle {
public HaloParticle(float r = 0, float a = 0) {
radius = r;
angle = a;
}
public float radius {
get;
set;
}
public float angle {
get;
set;
}
}
第三步:外光圈的实现
两个光圈的代码大致相同,先从比较简单的外光圈入手。创建OuterHalo脚本,对于外光圈,需要属性包括粒子系统、最大最小半径、粒子总数以及一个HaloParticle数组存粒子状态,如下:
public ParticleSystem _particle_system;
private ParticleSystem.Particle[] _particle_array;
private int _halo_resolution = 3000;
private float _min_radius = 2F;
private float _max_radius = 4.5F;
private HaloParticle[] _halo_particle;
之后在开始时完成初始各个粒子的位置。注意到这里所有的粒子都是贴近扇道中心部分,到边缘时粒子数目较少。所以在使用随机数时应使其在平均半径处概率最高,代码实现如下:void Start () {
_particle_system = this.GetComponent<ParticleSystem> ();
_particle_array = new ParticleSystem.Particle[_halo_resolution];
_halo_particle = new HaloParticle[_halo_resolution];
_particle_system.maxParticles = _halo_resolution;
_particle_system.Emit (_halo_resolution);
_particle_system.GetParticles (_particle_array);
for (int i = 0; i < _halo_resolution; ++i) {
//粒子半径,添加一个偏移量,使粒子集中于平均半径处
float shiftMinRadius = Random.Range(1, ((_max_radius + _min_radius) / 2) / _min_radius);
float shiftMaxRadius = Random.Range(((_max_radius + _min_radius) / 2) / _max_radius, 1);
float radius = Random.Range (_min_radius * shiftMinRadius, _max_radius * shiftMaxRadius);
//粒子角度
float angle = Random.Range (0, Mathf.PI * 2);
_halo_particle [i] = new HaloParticle (radius, angle);
_particle_array [i].position = new Vector3 (radius * Mathf.Cos (angle), radius * Mathf.Sin (angle), 0);
}
_particle_system.SetParticles (_particle_array, _particle_array.Length);
}
这时将脚本添加到外光圈对象,此时效果如下:下一步得让这玩意动起来,在Update函数中,添加代码使每帧旋转一定角度即可,注意到原网站中速度不是恒定不变的,这里用一个随机数来使旋转速度有一定变化。代码如下:
void Update () {
for (int i = 0; i < _halo_resolution; ++i) {
_halo_particle [i].angle -= Random.Range(0, 1F / 360);
_particle_array [i].position = new Vector3 (_halo_particle [i].radius * Mathf.Cos (_halo_particle [i].angle), _halo_particle [i].radius * Mathf.Sin (_halo_particle [i].angle), 0);
}
_particle_system.SetParticles (_particle_array, _particle_array.Length);
}
效果如图:
这样外光圈部分基本完成。
第四步:内光圈实现
内光圈和外光圈大体相同。先创建一个InnerHalo脚本并将代码复制进去,考虑到内光圈有两个缺口,这两个缺口在一个角度上,所以只需在初始化粒子位置时,使粒子尽可能向另外的两个角度即π/4和5π/4聚集就好。考虑对称性,只需实现一半,再用一个1/2的概率使角度减少π即可。这里实现[π,2π]。考虑5π/4太麻烦,就实现3π/2再将角度减去π/4即可。代码如下:
//粒子角度,添加一个偏移量,使粒子集中于π/4和5π/4处
float shiftMinAngle = Random.Range(1, (Mathf.PI * 3 / 2) / Mathf.PI);
float shiftMaxAngle = Random.Range((Mathf.PI * 3 / 2) / Mathf.PI / 2, 1);
float angle = Random.Range (Mathf.PI * shiftMinAngle, Mathf.PI * 2 * shiftMaxAngle) - Mathf.PI / 4;
if (Random.Range (0, 100) < 50)
angle -= Mathf.PI;
稍稍改一下初始数据,使内光圈比外光圈窄,转动速度慢,粒子数目多。之后效果如图: 和原网站中的比较一下,还是挺像的O(∩_∩)O~,唯一就是我的粒子比较少,每个粒子比较大。可是粒子数目已经够多了,表示电脑风扇一直在转。所以就这样吧,如果想要更接近的效果,只要将粒子调多调小一点就差不多了。