作业8-粒子系统与流动效果

本次作业基本要求是三选一

1、简单粒子制作

  • 按参考资源要求,制作一个粒子系统,参考资源
  • 使用 3.3 节介绍,用代码控制使之在不同场景下效果不一样

2、完善官方的“汽车尾气”模拟

  • 使用官方资源资源 Vehicle 的 car, 使用 Smoke 粒子系统模拟启动发动、运行、故障等场景效果

3、参考http://i-remember.fr/en这类网站,使用粒子流编程控制制作一些效果, 如“粒子光环”

  • 可参考以前作业

这次作业我选择完成第一项和第三项。

简单粒子制作

实现效果展示

图片

代码传送门

ParticleSystem1

项目实现过程

  1. 新建一个粒子系统halo,作为光晕。按照参考资源中的教程修改参数,具体设置如下。重要的属性有:start speed = 0,说明中间部分粒子不移动。start rotation ∈ [-100, 100],说明图像有旋转,产生光晕方向变化的效果。

图片

shape选择box,可以使光晕填充粒子。color over lifetime设置为两侧黑中间白,因为光晕应该是初始暗,中间亮,最后熄灭的。

图片

renderer的material选择参考资源给出的图,因为图是2*2的,所以texture sheet animation的tiles设为x = 2、y = 2。

图片

挂上changeColor.cs。

图片

  1. 新建一个粒子系统star,作为星光。按照参考资源中的教程修改参数,具体设置如下。

图片

星光应当向四周发射,所以shape选择sphere。星光的颜色变化和光晕一样,从无到有,最后暗淡,所以color over lifetime应当是两侧黑,中间白。星光的大小应该是先大后小,所以size over lifetime的曲线设置为从大到小。

图片

texture sheet animation和renderer的设置和光晕相同,不进行详细解释了。

图片

挂上changeColor.cs。

图片

  1. 修改mainCamera的transform如下,使背景为灰色更方便观察。

图片

代码解释说明

作用是随着点击改变光晕和星光的颜色。colorA变量表示颜色,当鼠标点击时,改变colorA的值。update函数调用changecolor函数。changecolor函数根据colorA的值改变startColor,当colorA为真时,startColor是粉色,当colorA为假时,startColor是蓝紫色。

public class changeColor : MonoBehaviour
{
    private ParticleSystem particleSys;
    private bool colorA;
    private int time;
    void Start()
    {
        particleSys = this.GetComponent<ParticleSystem>();
        colorA = true;
        time = 0;
    }
    void Update()
    {
        changecolor();
    }
    void OnGUI()
    {
        if(Input.GetMouseButtonDown(0)){
            time++;
            if(time%2 == 0){
                colorA = !colorA;
            }
        }
    }
    void changecolor()
    {
        var main = particleSys.main;
        if(colorA){
            main.startColor = new ParticleSystem.MinMaxGradient(new Color(1.0f, 0.6f, 0.6f));
        }
        else{
            main.startColor = new ParticleSystem.MinMaxGradient(new Color(0.4f, 0.4f, 0.6f));
        }
    }
}

粒子光环

实现效果展示

图片

代码传送门

ParticleHalo

项目实现过程

  1. 新建粒子系统clockwise和anticlockwise。
  2. 将ParticleHalo.cs挂到clockwise和anticlockwise上,将anticlockwise的ParticleHalo的clockwise设为false,iscollected设为false,colorgradient设置成蓝红蓝。

图片

代码解释说明

  1. ParticleInfo类:包括粒子的半径、角度、时间。
public class ParticalInfo 
{
    public float radius = 0f;
    public float angle = 0f;
    public float time = 0f;
    public ParticalInfo(float radius, float angle, float time)
    {
        this.radius = radius;
        this.angle = angle;
        this.time = time;
    }
}
  1. ParticleHalo类:

首先定义了粒子系统、粒子数组、粒子信息数组和一系列变量,具体在注释中解释。

    private ParticleSystem particleSys; //粒子系统
    private ParticleSystem.Particle[] particleArr; //粒子数组 
    private ParticalInfo[] particles; //粒子信息数组
    private float[] radius; 
    private float[] collect_radius;
    private int tier = 10; //层数
    private int time = 0;
    public Gradient colorGradient; //粒子颜色
    public int particleNum = 10000; //粒子数量
    public float size = 0.1f; //粒子大小
    public float minRadius = 7.0f; //外圈的最小半径
    public float maxRadius = 10.0f; //外圈的最大半径
    public float collect_MinRadius = 1.0f; //内圈的最小半径
    public float collect_MaxRadius = 4.0f; //内圈的最大半径
    public bool clockwise = true; //顺时针/逆时针
    public float speed = 2f; //速度
    public float pingPong = 0.02f; //游离范围
    public bool isCollected = true; //内圈/外圈

