3D游戏第八次作业-烟花粒子效果实现 结果展示
先来个结果镇楼
下面是一个动画演示:
最终效果演示
本次项目使用的资源:
Unity Particle Pack:使用的Flame 01以及Twinkle等material均来自这个包,且该包有较多的示例。
粒子效果制作
我们的烟花分为以下5个部分组成:
其中音乐音效,Firework主体也是一个粒子系统,它拥有下辖的5个粒子系统作为子部件。我们利用粒子系统面板中的 Sub Emitters 使得Firework所发射的每个粒子都拥有子部件的粒子效果。实际上,Firework主体只是提供一个粒子的移动,具体的粒子渲染效果全部由Firework的五个子部件来完成;
我们将从各个子部件的实现开始,逐步讲解,最后在Firework中完成各个粒子效果的合并;
trail子部件
即我们的烟花在爆炸之前飞行过程中产生的尾迹:
我们可以看到,我们的尾迹中的粒子在运动过程中发生了一些变化,总结如下:
那么我们如何创建这样一个trail粒子效果呢?
twinkle子部件
twinkle子部件用于在烟花爆炸的时候产生一个闪光,模拟烟花爆炸时的闪光。
我们从这段动画中看到,粒子从小变大,然后瞬间变小,并在这个过程中微微旋转。因此,我们根据这个效果来设计我们的粒子系统;
步骤:
Explore子部件
即烟花爆炸的时候产生的球型光雨:
在图中,我们可以看到球型光雨的运动特性:
根据以上效果,我们就可以开始我们的设计;
步骤:
Fire samll子部件
即我们飞行中的烟花:
从烟花的飞行过程中我们可以看出:
根据这些,我们开始我们的制作:
设置动画: 打开Fire small的粒子系统面板,打开 Texture sheet animation 选项,设置如下:
其中Mode默认为Grid模式unity粒子特效带拖尾,不必改动。在Mode下的Tiles中的x=7, y=7表示我们将Flame 01这张图像切分为7*7的网格,网格中的每一格代表动画的一帧。我们的动画将从第一帧开始播放到最后一帧,即第49帧。其他的属性保持默认即可;这样,我们产生的粒子就会是一个自动变化的粒子。
设置粒子的发射方向: 打开Fire small的粒子系统面板,勾选 Shape 选项。并选择shape为 cone ,即从锥体的底部或顶部发射粒子。设置具体如下:
其中:
其他均为默认值即可;但是由于锥体的上底面原本的方向不是直接指向下方的,所以我们要对粒子系统进行旋转,Fire small的transform如下:
设置粒子的抖动: 可以看到我们的烟火在运动过程中是不断抖动的。这是为了模拟烟花在飞翔过程中受到气流影响造成的火焰的抖动效果,我们直接勾选 Noise 选项即可。
设置粒子颜色动态变化: 打开Fire small的粒子系统面板,勾选 color over lifetime 选项。并设置颜色如下:
因为我们原来的图片在播放动画的时候尾焰比较大,我们让动画的透明度在后面均为1,使得尾焰变小。
设置Emission和粒子系统主模板
在Fire small中的Emissionunity粒子特效带拖尾,我们没有使用Rate over time和Bursts氛围,而是使用了Rate over Distance。Rate over Distance表示每个移动距离单位发射的粒子数。也就是说,我们的Fire small在运动中才会产生粒子。
Explore2子部件
即四散的光雨效果:
可以看到,我们的Explore2实际上只是一些粒子在呈球型发散,然后每个粒子都带有我们的制作过的trail尾迹。它的实现也比较简单。trail部分和我们前面所做的trail基本相同,只是在如粒子大小以及发射粒子的数目等参数方面存在差异,之后会指出。主要的部分还是Explore2这个部件的制作;
同样的开始
Firework主体
Firework主体的功能只是为烟花提供运动,因此不会产生任何粒子,各种粒子效果将由上面制作的各个部件来完成;
步骤:
制作放烟花场景:
代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireFirework : MonoBehaviour
{
// Start is called before the first frame update
public ParticleSystem[] firework;
public ParticleSystem.Particle[] m_Particles;
void Start()
{
GameObject[] temp;
// 获取场景中所有的Firework,即烟花发射器;
temp = GameObject.FindGameObjectsWithTag("firework");
firework = new ParticleSystem[temp.Length];
Debug.Log(temp.Length);
// 将烟花发射器赋予firework数组;
for(int i = 0; i < temp.Length; ++i)
{
firework[i] = temp[i].GetComponent();
firework[i].Stop();
}
if (m_Particles == null)
{
m_Particles = new ParticleSystem.Particle[firework[0].main.maxParticles];
}
}
// Update is called once per frame
[System.Obsolete]
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
// 在随机选择场景中的一个Firework;
int id = Random.Range(0, firework.Length);
// 利用该Firework发射一个粒子,即烟花;
firework[id].Emit(1);
// 获取场景中属于firework[id]的运行中的粒子;
int count = firework[id].GetParticles(m_Particles);
// 根据鼠标点击位置计算烟花的飞行时间;
float life_time = (hit.point.y - gameObject.transform.position.y) / firework[id].startSpeed;
// 根据鼠标点击位置和烟花飞行时间计算烟花的水平速度;
float x_v = (hit.point.x - gameObject.transform.position.x)/life_time;
// 设置刚刚发射的粒子的飞行时间;
m_Particles[count - 1].lifetime = life_time;
// 设置刚刚发射的粒子的速度;
m_Particles[count - 1].velocity = new Vector3(x_v, m_Particles[count - 1].velocity.y, m_Particles[count - 1].velocity.z);
// 将改动应用到场景中;
firework[id].SetParticles(m_Particles,count);
}
}
}
}
我在场景中放置了四个Firework,每个Firework拥有不同的烟花颜色。每次发射烟花将从四个烟花发射器中选一个进行发射,并设定烟花的飞行时间以及飞行速度,保证烟花到达鼠标点击的位置就爆炸。
以下是最终的效果展示:
最终效果演示
项目地址
项目连接-传送门
文章来源:https://blog.csdn.net/qq_43996906/article/details/110478794