2019-08-20 11:20:30 weixin_38744526 阅读数 10698

最近在写论文做毕业设计,真是一个头两个大。写过论文的伙伴一定都懂,头发一撮一撮地掉,好心痛!

我的毕设需要用到树莓派编程然后转接到Unity3D利用多媒体投影显示内容,这中间需要用到网络通信多线程。

查了一些资料,决定选择Python Socket来实现功能。Socket是任何一种计算机网络通讯中最基础的内容,网上也能查到好多Python Socket 套接字编程的指南和教程。

不过,教程太多弄得我眼花缭乱,也没明白Socket通信多线程是咋回事,偶然发现了一个讲Python 多线程的小视频,我觉得讲的超详细,很容易懂,特来分享给大家~

如果你也想知道Python多线程是怎么实现的,跟我一起看看下方视频,听知名技术专家李刚老师对Socket多线程和Python的TCP支持与创建TCP服务端的详细解析,

并发编程+网络编程

李刚老师出版的《疯狂java》体系图书曾得到市场的广泛认可,经过多次再版,并被多家高校选作教材。上方视频来自于李刚老师的在线视频课程《21天通关Python》第八章 并发编程+网络编程

鉴于大家都有学习Python的困惑,今天就给大家推荐一本巨有影响力的Python实战书,上线时间仅2个月,就超越了众多实力派,成京东和当当网上的长期畅销图书,并且收获了3.4W的五星好评。

这本书可谓是笔者独家私藏图书之一了,对我学习Python有着莫大的帮助,在京东上也常常"断货",这次拿出来给大家分享一下,希望能帮到大家。

《21天通关Python》视频课程以畅销图书为教材,由图书作者李刚亲自操刀讲解;上手门槛低,可作为0基础掌握Python教材;书籍+线上复合型学习场景特别适合Python小白学习!

点此查看课程:https://edu.csdn.net/bundled/detail/49?utm_source=jiansuopy58_1
(含图书邮寄+视频教程+社群答疑+导师带队)

笔者跟大家分享一个福利!下单时输入优惠码csdn66,立减20元,券后仅需99元
扫码入Python技术交流群,可免费听技术讲座+领学习资料+视频课免费看
在这里插入图片描述

2018-05-29 13:56:57 qq_36297981 阅读数 418

参考网站首页的光环效果:http://i-remember.fr/en
用unity3d的粒子系统做一个粒子光环
向上效果图
这里写图片描述

可以看到该粒子效果由两部分组成,一部分是粒子光环,另一部分是粒子海洋

设计方法:

    粒子的运动由程序来控制
    光环的粒子使用cos,sin以及圆环半径来确定位置
    粒子海洋中的粒子运动使用柏林噪声来控制
步骤一

新建一个空对象(ParticleHalo),在空对象下载新建两个空对象(Ring, SeaParticle),两个空对象都添加上粒子系统
这里写图片描述

步骤二

新建脚本RingParticle来控制光环中的粒子的运动

public class RingParticle : MonoBehaviour{
    void Start(){}
    void Update(){}
}

为RingParticle添加一些必要的参数

private ParticleSystem ps; //粒子系统(必须)
private ParticleSystem.Particle[] particles; //粒子系统中的粒子(必须)
public int count = 1000; //粒子数量
public float size = 0.3f; //粒子大小,非必须,可在inspector视图中的粒子系统中设置
public float maxRadius = 12f;//圆环的最大半径
public float minRadius = 5f;//圆谎的最小半径
public Gradient gradient; //用来给粒子添加颜色特效
private float[] radiuses; //粒子的半径
private float[] angles; //粒子的角度

在start函数中初始化粒子

    void Start()
    {
        particles = new ParticleSystem.Particle[count];
        radiuses = new float[count];
        angles = new float[count];
        ps = GetComponent<ParticleSystem>();
        ps.maxParticles = count; //设置粒子的数目
        ps.loop = false;//让粒子不循环播放
        ps.startSpeed = 0; //设置粒子的速度
        ps.startSize = size; //设置粒子的数量
        ps.Emit(count); //发射粒子
        ps.GetParticles(particles);
        for (int i = 0; i < count; ++i)
        {   // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近  
            float midRadius = (maxRadius + minRadius) / 2;
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);

            // 随机每个粒子的角度  
            float angle = Random.Range(0.0f, 360.0f);
            float theta = angle / 180 * Mathf.PI;
            radiuses[i] = radius;
            angles[i] = angle;
            particles[i].position = new Vector3(radius * Mathf.Cos(theta), radius * Mathf.Sin(theta), 0);
        }
        ps.SetParticles(particles, particles.Length);
    }

