参考http://Lightning - Procedural Lightning - AAA Quality, Performance and Sound. Dozens of Prefabs. 2D + 3D.,针对项目做了比较大的修改,原理是一致的:

1. 使用LineRenderer组件随机闪电的路径;

2. 通过截取材质贴图显示区域使闪电看起来更多样。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(LineRenderer))]
public class DynamicLightningBoltItem : MonoBehaviour
{//闪电每次闪烁模式public enum LightningBoltMode{None,Random,Loop,PingPong}[Tooltip("闪电分段"), Range(0, 8), SerializeField]private int segment = 6;[Tooltip("闪电持续时长"), SerializeField]private float multDuration = 1;[Tooltip("闪电闪烁时长"), SerializeField]private float onceDuration = 0.05f;[Tooltip("混乱偏移指数"), Range(0.0f, 1.0f), SerializeField]private float chaosFactor = 0.15f;//一张贴图可以存放多个闪电切图,每次随机截取其中一部分,看起来闪电随机多样[Tooltip("纹理中的行数"), SerializeField]public int matTextureRows = 1;[Tooltip("纹理中的列数"), SerializeField]public int matTextureColumns = 1;[Tooltip("闪烁动画模式"), SerializeField]private LightningBoltMode animationMode = LightningBoltMode.None;//随机数,可以多个闪电同一个随机数,形成相同的闪电外观private System.Random randomGenerator = new System.Random();//材质求贴图尺寸/偏移private Vector2 matTextureSize;private Vector2[] matTextureOffset;private LineRenderer lineRenderer;//动画参数private int animationOffsetIndex;private int animationPingPongDir = 1;//闪电起始/结束为止private Transform startTrans;private Transform endTrans;private void Awake(){lineRenderer = GetComponent<LineRenderer>();lineRenderer.positionCount = 0;if (matTextureColumns < 1)matTextureColumns = 1;if (matTextureRows < 1)matTextureRows = 1;if (matTextureRows * matTextureColumns < 2 && animationMode != LightningBoltMode.None){animationMode = LightningBoltMode.None;}SetMaterialTextute();}#region --- Test ---private Transform startPoint;private Transform endPoint;private float testTimer;private void Start(){startPoint = new GameObject("StartPoint").transform;endPoint = new GameObject("EndPoint").transform;startPoint.SetParent(transform);endPoint.SetParent(transform);startPoint.localPosition = Vector3.zero;multDuration = 100;StartLightning(startPoint, endPoint);}private void Update(){if(testTimer >= 1){testTimer = 0;endPoint.localPosition = Random.onUnitSphere * 10;}testTimer += Time.deltaTime;}#endregionpublic void StartLightning(Transform startPoint, Transform endPoint){startTrans = startPoint;endTrans = endPoint;StopAllCoroutines();if (startTrans == null || endTrans == null){lineRenderer.positionCount = 0;return;}StartCoroutine(TriggerMultLightning());}public void StopLightning(){StopAllCoroutines();lineRenderer.positionCount = 0;}private IEnumerator TriggerMultLightning(){float timer = 0;while (timer < multDuration){if (startTrans == null || endTrans == null)break;GenerateLightning(startTrans.position, endTrans.position, segment);timer += onceDuration;yield return new WaitForSeconds(onceDuration);}lineRenderer.positionCount = 0;}//设置材质贴图的尺寸private void SetMaterialTextute(){matTextureSize = new Vector2(1.0f / matTextureColumns, 1.0f / matTextureRows);lineRenderer.material.mainTextureScale = matTextureSize;matTextureOffset = new Vector2[matTextureRows * matTextureColumns];for (int y = 0; y < matTextureRows; y++){for (int x = 0; x < matTextureColumns; x++){matTextureOffset[x + (y * matTextureColumns)] = new Vector2((float)x / matTextureColumns, (float)y / matTextureRows);}}}private void GenerateLightning(Vector3 startPoint, Vector3 endPoint, int segment){List<(Vector3, Vector3)> segmentList = new List<(Vector3, Vector3)>();segmentList.Add((startPoint, endPoint));if (segment > 0 && segment <= 8){int startIndex = 0;float offsetAmount = (endPoint - startPoint).magnitude * chaosFactor;Vector3 middlePoint;for (int i = 0; i < segment; i++){//每次循环将新的分段数据添加至列表//previousIndex/startIndex标记上次循环的起始/结束位置//使用上次循环计算的结果作为下次循环的源数据,计算分段数据int previousIndex = startIndex;startIndex = segmentList.Count;for (int j = previousIndex; j < startIndex; j++){startPoint = segmentList[j].Item1;endPoint = segmentList[j].Item2;//插入中点middlePoint = (startPoint + endPoint) * 0.5f;//随机偏移中点middlePoint += GetRandomVector(startPoint, endPoint, offsetAmount);//添加两个新分段segmentList.Add((startPoint, middlePoint));segmentList.Add((middlePoint, endPoint));}//每循环一次,闪电偏移减半offsetAmount *= 0.5f;}//移除多余分段segmentList.RemoveRange(0, startIndex);}UpdateLineRenderer(segmentList);}private Vector3 GetRandomVector(Vector3 start, Vector3 end, float offsetAmount){Vector3 directionNormalized = (end - start).normalized;Vector3 perpendicularNormal = GetPerpendicularVector(directionNormalized);//随机偏移距离float distance = ((float)randomGenerator.NextDouble() + 0.1f) * offsetAmount;//随机旋转角度float rotationAngle = (float)randomGenerator.NextDouble() * 360.0f;//绕着方向旋转,然后由垂直向量偏移return Quaternion.AngleAxis(rotationAngle, directionNormalized) * perpendicularNormal * distance;}private Vector3 GetPerpendicularVector(Vector3 directionNormalized){if (directionNormalized == Vector3.zero){return Vector3.right;}else{// use cross product to find any perpendicular vector around directionNormalized:// 0 = x * px + y * py + z * pz// => pz = -(x * px + y * py) / z// for computational stability use the component farthest from 0 to divide byfloat x = directionNormalized.x;float y = directionNormalized.y;float z = directionNormalized.z;float px, py, pz;float ax = Mathf.Abs(x);float ay = Mathf.Abs(y);float az = Mathf.Abs(z);if (ax >= ay && ay >= az){// x is the max, so we can pick (py, pz) arbitrarily at (1, 1):py = 1.0f;pz = 1.0f;px = -(y * py + z * pz) / x;}else if (ay >= az){// y is the max, so we can pick (px, pz) arbitrarily at (1, 1):px = 1.0f;pz = 1.0f;py = -(x * px + z * pz) / y;}else{// z is the max, so we can pick (px, py) arbitrarily at (1, 1):px = 1.0f;py = 1.0f;pz = -(x * px + y * py) / z;}return new Vector3(px, py, pz).normalized;}}private void UpdateLineRenderer(List<(Vector3, Vector3)> segmentList){if (segmentList == null || segmentList.Count == 0){lineRenderer.positionCount = 0;return;}lineRenderer.positionCount = segmentList.Count + 1;lineRenderer.SetPosition(0, segmentList[0].Item1);for (int i = 0; i < segmentList.Count; i++){lineRenderer.SetPosition(i + 1, segmentList[i].Item2);}SelectOffsetFromAnimationMode();}private void SelectOffsetFromAnimationMode(){int index = 0;switch (animationMode){case LightningBoltMode.None://固定第一个贴图index = 0;break;case LightningBoltMode.Random://贴图列表中随机index = randomGenerator.Next(0, matTextureOffset.Length);break;case LightningBoltMode.Loop://贴图列表中循环index = animationOffsetIndex++;if (animationOffsetIndex >= matTextureOffset.Length)animationOffsetIndex = 0;break;case LightningBoltMode.PingPong://贴图列表中循环index = animationOffsetIndex;animationOffsetIndex += animationPingPongDir;if (animationOffsetIndex >= matTextureOffset.Length){animationOffsetIndex = matTextureOffset.Length - 2;animationPingPongDir = -1;}else if (animationOffsetIndex < 0){animationOffsetIndex = 1;animationPingPongDir = 1;}break;default:break;}if (index < 0 || index >= matTextureOffset.Length)index = 0;lineRenderer.material.mainTextureOffset = matTextureOffset[index];}}

【Unity】使用LineRenderer实现闪电效果相关推荐

