Unity3DGame学习笔记(6):粒子系统

实验任务:

这次我们需要参考玩野的光环效果并用unity来实现它: http://i-remember.fr/en  
目标效果:

实验效果:

实验需求分析:
1.粒子沿一定半径随机分布,且在半径中央的例子较多;
2.粒子按一定速度分别顺时针和逆时针旋转,且速度各不相同;
2.粒子有两层,一层顺时针运动,一层逆时针运动;
3.粒子有部分的亮度较大,一部分比较小;
4.有一个按钮,鼠标移入时收缩粒子,移出时扩散粒子;

需求1,3:

要实现圆形分布,我是通过在360度范围内随机生成方位角度,再将其转化为cos和sin值来获得x,y坐标;
void setParticle() {
	bool clock = true; //分配旋转方向
	for (int i = 0; i < particleNum; i++) {
		//处理粒子集中分布于平均半径
		float midRadius = (5f + 12f) / 2;
		float minRate = Random.Range (1f, midRadius / 5f);
		float maxRate = Random.Range (midRadius / 12f, 1f);
		float radius = Random.Range (5f * minRate, 12f * maxRate);
		notHoverRadius [i] = radius;
		//记录收缩后的半径
		float hradius = Random.Range (8f, 9f);
		hoverRadius [i] = hradius;
		
		float angle = Random.Range (0f, 360f); //随机生成方位角
		float t = Random.Range (0f, 10f);//随机生成时钟系数,浮动实现时有用
		attribute [i] = new particleAttr (angle, clock, radius, t);
		//分成顺和逆时钟移动
		if (clock) {
			clock = false;
		} else {
			clock = true;
		}
		float radOfAngle = angle / 180 * Mathf.PI;
		//设置粒子位置
		particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * radius, Mathf.Sin (radOfAngle) * radius, 0);
	}
	particleSystem.SetParticles (particleArray, particleArray.Length);
}

需求2,4:

首先,旋转运动我分为两个部分,一个为鼠标移入一个为鼠标移出(这里代码有点冗余,应该可以合并),实现两个时刻的移动;而亮度不同我是通过渐变实现的,设置5个变化时间点。
void Start() {
	//初始化粒子
	hoverRadius = new float[particleNum];
	notHoverRadius = new float[particleNum];
	attribute = new particleAttr[particleNum];
	particleArray = new ParticleSystem.Particle[particleNum];
	Debug.Log (particleArray.Length);
	particleSystem.maxParticles = particleNum;
	particleSystem.Emit(particleNum);
	particleSystem.GetParticles(particleArray);

	aKeys = new GradientAlphaKey[5];
	//设置渐变来实现部分亮度不同
	aKeys [0].time = 0f; aKeys [0].alpha = 1f;
	aKeys [1].time = 0.4f; aKeys [1].alpha = 0.4f;
	aKeys [2].time = 0.6f; aKeys [2].alpha = 1f;
	aKeys [3].time = 0.8f; aKeys [3].alpha = 0.4f;
	aKeys [4].time = 1f; aKeys [4].alpha = 0.9f;
	cKeys = new GradientColorKey[2];
	cKeys [0].time = 0f; cKeys [0].color = Color.white;
	cKeys [1].time = 1f; cKeys [1].color = Color.white;
	colorGradient.SetKeys (cKeys, aKeys);

	setParticle ();//设置粒子属性
}
void Hover(float minRadius, float maxRadius) {
	int speedLevel = 10;//设置不同的速度级别
	for (int i = 0; i < particleNum; i++) {
		//收缩
		if (attribute [i].radius > hoverRadius [i]) {
			attribute [i].radius -= collectSpeed;
		} else if (attribute [i].radius < hoverRadius [i] - 1f){
			attribute [i].radius += collectSpeed;
		}
		//粒子浮动实现
 attribute[i].time += Time.deltaTime; attribute[i].radius += Mathf.PingPong(attribute[i].time / 8f / 10f, 0.02f) - 0.02f / 2.0f; particleArray [i].color = colorGradient.Evaluate (attribute [i].particleAngle / 360f);float newSpeed = (i % speedLevel + 1) * (2f / attribute[i].radius / speedLevel);if (attribute [i].clockWise) {attribute [i].particleAngle -= newSpeed;} else {attribute [i].particleAngle += newSpeed;}attribute [i].particleAngle = (360f + attribute [i].particleAngle) % 360f;float radOfAngle = attribute [i].particleAngle / 180 * Mathf.PI;particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * attribute [i].radius, Mathf.Sin (radOfAngle) * attribute [i].radius, 0);}particleSystem.SetParticles (particleArray, particleArray.Length);}void notHover(float minRadius, float maxRadius) {int speedLevel = 10; //设置不同的速度级别//扩散for (int i = 0; i < particleNum; i++) {if (attribute [i].radius < notHoverRadius [i]) {attribute [i].radius += collectSpeed;} else if (attribute [i].radius > notHoverRadius [i] + 1f) {attribute [i].radius -= collectSpeed;}
		//粒子浮动实现
		attribute[i].time += Time.deltaTime;  
		attribute[i].radius += Mathf.PingPong(attribute[i].time / 5f / 12f, 0.02f) - 0.02f / 2.0f;  

		particleArray [i].color = colorGradient.Evaluate (attribute [i].particleAngle / 360f);


		float newSpeed = (i % speedLevel + 1) * (2f / attribute[i].radius / speedLevel);
			//判断顺逆时钟
		if (attribute [i].clockWise) {
			attribute [i].particleAngle -= newSpeed;
		} else {
			attribute [i].particleAngle += newSpeed;
		}

		attribute [i].particleAngle = (360f + attribute [i].particleAngle) % 360f;

		float radOfAngle = attribute [i].particleAngle / 180 * Mathf.PI;

		particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * attribute [i].radius, Mathf.Sin (radOfAngle) * attribute [i].radius, 0);
	}
	particleSystem.SetParticles (particleArray, particleArray.Length);
}