完成后运行,大致效果
这里写图片描述
在update函数中是粒子运动起来

void Update () {
        for (int i = 0; i < count; ++i)
        {   
            //将粒子的旋转速度分成10个不同的速度,让不同的粒子有不同的速度
            angles[i] -= (i / 100 + 1) / radiuses[i] * Random.Range(1, 3);
            angles[i] = (360.0f + angles[i]) % 360.0f;

            float theta = angles[i] / 180 * Mathf.PI;
            //让粒子的半径在一定范围内波动,产生有利效果
            radiuses[i] += Random.Range(-0.01f, 0.01f);
            particles[i].position = new Vector3(radiuses[i] * Mathf.Cos(theta), radiuses[i] * Mathf.Sin(theta), 0);
            //给粒子加上颜色特效
            particles[i].color = gradient.Evaluate(0.5f);

        }
        ps.SetParticles(particles, particles.Length);
    }

在inspector视图中设置gradient
这里写图片描述
再次运行,就可以看到旋转的粒子光环了

制作粒子海洋

可先参考博文unity制作神奇的粒子海洋
新建SeaPaticle脚本控制粒子运动

public class SeaParticle : MonoBehaviour 

给脚本添加必要的参数

 public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    public Gradient colorGradient; //粒子的眼神特效
    public int seaResolution = 50; //每行粒子的数目
    public float spacing = 0.5f;//粒子之间的间隔
    public float noiseScale = 0.2f; //
    public float heightScale = 3f;
    public float noiseX;
    public float noiseY;

初始化粒子

void Start () {
        particleSystem = GetComponent<ParticleSystem>();
        particleSystem.loop = false;
        particlesArray = new ParticleSystem.Particle[seaResolution * seaResolution];
        particleSystem.maxParticles = seaResolution * seaResolution;
        particleSystem.Emit(seaResolution * seaResolution);
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale, j * noiseScale) * heightScale;
                particlesArray[i * seaResolution + j].position = new Vector3(i * spacing, zPos, j * spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
    }

让粒子运动起来

void Update () {
      for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale + noiseX, j * noiseScale + noiseY);
                //让粒子在x、z方向上波动
                float r = Random.Range(5, 10);
                particlesArray[i * seaResolution + j].color = colorGradient.Evaluate(zPos);

                //重新设置x,y的原因是为了让粒子波动起来
                particlesArray[i * seaResolution + j].position = new Vector3((i + zPos * r) * spacing, zPos * heightScale, (j + zPos * r)* spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
        noiseX += Time.deltaTime;
        noiseY += Time.deltaTime;
    }

在inspector视图中调整参数,让粒子海洋的运动符合我们的要求
这里写图片描述
最后的静态效果

完整代码:

RingParticle

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

public class Particle : MonoBehaviour {
    private ParticleSystem ps; //粒子系统(必须)
    private ParticleSystem.Particle[] particles; //粒子系统中的粒子(必须)
    public int count = 1000; //粒子数量
    public float size = 0.3f; //粒子大小,非必须,可在inspector视图中的粒子系统中设置
    public float maxRadius = 12f;//圆环的最大半径
    public float minRadius = 5f;//圆谎的最小半径
    public Gradient gradient; //用来给粒子添加颜色特效
    private float[] radiuses; //粒子的半径
    private float[] angles; //粒子的角度
    // Use this for initialization
    void Start()
    {
        particles = new ParticleSystem.Particle[count];
        radiuses = new float[count];
        angles = new float[count];
        ps = GetComponent<ParticleSystem>();
        ps.maxParticles = count; //设置粒子的数目
        ps.loop = false;//让粒子不循环播放
        ps.startSpeed = 0; //设置粒子的速度
        ps.startSize = size; //设置粒子的数量
        ps.Emit(count); //发射粒子
        ps.GetParticles(particles);
        for (int i = 0; i < count; ++i)
        {   // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近  
            float midRadius = (maxRadius + minRadius) / 2;
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);

            // 随机每个粒子的角度  
            float angle = Random.Range(0.0f, 360.0f);
            float theta = angle / 180 * Mathf.PI;
            radiuses[i] = radius;
            angles[i] = angle;
            particles[i].position = new Vector3(radius * Mathf.Cos(theta), radius * Mathf.Sin(theta), 0);
        }
        ps.SetParticles(particles, particles.Length);
    }
    // Update is called once per frame
    void Update () {
        for (int i = 0; i < count; ++i)
        {   
            //将粒子的旋转速度分成10个不同的速度,让不同的粒子有不同的速度
            angles[i] -= (i / 100 + 1) / radiuses[i] * Random.Range(1, 3);
            angles[i] = (360.0f + angles[i]) % 360.0f;

            float theta = angles[i] / 180 * Mathf.PI;
            //让粒子的半径在一定范围内波动,产生有利效果
            radiuses[i] += Random.Range(-0.01f, 0.01f);
            particles[i].position = new Vector3(radiuses[i] * Mathf.Cos(theta), radiuses[i] * Mathf.Sin(theta), 0);
            //给粒子加上颜色特效
            particles[i].color = gradient.Evaluate(0.5f);

        }
        ps.SetParticles(particles, particles.Length);
    }
}

