Unity 3D Game 粒子光环

介绍

参考 http://i-remember.fr/en 制作类似该网站效果

基本步骤

创建粒子光环(空对象)

将摄像机背景置为黑色

创建粒子系统,配置参数

新建 C# 脚本,命名为 ParticleRing

ParticleRing.cs

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
using System.Collections;using System.Collections.Generic;using UnityEngine;

public class  : MonoBehaviour{	public class circleParticle	{		public float radius = 0.0f;		public float angle = 0.0f;		public float time = 0.0f;		public circleParticle(float radius, float angle, float time)		{			this.radius = radius;			this.angle = angle;			this.time = time;		}	}

	public ParticleSystem particleSystem; 	private ParticleSystem.Particle[] particlesArray; // 粒子数组	private circleParticle[] particleAttr; //粒子属性数组	public int particleSum = 10000; // 粒子数量	public float minRadius = 5.0f;	public float maxRadius = 10.0f;	public int Part = 2; // 将粒子们分为两部分	public float minSpeed = 0.09f;	public float maxSpeed = 0.12f;	public float speedLevelSum = 9; // 粒子速度分为九层	public float driftRange = 0.03f; // 游离范围

	public Gradient colorGradient;  

	void Start()	{		particleAttr = new circleParticle[particleSum];		particlesArray = new ParticleSystem.Particle[particleSum];		particleSystem.maxParticles = particleSum;		particleSystem.Emit(particleSum);		particleSystem.GetParticles(particlesArray);

		// 初始化梯度颜色控制器  		GradientAlphaKey[] alphaKeys = new GradientAlphaKey[5];  		alphaKeys[0].time = 0.0f; alphaKeys[0].alpha = 1.0f;  		alphaKeys[1].time = 0.4f; alphaKeys[1].alpha = 0.4f;  		alphaKeys[2].time = 0.6f; alphaKeys[2].alpha = 1.0f;  		alphaKeys[3].time = 0.9f; alphaKeys[3].alpha = 0.4f;  		alphaKeys[4].time = 1.0f; alphaKeys[4].alpha = 0.9f;  		GradientColorKey[] colorKeys = new GradientColorKey[2];  		colorKeys[0].time = 0.0f; colorKeys[0].color = Color.white;  		colorKeys[1].time = 1.0f; colorKeys[1].color = Color.white;  		colorGradient.SetKeys(colorKeys, alphaKeys);  

		for (int i = 0; i < particleSum; i++)		{			// 随机产生角度			float randomAngle = Random.Range(0.0f, 360.0f);

			// 随机产生每个粒子距离中心的半径,同时粒子要集中在平均半径附近			float midRadius = (maxRadius + minRadius) / 2;			float minRate = Random.Range(1.0f, midRadius / minRadius);			float maxRate = Random.Range(midRadius / maxRadius, 1.0f);			float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

			// 随机时间			float randomTime = Random.Range (0, 10f);

			//粒子属性设置			particleAttr[i] = new circleParticle(randomRadius, randomAngle, randomTime);			particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);		}		//设置粒子		particleSystem.SetParticles(particlesArray, particleSum);	}

	void Update()	{		for (int i = 0; i < particleSum; i++)		{			// 速度方向分为两部分,一部分顺时针,一部分逆时针			float speed = (i % Part == 0) ? Random.Range(minSpeed, maxSpeed) : - 2 * Random.Range(minSpeed, maxSpeed);			// 给不同的粒子速度加权,分为 9 层			float weightedSpeed = (i % speedLevelSum + 1) * speed;

			// 更新角度			particleAttr[i].angle += Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比			particleAttr[i].angle = particleAttr[i].angle % 360;			float radian = particleAttr[i].angle / 180 * Mathf.PI;            // 更新半径			particleAttr [i].time += Time.deltaTime;			particleAttr [i].radius += Mathf.PingPong(particleAttr [i].time / minRadius / maxRadius, driftRange) - driftRange / 2.0f;            // 更新位置            particlesArray[i].position = new Vector3(particleAttr [i].radius * Mathf.Cos(radian), particleAttr [i].radius * Mathf.Sin(radian), 0f);

			particlesArray[i].color = colorGradient.Evaluate(particleAttr[i].angle / 360.0f);		}		particleSystem.SetParticles(particlesArray, particleSum);	}}

效果图

鼠标悬停在粒子光环内部效果

修改 circleParticle

添加 originRadius ,用以记录光环收缩前当前粒子的旋转半径

1234567891011121314
public class circleParticle{	public float radius = 0.0f;	public float angle = 0.0f;	public float time = 0.0f;	public float originRadius = 0.0f;	public circleParticle(float radius, float angle, float time)	{		this.radius = radius;		this.angle = angle;		this.time = time;		this.originRadius = radius;	}}

修改 update()

判断鼠标与光环的关系

123456789101112131415
// 鼠标到光环中心的距离float mouseToCenter = Mathf.Sqrt (Mathf.Pow((Input.mousePosition.x - Screen.width / 2), 2f) + Mathf.Pow((Input.mousePosition.y - Screen.height / 2), 2f));// 鼠标在光环内部bool mouseInRing = false;// 此处认为满足此条件,即是在光环内部if (mouseToCenter < Screen.height / 4) {	mouseInRing = true;	if (mouseInRingTime <= mouseInRingTimeLimit) { // 在粒子光环里面的累计时间每一帧加一,并不会大过限定值		mouseInRingTime++;	}} else { // 鼠标移出粒子光环	mouseInRing = false;	if (mouseInRingTime > 0)		mouseInRingTime--;}

根据鼠标与光环关系进行的行为

123456789101112131415161718192021222324
// 当鼠标在粒子光环里当时间累积为零if (mouseInRingTime == 0) {    particleAttr [i].originRadius = particleAttr[i].radius;}

// 鼠标进入粒子光环if (mouseInRing){    particleAttr[i].angle -= 1 / 3 * Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比    particleAttr[i].angle = particleAttr[i].angle % 360;    radian = particleAttr[i].angle / 180 * Mathf.PI;    if (mouseInRingTime < mouseInRingTimeLimit) {        particleAttr [i].radius = minRadius + (particleAttr [i].radius - minRadius) * (particleAttr [i].radius / maxRadius);    }}// 鼠标在粒子光环外if (!mouseInRing && mouseInRingTime > 0){    particleAttr[i].angle += mouseInRingTime / 5 * Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比    particleAttr[i].angle = particleAttr[i].angle % 360;    radian = particleAttr[i].angle / 180 * Mathf.PI;

    particleAttr [i].radius += (particleAttr [i].originRadius - particleAttr [i].radius) / Mathf.Sqrt(mouseInRingTime) * (particleAttr [i].radius / maxRadius);}

完整代码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
using System.Collections;using System.Collections.Generic;using UnityEngine;

public class  : MonoBehaviour{	public class circleParticle	{		public float radius = 0.0f;		public float angle = 0.0f;		public float time = 0.0f;		public float originRadius = 0.0f;		public circleParticle(float radius, float angle, float time)		{			this.radius = radius;			this.angle = angle;			this.time = time;			this.originRadius = radius;		}	}