需求5:

在这里我通过添加一个button的UI组件,在上面挂上buttonScript代码来监听鼠标事件,在MyParticleSystem里实现扩散和收缩。
在buttonScript中:
public ParticleSystem ps;
// Use this for initialization
public void OnPointerEnter (PointerEventData eventData) {
	ps.GetComponent<MyParticleSystem> ().ifHover = true;
}
	
// Update is called once per frame
public void OnPointerExit (PointerEventData eventData) {
	ps.GetComponent<MyParticleSystem> ().ifHover = false;
}

在MyParticleSystem中:
void Update() {
	Debug.Log (ifHover);
	//判断是否悬停,采取不同的移动方法
	if (ifHover) {
		Hover (8f, 9f);
	} else {
		notHover (5f, 12f);
	}
}

完整代码:

buttonScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class buttonScript : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
	public ParticleSystem ps;
	// Use this for initialization
	public void OnPointerEnter (PointerEventData eventData) {
		ps.GetComponent<MyParticleSystem> ().ifHover = true;
	}
	
	// Update is called once per frame
	public void OnPointerExit (PointerEventData eventData) {
		ps.GetComponent<MyParticleSystem> ().ifHover = false;
	}
}


MyParticleSystem:
using UnityEngine;
using System.Collections;

public class MyParticleSystem : MonoBehaviour
{
	public ParticleSystem particleSystem;
	public Gradient colorGradient;

	public bool ifHover = false; //判断是否鼠标悬停

	private ParticleSystem.Particle[] particleArray; //储存粒子
	private float[] hoverRadius; //记录收缩时的半径
	private float[] notHoverRadius;//记录扩散时的半径

	GradientAlphaKey[] aKeys;
	GradientColorKey[] cKeys;

	private class particleAttr {
		public float particleAngle; //角度
		public bool clockWise; //移动时钟方向
		public float radius; //半径
		public float originalRadius; //变化前的半径
		public float offset = 0.01f;
		public float time; //时间

		public particleAttr(float p, bool c, float r, float t) {
			particleAngle = p;
			clockWise = c;
			radius = r;
			originalRadius = r;
			time = t;
		}
	}

	private float maxOffSet = 0.1f;
	private float midRadius; //平均半径

	private particleAttr[] attribute; //储存粒子属性

	public int particleNum = 10000; //粒子个数
	private float collectSpeed = 0.3f; //粒子收缩速度

	void Start() {
		//初始化粒子
		hoverRadius = new float[particleNum];
		notHoverRadius = new float[particleNum];
		attribute = new particleAttr[particleNum];
		particleArray = new ParticleSystem.Particle[particleNum];
		Debug.Log (particleArray.Length);
		particleSystem.maxParticles = particleNum;
		particleSystem.Emit(particleNum);
		particleSystem.GetParticles(particleArray);

		aKeys = new GradientAlphaKey[5];
		//设置渐变来实现部分亮度不同
		aKeys [0].time = 0f; aKeys [0].alpha = 1f;
		aKeys [1].time = 0.4f; aKeys [1].alpha = 0.4f;
		aKeys [2].time = 0.6f; aKeys [2].alpha = 1f;
		aKeys [3].time = 0.8f; aKeys [3].alpha = 0.4f;
		aKeys [4].time = 1f; aKeys [4].alpha = 0.9f;
		cKeys = new GradientColorKey[2];
		cKeys [0].time = 0f; cKeys [0].color = Color.white;
		cKeys [1].time = 1f; cKeys [1].color = Color.white;
		colorGradient.SetKeys (cKeys, aKeys);

		setParticle ();//设置粒子属性
	}

	void setParticle() {
		bool clock = true;
		for (int i = 0; i < particleNum; i++) {
			//处理粒子集中分布于平均半径
			float midRadius = (5f + 12f) / 2;
			float minRate = Random.Range (1f, midRadius / 5f);
			float maxRate = Random.Range (midRadius / 12f, 1f);
			float radius = Random.Range (5f * minRate, 12f * maxRate);
			notHoverRadius [i] = radius;
			//记录收缩后的半径
			float hradius = Random.Range (8f, 9f);
			hoverRadius [i] = hradius;

			float angle = Random.Range (0f, 360f);
			float t = Random.Range (0f, 10f);
			attribute [i] = new particleAttr (angle, clock, radius, t);
			//分成顺逆时钟移动
			if (clock) {
				clock = false;
			} else {
				clock = true;
			}
			float radOfAngle = angle / 180 * Mathf.PI;

			particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * radius, Mathf.Sin (radOfAngle) * radius, 0);
		}
		particleSystem.SetParticles (particleArray, particleArray.Length);
	}

	void Update() {
		Debug.Log (ifHover);
		//判断是否悬停,采取不同的移动方法
		if (ifHover) {
			Hover (8f, 9f);
		} else {
			notHover (5f, 12f);
		}
	}

	void Hover(float minRadius, float maxRadius) {
		int speedLevel = 10;//设置不同的速度级别
		for (int i = 0; i < particleNum; i++) {
			//收缩
			if (attribute [i].radius > hoverRadius [i]) {
				attribute [i].radius -= collectSpeed;
			} else if (attribute [i].radius < hoverRadius [i] - 1f){
				attribute [i].radius += collectSpeed;
			}
			attribute[i].time += Time.deltaTime;  
			attribute[i].radius += Mathf.PingPong(attribute[i].time / 8f / 10f, 0.02f) - 0.02f / 2.0f;  

			particleArray [i].color = colorGradient.Evaluate (attribute [i].particleAngle / 360f);


			float newSpeed = (i % speedLevel + 1) * (2f / attribute[i].radius / speedLevel);
			if (attribute [i].clockWise) {
				attribute [i].particleAngle -= newSpeed;
			} else {
				attribute [i].particleAngle += newSpeed;
			}

			attribute [i].particleAngle = (360f + attribute [i].particleAngle) % 360f;

			float radOfAngle = attribute [i].particleAngle / 180 * Mathf.PI;

			particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * attribute [i].radius, Mathf.Sin (radOfAngle) * attribute [i].radius, 0);
		}
		particleSystem.SetParticles (particleArray, particleArray.Length);
	}

	void notHover(float minRadius, float maxRadius) {
		int speedLevel = 10; //设置不同的速度级别
		//扩散
		for (int i = 0; i < particleNum; i++) {
			if (attribute [i].radius < notHoverRadius [i]) {
				attribute [i].radius += collectSpeed;
			} else if (attribute [i].radius > notHoverRadius [i] + 1f) {
				attribute [i].radius -= collectSpeed;
			}
			attribute[i].time += Time.deltaTime;  
			attribute[i].radius += Mathf.PingPong(attribute[i].time / 5f / 12f, 0.02f) - 0.02f / 2.0f;  

			particleArray [i].color = colorGradient.Evaluate (attribute [i].particleAngle / 360f);


			float newSpeed = (i % speedLevel + 1) * (2f / attribute[i].radius / speedLevel);
			//判断顺逆时钟
			if (attribute [i].clockWise) {
				attribute [i].particleAngle -= newSpeed;
			} else {
				attribute [i].particleAngle += newSpeed;
			}

			attribute [i].particleAngle = (360f + attribute [i].particleAngle) % 360f;

			float radOfAngle = attribute [i].particleAngle / 180 * Mathf.PI;

			particleArray [i].position = new Vector3 (Mathf.Cos (radOfAngle) * attribute [i].radius, Mathf.Sin (radOfAngle) * attribute [i].radius, 0);
		}
		particleSystem.SetParticles (particleArray, particleArray.Length);
	}
}

Unity组件设置:

1.相关组件:

2.button设置:

3.粒子系统设置:
  








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值