SeaParticel

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

public class SeaParticle : MonoBehaviour {
    public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    public Gradient colorGradient;
    public int seaResolution = 50; //每行粒子的数目
    public float spacing = 0.5f;//粒子之间的间隔
    public float noiseScale = 0.2f; //
    public float heightScale = 3f;
    public float noiseX;
    public float noiseY;
    // Use this for initialization
    void Start () {
        particleSystem = GetComponent<ParticleSystem>();
        particleSystem.loop = false;
        particlesArray = new ParticleSystem.Particle[seaResolution * seaResolution];
        particleSystem.maxParticles = seaResolution * seaResolution;
        particleSystem.Emit(seaResolution * seaResolution);
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale, j * noiseScale) * heightScale;
                particlesArray[i * seaResolution + j].position = new Vector3(i * spacing, zPos, j * spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
    }

    // Update is called once per frame
    void Update () {
      for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale + noiseX, j * noiseScale + noiseY);
                //让粒子在x、z方向上波动
                float r = Random.Range(5, 10);
                particlesArray[i * seaResolution + j].color = colorGradient.Evaluate(zPos);

                //重新设置x,y的原因是为了让粒子波动起来
                particlesArray[i * seaResolution + j].position = new Vector3((i + zPos * r) * spacing, zPos * heightScale, (j + zPos * r)* spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
        noiseX += Time.deltaTime;
        noiseY += Time.deltaTime;
    }
}
2018-05-29 17:17:55 bkjs626 阅读数 4752

要求

这次作业主要是学习粒子系统的使用,在 http://i-remember.fr/en 网站上,可以看到一个很酷炫的白色粒子光带,效果如下:
这里写图片描述
这里写图片描述

当鼠标hover到图一中间的+号圆圈中间时,光环会收缩成图二的状态,具体效果可自行前往网站体验~

我们需要模仿这个效果并尝试用粒子流编程控制来实现。

实现

光环在收缩前较为分散,位于光环中间的部分粒子较周围密集,因此我想用一个正太分布来模拟粒子在光环半径范围内的分布状况。这里我采用了Box-Muller 算法来到服从正态分布的随机数,基本思想是先得到服从均匀分布的随机数再将服从均匀分布的随机数转变为服从正态分布。关于Box-Muller 算法可参考百度百科

class Ndistribution{
    System.Random rand = new System.Random();

    public double getNormalDistribution(double mean, double stdDev)
    {
        double u1 = 1.0 - rand.NextDouble(); //uniform(0,1] random doubles
        double u2 = 1.0 - rand.NextDouble();
        double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
                     Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
        double randNormal = mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
        return randNormal;
    }
}

有了生成服从正太分布随机数的函数之后,接下来我们将用一个脚本来控制粒子的生成以及粒子坐标的变化。
首先声明一下属性:

    public int particleNum = 10000; // 粒子数目
    public float minRadius = 5.0f;  // 光环最小半径
    public float maxRadius = 10.0f; // 光环最大半径

    private ParticleSystem.Particle[] particles;
    private float[] particleAngle;  // 粒子角度
    private float[] particleR;  // 粒子半径
    private int speedLevel = 5; // 粒子旋转速度水平
    private float particleSpeed = 0.1f;  // 粒子旋转速度

    private Ray ray;
    private RaycastHit hit;

    // 收缩前粒子位置
    private float[] before;   
    // 收缩后粒子位置
    private float[] after;   
    // 粒子缩放的速度
    private float shrinkSpeed = 2f;
    private bool ischange = false;

