实验任务:
实验任务:
这次我们需要参考玩野的光环效果并用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.粒子系统设置: