UnityEffects(3)之闪电链

今天来分享一下Untiy中实现闪电链的方法,实际在项目中使用,效果不错。

国际惯例:

UnityEffects(3)之闪电链_第1张图片

来张会动的:


工程放在:https://github.com/aceyan/UnityEffects 使用unity5.4

场景是Scene/(3)ChainLightning

 

使用了unity的lineRender来模拟闪电的效果:

 UnityEffects(3)之闪电链_第2张图片

主要功能都在UVChainLightning这个脚本中:


using System;
using System.Collections.Generic;
using UnityEngine;
///
/// uv贴图闪电链
///
[RequireComponent(typeof(LineRenderer))]
[ExecuteInEditMode]
public classUVChainLightning :MonoBehaviour
{
    //美术资源中进行调整
    public float detail = 1;//增加后,线条数量会减少,每个线条会更长。
    public float displacement = 15;//位移量,也就是线条数值方向偏移的最大值
 
    public Transform target;//链接目标
    public Transform start;
    public float yOffset = 0;
    private LineRenderer _lineRender;
    private List _linePosList;
 
 
    private void Awake()
    {
        _lineRender =GetComponent();
        _linePosList = new List();
    }
 
    private void Update()
    {
        if(Time.timeScale != 0)
        {
            _linePosList.Clear();
            Vector3 startPos =Vector3.zero;
            Vector3 endPos =Vector3.zero;
            if (target != null)
            {
                endPos =target.position + Vector3.up *yOffset;
            }
            if(start != null)
            {
                startPos =start.position + Vector3.up *yOffset;
            }
 
            CollectLinPos(startPos,endPos, displacement);
           _linePosList.Add(endPos);
 
           _lineRender.SetVertexCount(_linePosList.Count);
            for (int i = 0, n = _linePosList.Count; i< n; i++)
            {
               _lineRender.SetPosition(i, _linePosList[i]);
            }
        }
    }
 
    //收集顶点,中点分形法插值抖动
    private void CollectLinPos(Vector3 startPos,Vector3 destPos,float displace)
    {
        if (displace < detail)
        {
           _linePosList.Add(startPos);
        }
        else
        {
 
            float midX = (startPos.x + destPos.x) / 2;
            float midY = (startPos.y + destPos.y) / 2;
            float midZ = (startPos.z + destPos.z) / 2;
 
            midX += (float)(UnityEngine.Random.value - 0.5) * displace;
            midY += (float)(UnityEngine.Random.value - 0.5) * displace;
            midZ += (float)(UnityEngine.Random.value - 0.5) * displace;
 
            Vector3 midPos =newVector3(midX,midY,midZ);
 
            CollectLinPos(startPos,midPos, displace / 2);
            CollectLinPos(midPos,destPos, displace / 2);
        }
    }
 
 
}   


 

代码十分简单,可以看到使用了一个递归的分治算法来生成闪电链各段的位置。然后设置lineRender的position集合来模拟闪电效果,加入uv动画效果更佳:) 也可以根据需要优化成迭代算法。

原理原文:http://krazydad.com/bestiary/bestiary_lightning.html

=。=好像原文挂掉了,记得原文是带flash演示的,莫非因为flash日薄西山了,作者就把原文“下架”了?为flash默哀…

下面搬运一下雷文顿大神对原文的翻译,原文:http://blog.csdn.net/u012945598/article/details/18862091

UnityEffects(3)之闪电链_第3张图片

这部短片使用了中点位移法来模拟闪电。

中点位移法通常是用于生成分形地形的算法,你会发现闪电的形状类似于一个理想化的山脉的边缘。

下面节选的这段闪电递归程序可以帮你完成所有的工作。

function drawLightning(x1,y1,x2,y2,displace)
{
  if (displace
    graf.moveTo(x1,y1);
    graf.lineTo(x2,y2);
  }
  else {
    varmid_x = (x2+x1)/2;
    varmid_y = (y2+y1)/2;
    mid_x+= (Math.random()-.5)*displace;
    mid_y+= (Math.random()-.5)*displace;
    drawLightning(x1,y1,mid_x,mid_y,displace/2);
    drawLightning(x2,y2,mid_x,mid_y,displace/2);
  }
}

你可以通过传递一个线段的两个端点坐标(x1,y1,x2,y2)和一个位移量,计算出线段终点坐标(mid_x,mid_y),然后通过一个随机值替换它,该随机值按照每次划分线段时的位移值比例减少。

UnityEffects(3)之闪电链_第4张图片


第一次划分会得到一个较大的位移线段,而之后随着位移值的减小位移线段也会逐渐减小(每次递归位移值都会除以2),如此便可以使一条线段"碎形"。

当位移值低于我们定义的最小值时(可使用"detail"滑动条修改),我们就将这条线绘制出来。也就是说满足条件if(displace

原文中的四个滑动条:


1.detail 增加后,线条数量会减少,每个线条会更长。

2.thickness 代表线条的粗细

3.number bolts 代表线条的数量

4.displacement 位移量,也就是线条数值方向偏移的最大值

 

 

 

Ps:之前在Untiy 的Asset Store还看到这么一个闪电效果的插件

https://www.assetstore.unity3d.com/en/#!/content/5141

看了代码发现是粒子系统模拟的,生成很多的粒子连接起来模拟闪电的效果。效果会比较”浓厚一些”。后来也模仿着在游戏中实现了一个,发现粒子少了容易穿帮,粒子多了性能成问题,所以这个粒子模拟的方式不推荐手游使用。

你可能感兴趣的:(游戏开发,unity3D)