在Start()函数中执行初始化的工作,这里的重点是为每一个粒子利用上面提到的随机数生成函数生成一个半径,同时也为它们随机生成(0, 360)之间的一个角度,这样粒子就可以根据半径与角度,形成一个圆形光环。并且还需要令刚生成的半径作为光环收缩前粒子的半径,收缩后的半径我设定为原来的0.7倍。这样一来,效果应该是从一个大的服从正太分布的光环变成一个小的光环,而理想中的效果在收缩后在最内圈的粒子比较集中。因此,我为收缩后半径小于一定数值的粒子重新生成一个收缩半径,如下面的代码所示:

    void Start () {
        particleAngle = new float[particleNum];
        particleR = new float[particleNum];
        before = new float[particleNum];
        after = new float[particleNum];
        particles = new ParticleSystem.Particle[particleNum];

        particleSystem.maxParticles = particleNum;
        particleSystem.Emit(particleNum);
        particleSystem.GetParticles(particles);

        Ndistribution nd = new Ndistribution();

        // 每个粒子在初始化的时候都设定好收缩前和收缩后的粒子半径
        for (int i = 0; i < particleNum; i++)
        {
            float r = (float)nd.getNormalDistribution((minRadius+maxRadius)*0.5f, 1);
            float angle = UnityEngine.Random.Range(0.0f, 360.0f);
            particleAngle[i] = angle;
            particleR[i] = r;

            before[i] = r;
            after[i] = 0.7f * r;

            if (after[i] < minRadius * 1.1f)
            {
                float midRadius = minRadius * 1.05f;
                after[i] = UnityEngine.Random.Range(UnityEngine.Random.Range(minRadius, midRadius), (minRadius * 1.1f));
            }
        }
    }

然后在每一帧执行Update()函数时更新所有粒子的位置,实现旋转。根据遍历粒子数组时的index的奇偶性,来区分粒子的旋转方向;同时利用不同速度级别和基本旋转速度的乘积,来实现粒子以不同速度旋转。

     // 通过奇偶控制粒子顺时针或逆时针旋转 
     if (i % 2 == 0)  
     {  
         // 逆时针
         particleAngle[i] += (i % speedLevel + 1) * particleSpeed;  
     }  
     else  
     {  
         // 顺时针
         particleAngle[i] -= (i % speedLevel + 1) * particleSpeed;  
     }  

     particleAngle[i] = particleAngle[i] % 360;
     // 转换为弧度制
     float rad = particleAngle[i] / 180 * Mathf.PI;  

     // 更新粒子坐标
     particles[i].position = new Vector3(particleR[i] * Mathf.Cos(rad), particleR[i] * Mathf.Sin(rad), 0f);  

接着还要实现鼠标悬停中间后粒子收缩的效果。unity3d不像web一样直接可以用hover,我参考了网上的博客,使用光线射击到中间物体的方法。注意这里需要为光环gameObject添加Box Collider,并设置合适的大小。

缩放的实现是根据初始化时生成的半径,逐帧更改粒子当前的半径直到与设定的大小一致。

ray = camera.ScreenPointToRay(Input.mousePosition);  
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "button") ischange = true;  
else ischange = false;  
...

if (ischange)
{
    // 开始收缩
    if(particleR[i] > after[i])
    {
        particleR[i] -= shrinkSpeed * (particleR[i] / after[i]) * Time.deltaTime;
    }
}
else
{
    // 开始还原
    if (particleR[i] < before[i])
    {
        particleR[i] += shrinkSpeed * (before[i] / particleR[i]) * Time.deltaTime;
    }
    else if (particleR[i] > before[i])
    {
        particleR[i] = before[i];
    }
}

最后附上相关参数设定:
这里写图片描述
这里写图片描述
这里写图片描述

最终效果

粒子光环

演示视频地址:https://www.bilibili.com/video/av24101271/
完整项目源码见GitHub:https://github.com/CarolSum/Unity3d-Learning/tree/master/hw7

unity3d粒子缩放

阅读数 1336

没有更多推荐了,返回首页