  1. unity组件LineRenderer

    这是一个好玩的组件 主要作用划线,像水果忍者中的刀光,还有一些涂鸦的小游戏,包括让鼠标划线然后让对象进行跟踪导航也可通过此插件完成 附注:unity版本建议使用稳定一些的版本,有些api可能已经发生变 ...

  2. Unity之ASE如何实现UV扰动闪电效果

    前言 UV扰动,顾名思义,就是通过干扰原贴图的UV,使UV发生变化,导致贴图出现会动的效果,如果我们贴图和扰动的速度调整的刚好合适的话,会出现一些非常棒的效果,比如下图所示的闪电效果: 又或者下面这张 ...

  3. Unity使用LineRenderer组件画出菱形,长度,角度可任意调节

    首先说下我的思路: 开始想的比较简单,就是先建两个空物体分别挂上脚本,一个在X轴画直线,一个与X轴成angle夹角,通过计算得出坐标,这样就能画出一个菱形的角度,下面是实例图: 最后再写个脚本通过循环 ...

  4. Unity 使用LineRenderer绘制贝塞尔曲线

    Unity 使用LineRenderer绘制贝塞尔曲线 LineRenderer介绍 LineRenderer线渲染器,在三维空间中渲染线段和曲线段. 贝塞尔曲线介绍 通过很少的控制点,生成复杂的平滑 ...