start函数:实例化粒子系统,初始化各粒子的属性、粒子系统的设定。调用randomlySpread函数,作用是将粒子随机分布到轨道上,具体的实现后面会放上。

void Start () 
    {
        particleArr = new ParticleSystem.Particle[particleNum];
        particles = new ParticalInfo[particleNum];
        radius = new float[particleNum];
        collect_radius = new float[particleNum];
        particleSys = this.GetComponent<ParticleSystem>();
        particleSys.startSpeed = 0;            
        particleSys.startSize = size; 
        particleSys.loop = false;
        particleSys.maxParticles = particleNum;      
        particleSys.Emit(particleNum); 
        particleSys.GetParticles(particleArr);
        RandomlySpread();
    }

update函数:实现粒子的旋转,原理是每个粒子每一帧都加上或减掉一个值,加还是减由clockwise判断。然后区分内外圈,如果是内圈,但半径大于内圈最大半径,需要缩小半径;如果是外圈,但半径小于外圈最小半径,需要增加半径。调用PingPong函数实现粒子的漂浮。调用changeColor函数实现颜色的变化。

void Update ()
    {
        for(int i = 0; i < particleNum; i++) {
            if(clockwise){
                particles [i].angle -= (i % tier + 1) * (speed / particles [i].radius / tier);
            }
            else{
                particles [i].angle += (i % tier + 1) * (speed / particles [i].radius / tier);
            }
            particles [i].angle = (360f + particles [i].angle) % 360f;
            float theta = particles [i].angle / 180 * Mathf.PI;
            if(isCollected == true){
                if(particles [i].radius > collect_radius [i]){
                    particles [i].radius -= 15f * (collect_radius [i] / collect_radius [i]) * Time.deltaTime;  
                } 
                else{
                    particles [i].radius = collect_radius [i];
                } 
            } 
            else {
                if(particles [i].radius < radius [i]){
                    particles [i].radius += 15f * (collect_radius [i] / collect_radius [i]) * Time.deltaTime;  
                } 
                else{
                    particles [i].radius += Mathf.PingPong (particles [i].time / minRadius / maxRadius, pingPong) - pingPong / 2f;
                } 
            }
            particleArr [i].position = new Vector3 (particles [i].radius * Mathf.Cos (theta), 0f, particles [i].radius * Mathf.Sin (theta));
        }
        changeColor ();
        particleSys.SetParticles(particleArr, particleArr.Length);
    }

OnGUI函数:当按下鼠标时,改变isCollected的值,即原本的外圈变成内圈,原本的内圈变成外圈。

    void OnGUI()
    {
        if(Input.GetMouseButtonDown(0)){
            time++;
            if(time%2 == 0){
                isCollected = !isCollected;
            }
        }
    }

RandomlySpread函数:随机生成粒子的外圈半径、内圈半径、角度和时间。

void RandomlySpread()
    {
        for(int i = 0; i < particleNum; ++i){  
            float midRadius = (maxRadius + minRadius) / 2;
            float minRate = UnityEngine.Random.Range(1.0f, midRadius / minRadius);
            float maxRate = UnityEngine.Random.Range(midRadius / maxRadius, 1.0f);
            float _radius = UnityEngine.Random.Range(minRadius * minRate, maxRadius * maxRate);
            radius[i] = _radius;
            float collect_MidRadius = (collect_MaxRadius + collect_MinRadius) / 2;
            float collect_outRate = Random.Range (1f, collect_MidRadius / collect_MinRadius);
            float collect_inRate = Random.Range (collect_MaxRadius / collect_MidRadius, 1f);
            float _collect_radius = Random.Range (collect_MinRadius * collect_outRate, collect_MaxRadius * collect_inRate);
            collect_radius[i] = _collect_radius;
            float angle = UnityEngine.Random.Range(0.0f, 360.0f);
            float theta = angle / 180 * Mathf.PI;
            float time = UnityEngine.Random.Range(0.0f, 360.0f);
            if(isCollected == false){
                particles [i] = new ParticalInfo (_radius, angle, time);
            } 
            else{
                particles [i] = new ParticalInfo (_collect_radius, angle, time);
            } 
            particleArr[i].position = new Vector3(particles[i].radius * Mathf.Cos(theta), 0f, particles[i].radius * Mathf.Sin(theta));
        }
        particleSys.SetParticles(particleArr, particleArr.Length);
    }

changeColor函数:实现颜色的变化。根据开始时间、粒子的角度和colorGradient设置每个粒子的颜色。

void changeColor()
    {
        float colorValue;
        for(int i = 0; i < particleNum; i++){
            colorValue = (Time.realtimeSinceStartup - Mathf.Floor(Time.realtimeSinceStartup));
            colorValue += particles[i].angle/360;
            while (colorValue > 1) colorValue--;
            particleArr[i].startColor = colorGradient.Evaluate(colorValue);
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值