	public ParticleSystem particleSystem; 	private ParticleSystem.Particle[] particlesArray; // 粒子数组	private circleParticle[] particleAttr; //粒子属性数组	public int particleSum = 10000; // 粒子数量	public float minRadius = 5.0f;	public float maxRadius = 10.0f;	public int Part = 2; // 将粒子们分为两部分	public float minSpeed = 0.09f;	public float maxSpeed = 0.12f;	public float speedLevelSum = 9; // 粒子速度分为九层	public float driftRange = 0.03f; // 游离范围	public int mouseInRingTime;	public int mouseInRingTimeLimit;

	public Gradient colorGradient;  

	void Start()	{		particleAttr = new circleParticle[particleSum];		particlesArray = new ParticleSystem.Particle[particleSum];		particleSystem.maxParticles = particleSum;		particleSystem.Emit(particleSum);		particleSystem.GetParticles(particlesArray);

		// 初始化梯度颜色控制器  		GradientAlphaKey[] alphaKeys = new GradientAlphaKey[5];  		alphaKeys[0].time = 0.0f; alphaKeys[0].alpha = 1.0f;  		alphaKeys[1].time = 0.4f; alphaKeys[1].alpha = 0.4f;  		alphaKeys[2].time = 0.6f; alphaKeys[2].alpha = 1.0f;  		alphaKeys[3].time = 0.9f; alphaKeys[3].alpha = 0.4f;  		alphaKeys[4].time = 1.0f; alphaKeys[4].alpha = 0.9f;  		GradientColorKey[] colorKeys = new GradientColorKey[2];  		colorKeys[0].time = 0.0f; colorKeys[0].color = Color.white;  		colorKeys[1].time = 1.0f; colorKeys[1].color = Color.white;  		colorGradient.SetKeys(colorKeys, alphaKeys);  

		mouseInRingTime = 0;		mouseInRingTimeLimit = 30;

		for (int i = 0; i < particleSum; i++)		{			// 随机产生角度			float randomAngle = Random.Range(0.0f, 360.0f);

			// 随机产生每个粒子距离中心的半径,同时粒子要集中在平均半径附近			float midRadius = (maxRadius + minRadius) / 2;			float minRate = Random.Range(1.0f, midRadius / minRadius);			float maxRate = Random.Range(midRadius / maxRadius, 1.0f);			float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

			// 随机时间			float randomTime = Random.Range (0, 10f);

			//粒子属性设置			particleAttr[i] = new circleParticle(randomRadius, randomAngle, randomTime);			particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);		}		//设置粒子		particleSystem.SetParticles(particlesArray, particleSum);	}

	void Update()	{		// 鼠标到光环中心的距离		float mouseToCenter = Mathf.Sqrt (Mathf.Pow((Input.mousePosition.x - Screen.width / 2), 2f) + Mathf.Pow((Input.mousePosition.y - Screen.height / 2), 2f));		// 鼠标在光环内部		bool mouseInRing = false;		// 此处认为满足此条件,即是在光环内部		if (mouseToCenter < Screen.height / 4) {			mouseInRing = true;			if (mouseInRingTime <= mouseInRingTimeLimit) { // 在粒子光环里面的累计时间每一帧加一,并不会大过限定值				mouseInRingTime++;			}		} else { // 鼠标移出粒子光环			mouseInRing = false;			if (mouseInRingTime > 0)				mouseInRingTime--;		}

		for (int i = 0; i < particleSum; i++)		{			// 速度方向分为两部分,一部分顺时针,一部分逆时针			float speed = (i % Part == 0) ? Random.Range(minSpeed, maxSpeed) : - 2 * Random.Range(minSpeed, maxSpeed);			// 给不同的粒子速度加权,分为 9 层			float weightedSpeed = (i % speedLevelSum + 1) * speed;

			// 更新角度			particleAttr[i].angle += Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比			particleAttr[i].angle = particleAttr[i].angle % 360;			float radian = particleAttr[i].angle / 180 * Mathf.PI;            // 更新半径			particleAttr [i].time += Time.deltaTime;			particleAttr [i].radius += Mathf.PingPong(particleAttr [i].time / minRadius / maxRadius, driftRange) - driftRange / 2.0f;

			// 当鼠标在粒子光环里当时间累积为零			if (mouseInRingTime == 0) {				particleAttr [i].originRadius = particleAttr[i].radius;			}

			// 鼠标进入粒子光环			if (mouseInRing)			{				particleAttr[i].angle -= 1 / 3 * Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比				particleAttr[i].angle = particleAttr[i].angle % 360;				radian = particleAttr[i].angle / 180 * Mathf.PI;				if (mouseInRingTime < mouseInRingTimeLimit) {					particleAttr [i].radius = minRadius + (particleAttr [i].radius - minRadius) * (particleAttr [i].radius / maxRadius);				}			}			// 鼠标在粒子光环外			if (!mouseInRing && mouseInRingTime > 0)			{				particleAttr[i].angle += mouseInRingTime / 5 * Mathf.Sqrt(2 * particleAttr [i].radius / maxRadius) * weightedSpeed; // 此处粒子的速度与半径的平方根成正比				particleAttr[i].angle = particleAttr[i].angle % 360;				radian = particleAttr[i].angle / 180 * Mathf.PI;

				particleAttr [i].radius += (particleAttr [i].originRadius - particleAttr [i].radius) / Mathf.Sqrt(mouseInRingTime) * (particleAttr [i].radius / maxRadius);			}

            // 更新位置            particlesArray[i].position = new Vector3(particleAttr [i].radius * Mathf.Cos(radian), particleAttr [i].radius * Mathf.Sin(radian), 0f);

			particlesArray[i].color = colorGradient.Evaluate(particleAttr[i].angle / 360.0f);		}		particleSystem.SetParticles(particlesArray, particleSum);	}}

最终效果

引用

Unity3D学习笔记(9)—— 粒子光环
Unity-3D 粒子光圈效果

原文:大专栏  Unity 3D Game 粒子光环

原文地址:https://www.cnblogs.com/chinatrump/p/11615073.html

时间: 2024-10-05 21:01:54

Unity 3D Game 粒子光环的相关文章

【Unity 3D】学习笔记四十二:粒子特效

粒子特效 粒子特效的原理是将若干粒子无规则的组合在一起,来模拟火焰,爆炸,水滴,雾气等效果.要使用粒子特效首先要创建,在hierarchy视图中点击create--particle system即可 粒子发射器 粒子发射器是用于设定粒子的发射属性,比如说粒子的大小,数量和速度等.在创建完粒子对象后,在右侧inspector视图中便可以看到所有的粒子属性: emit:是否是使用粒子发射器. min size:粒子最小尺寸. max size:粒子最大尺寸. min energy:粒子的最小生命周期

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

【Unity 3D】学习笔记三十二:游戏元素——游戏光源

游戏光源 在3D游戏中,光源是一个非常具有特色的游戏组件.用来提升游戏画面质感的.如果没有加入光源,游戏场景可能就会显得很昏暗.在unity中提供了三种不同的光源类型:点光源,聚光灯,平行光. 点光源 顾名思义,点光源是从一个点向周围散发出光的光源,就像电灯一样.创建点光源在hierarchy视图中点击create--point light: 创建完以后,点击点光源对象,在右侧inspector视图中可以看到点光源的所有信息: type:光源的类型.有point(点光源),directional

【Unity 3D】学习笔记四十五:游戏实例——击垮围墙

用这个游戏实例来总结之前我们复习的所有关于物理引擎的知识.在游戏中,发送一个球形的炮弹来击垮前面的墙.给炮弹与墙都添加了刚体组件,给炮弹绑定了粒子系统,并且在炮弹的粒子动画中添加了5组不同的颜色,显示移动轨迹. using UnityEngine; using System.Collections; public class Script_06_14 : MonoBehaviour { //炮弹对象 private GameObject obj; //准心贴图 public Texture te

【Unity 3D】学习笔记二十八:unity工具类

unity为开发者提供了很多方便开发的工具,他们都是由系统封装的一些功能和方法.比如说:实现时间的time类,获取随机数的Random.Range( )方法等等. 时间类 time类,主要用来获取当前的系统时间. using UnityEngine; using System.Collections; public class Script_04_13 : MonoBehaviour { void OnGUI() { GUILayout.Label("当前游戏时间:" + Time.t

Unity 3D 实战核心技术详解 书籍出版

经过半年的努力,处女作<Unity 3D 实战核心技术详解>终于问世了,购买网址: http://www.broadview.com.cn/article/70 在12月5日到12日期间,在打折的基础上优惠,书籍内容全是干货,购买方式:可以查看网页中的"如何购买".

unity 3d yield 用法总结

最近,需要需要用unity 3d做点东西,但是了碰到了延迟加载问题,我总结余下: Coroutines & Yield是unity3d编程中重要的概念,它可以实现将一段程序延迟执行或者将其各个部分分布在一个时间段内连续执行,但是在Javascript与C#中实现Coroutines & Yield,在语法上却有一些区别: javascript中yield用法很简单,直接yield就行了,或者yield WaitForSeconds (2); c#中的用法如下: yield不可单独使用 需要

Unity 3d中Shader是什么,可以吃吗?

众所周知,Unity3d是一款跨平台非常广的游戏引擎,上手容易,界面友好,集成功能众多,是目前开发手游的主流引擎.本人有幸使用Unity 3d进行开发已一年多时间,已领略了这歀引擎的强大之处. 编写shader也是我工作内容的一部分,先来说说shader是什么吧,我以自己的理解说明一下: 首先 shader是一种语言,一种在GPU,也就是显卡上执行的高级语言.shader的本意是着色器,可以自定义GPU的渲染管线中的两个环节(即顶点和片段).由此,我们可以控制对象在屏幕上的渲染效果,甚至实现一些

【图说】Eclipse与Unity 3D协同工作

原地址:http://blog.csdn.net/h570768995/article/details/9355313 Eclipse开发过程中总会碰到很多的难题,如何利用好工具帮助我们更快捷的开发也是一件重要事. 下面介绍Eclipse与Unity 3D协同工作: 1,首先在Unity3D中简单建立一个工程文件 2,好的,接下来点击[File]->[Build setting] 3,然后点击[Build],记好你Build出来的.apk的名字.这时候在工程目录下会出现“temp”文件夹(没有B