  5. 怎么用计算机弹出惊雷,会声会影闪电效果_怎么用会声会影绘制惊雷闪电地效果_飞翔教程...

    漆黑的夜空,轰隆隆的雷声连绵不绝于耳,不时倏忽一现的闪电也趁机跳起了谁也不知道下一步踏在何处的热情舞步,诸多影片中惊雷闪电的效果真是让人过目难忘!那么这一切真的全是摄像师们苦苦留守雨夜摄录下来的吗?其 ...

  6. unity 制作书本 翻页效果

    unity 制作书籍翻页效果 unity C# 翻书效果 2D 真实翻页 不使用插件 自制 实现思路: 将书本分为两边,一边一个翻页实现: 下图为书本的右面,以OA为分界线,△OAB是下一面的如上图的 ...

  7. 试着在unity实现阴阳师抽卡效果

    试着在unity实现阴阳师抽卡效果 之前为了社团活动(DemoDay,一个展示社团成员游戏作品的社团展会)做了一个抽奖程序.因为是硬核游戏开发社团举办的游戏展,我为此特地做了一个阴阳师的抽卡系统如下 ...

  8. Unity从零开始实现一个全息效果Shader

    Unity从零开始实现一个全息效果Shader 前言 开始捣鼓 一.准备阶段 二.先从透明效果开始 三.顶点故障效果 四.扫描线效果 五.菲尼尔反射效果 六.颗粒效果 七.颜色故障效果 CustomE ...

  9. unity实现吸附功能的效果

    unity实现吸附功能的效果随笔 物体移动到墙体一定距离会被吸附到墙体上面 这个一定的距离根据代码 Vector3 scale = boxCol.transform.localScale+ new V ...

最新文章

  1. 改变2020年及未来的8大人工智能趋势
  2. 全世界最前沿的125个科学问题
  3. Android SQlite数据库的使用(三)-将数据库文件连同应用程序一起发布
  4. java step1:基础知识5(java中Timer和TimerTask的使用)
  5. QT+OpenCV照片动画风格转换
  6. CentOS 6 安装Hadoop 2.6 (一)准备工作
  7. 怎样基于谷歌地图的Server缓存公布Image Service服务
  8. spring学习(38):注入set类型
  9. python 绘图 hist bin参数_Python-hist,distplot bin宽度不一致问题的解决方案
  10. python 实现对地图的点击_python实现Pyecharts实现动态地图(Map、Geo)
  11. javascript匿名函数及闭包深入理解及应用
  12. python selenium+pywin32 实现网页另存为
  13. nagios监控php使用情况,给nagios增加监控当前php进程数的插件,并用pnp出图
  14. webpack—模块化、模块化核心、ESM、其它模块化|概念、安装、使用、打包模块、打包配置、核心配置、深入、Loaders、||Plugins、sourceMap、WebpackDevServer、
  15. 什么是平面设计?详细讲解平面设计
  16. oracle mysql收费_oracle 数据库收费标准
  17. C#身份证号码验证代码
  18. 超全面UI基础设计规范
  19. HQChart使用教程60-新版k线训练使用教程
  20. Cent OS 7 的日常操作

热门文章

  1. 重装系统后打不开我的世界服务器手机版,我的世界最新版为什么进不去
  2. 测试思维面试题最新整理,有它遇到hr不用慌了
  3. Python3使用turtle画一个十边形
  4. 2019ccpc省赛榜单
  5. python学习 | 视频的封面提取
  6. 明日方舟愚人号地图设计反推
  7. python画四边形_Python之OpenGL笔记(12):画纹理四边形
  8. 苹果android什么意思,用惯了安卓机的人,换了iphone以后是什么感受?
  9. 什么?听说很多Java老司机都栽在了这四个概念上?
  10. Android 屏幕适配方案(多分辨率适配)