Unity3D学习 粒子光环

本文介绍了如何在Unity3D中创建粒子光环效果,包括粒子的创建、正态分布模拟、运动、收缩与扩张以及旋转。通过鼠标交互实现光环的动态变化,详细讲解了粒子数据结构和更新过程。
粒子光环
  • 设计说明
    • 粒子沿着圆环以不同方向做运动
    • 当鼠标移到圆环中心,圆环收缩,移开时圆环恢复。
粒子的创建

创建一个空项目,添加Particle System的组件,并给它挂上材料,调节参数,粒子系统就可以生成粒子了。

在这里插入图片描述

因为之后涉及到检测光标的位置,所以要给光环上增加检测器。并将它的tag设为button。

在这里插入图片描述

粒子的正态分布

因为希望粒子光环最内和最外粒子少,中间粒子多。所以要生成服从正态分布的随机数。先找到均匀随机分配的随机数,再获得服从正态分布的随机数。

class Ndistribution{
    System.Random rand = new System.Random();
    public double getNormalDistribution(double mean, double stdDev)
    {
        double u1 = 1.0 - rand.NextDouble(); //uniform(0,1] random doubles
        double u2 = 1.0 - rand.NextDouble();//两个独立的均匀随机数
        double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
                     Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
        double randNormal = mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
        return randNormal;
    }
}

这个算法方法简单,但是原理似乎很复杂,我没有深入研究。

粒子的运动
粒子数据结构

首先创建粒子数组和它的数据数组来存储粒子的信息。包括它的角度,半径,以及收缩前后的半径。(都是对于原点来说)

public ParticleData(float angle, float radius, float before, float after) {
    this.angle = angle;
    this.radius = radius;
    this.before = before;
    this.after = after;
}
public int particleNum = 10000; // 粒子数目
private ParticleSystem.Particle[] particles;//粒子数组
private ParticleData[] particleDatas;//粒子data
粒子数据初始化

粒子的半径,角度都是随机生成的。before即初始半径,after为收缩后的半径。因为收缩后应该是内部比较紧凑,外部松散,所以after比阈值小的粒子会有另外的值。依然使用随机数得到after,这样得到的数据看起来连贯性比较好,粒子不会出现明显分层。

for (int i = 0; i < particleNum; i++) {
		float angle = UnityEngine.Random.Range(0.0f, 360.0f);
    float radius = (float)nd.getNormalDistribution((minRadius+maxRadius)*0.5f, 1);
    float before = radius;
    float after = 0.7f * radius;

    if (after < minRadius * 1.1f) {
    		float midRadius = minRadius * 1.2f;
        after = UnityEngine.Random.Range(UnityEngine.Random.Range(minRadius, midRadius), (minRadius * 1.1f));
    }
    particleDatas[i] = new ParticleData(angle,radius,before,after);
}
粒子的收缩和扩张

收缩和扩张的时候,都以比较平和的方式来变化。当检测到鼠标移到光环中间时,就将isshrink设为true。

if (isshrink) {
    // 开始收缩
		if(particleDatas[i].radius > particleDatas[i].after) {
    		particleDatas[i].radius -= shrinkSpeed * (particleDatas[i].radius / particleDatas[i].after) * Time.deltaTime;//逼近
    }
} else {
  // 开始还原
    if (particleDatas[i].radius < particleDatas[i].before) {
    		particleDatas[i].radius += shrinkSpeed * (particleDatas[i].before / particleDatas[i].radius) * Time.deltaTime;
    } else {
        particleDatas[i].radius = particleDatas[i].before;
    }
}
ray = camera.ScreenPointToRay(Input.mousePosition);  
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "button") 
  	isshrink = true;  
else isshrink = false; 
粒子的旋转

粒子往不同方向旋转效果会比较好。可以直接通过奇偶来判断顺时针或逆时针,不需要分两个光环来写。设置speedLevel是为了让粒子以不同速度来旋转。

if (i % 2 == 0) {  
   // 逆时针
		particleDatas[i].angle += (i % speedLevel + 1) * particleSpeed;  
} else {  
   // 顺时针
    particleDatas[i].angle -= (i % speedLevel + 1) * particleSpeed;  
}
particleDatas[i].angle = particleDatas[i].angle % 360;
粒子数据更新

上面对粒子的半径和角度进行了更新,要将它应用到粒子上。

float rad = particleDatas[i].angle / 180 * Mathf.PI;  
// 更新粒子坐标
particles[i].position = new Vector3(particleDatas[i].radius * Mathf.Cos(rad), particleDatas[i].radius * Mathf.Sin(rad), 0f); 

particleSystem.SetParticles(particles, particleNum); //应用到粒子上

至此完成了整个项目,粒子光环做出来效果真的很漂亮。

在这里插入图片描述

参考博客 参考博客2

项目仓库

视频链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值