UnityEffects(3)之闪电链

本文介绍了如何在Unity中使用LineRenderer模拟闪电链效果,详细解析了UVChainLightning脚本中的递归分治算法,并提供了相关代码示例。通过位移算法生成分形闪电形状,适合游戏开发中的视觉特效。

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

国际惯例:


来张会动的:


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

场景是Scene/(3)ChainLightning

 

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

 

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


using System;
using System.Collections.Generic;
using UnityEngine;
///<summary>
/// uv贴图闪电链
///</summary>
[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<Vector3> _linePosList;
 
 
    private void Awake()
    {
        _lineRender =GetComponent<LineRenderer>();
        _linePosList = new List<Vector3>();
    }
 
    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


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

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

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

function drawLightning(x1,y1,x2,y2,displace)
{
  if (displace <curDetail) {
    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),然后通过一个随机值替换它,该随机值按照每次划分线段时的位移值比例减少。


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

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

原文中的四个滑动条:


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

2.thickness 代表线条的粗细

3.number bolts 代表线条的数量

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

 

 

 

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

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

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

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值