GJM : 用Unity模仿CSGO里的火焰效果 [转载]
本文章由天天不在编写,转载请注明出处。 所有权利保留。
文章链接:http://www.cnblogs.com/zhouxin/p/5910257.html
作者:天天不在
CSGO里的火焰效果和真实的情况比较像,能沿着遮挡物前进,如下是模仿效果。
思路比较简单,开始想的是一圈一圈发出去,但是前圈与后圈的联系不好做,换种思路,每个方向发射一条线,这样根据上一个位置的方位先向前进,如果前面有遮挡,则计算好新的位置与方向,反之前面没有遮挡,选择合适的位置,并从这个方向的上面向下检测,检测这个方向的垂直位置有没遮挡,如果有遮挡,计算新的方向与位置,没有,则表明延展不下去。如下图所示.
相关主要代码:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/ / 根据一条线的上一个节点,确定这个节点如何定位 bool forward ( ref Vector 3 pos , ref Quaternion quat ) { var forward = quat * Vector 3. forward; var up = quat * Vector 3. up ; var nextPos = pos + forward * radius; RaycastHit hit; / / 前面有没挡住 / / Debug.DrawRay ( nextPos , forward , Color.red , 100 ) ; var hitForward = Physics.Raycast ( nextPos , forward , out hit , radius * 2 ) ; var hitDown = false ; / / 如果前面没有挡住 , 检查垂直位置 if ( !hitForward ) { / / height用来控制垂直扩展的高度 var upPos = pos + 2 * forward * radius + up * height * 2 ; / / Debug.DrawRay ( upPos , - up , Color.green , 100 ) ; hitDown = Physics.Raycast ( upPos , - up , out hit , height * 4 ) ; } if ( hitForward || hitDown ) { / / 新的位置 pos = hit.point + hit.normal * prefabHeight; / / Debug.DrawRay ( pos , hit.normal , Color.blue , 100 ) ; quat = Quaternion.FromToRotation ( up , hit.normal ) * quat; return true ; } return false ; } |
如上代码每句都加上了注释,我们添加了一个radius参数,用来表示每次前进的步子大小,radius越小,则越密集,然后添加一个height参数用来表示垂直方向升降能力,可以看下图。
确定一条线上显示后,我们只要考虑沿着周围全部扩展就行,在这我们用level表示扩展多少层,层数越多,我们每条线的相隔的角度也应该越小,如下效果。
相关代码:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/ / 分成多条线向外扩散 public void extend ( ) { / / 分成多条线 count = ( int ) ( 2 * level * Mathf.PI ) ; / / 每条偏移角度 angle = 360.0 f / count; var up = transform.rotation * Vector 3. up ; for ( int i = 0 ; i < count; i + + ) { var curAngle = angle * i; var curQuat = Quaternion.AngleAxis ( curAngle , up ) ; var quat = curQuat * transform.rotation; / / forward ( transform. position , quat , level , i ) ; StartCoroutine ( forward ( transform. position , quat , level , i ) ) ; } } / / 每条线向前扩展,自动翻越遮挡 public IEnumerator forward ( Vector 3 pos , Quaternion quat , int level , int place ) { var npos = pos; var nquat = quat; int curLevel = 1 ; var prePos = npos; while ( curLevel < = level & & forward ( ref npos , ref nquat ) ) { / / Debug.DrawLine ( prePos , npos , Color.blue , 100 f , true ) ; if ( bCreate ( curLevel , place ) ) { var offset = offsetPos ( nquat , 1 ) ; var obj = Instantiate ( getPrefab ( curLevel ) , npos + offset , nquat ) ; / / Debug.DrawLine ( prePos , npos , Color.blue , 100 f , true ) ; var duration = getDuration ( curLevel ) ; Destroy ( obj , duration ) ; } yield return new WaitForSeconds ( deltaTime ) ; curLevel + + ; prePos = npos; } } |
这些蓝线确定了火焰沿线步局,但是现在最中心会比较密集,我们需要有选择的是否生成,如下图:
相关代码:
1
2
3
4
5
6
7
8
9
|
/ / 确定当前层上的某个位置是否需要生成 bool bCreate ( int level , int place ) { / / 当前需要显示的个数 var levelCount = ( int ) ( 2 * level * Mathf.PI ) ; var levelLength = Mathf.RoundToInt ( ( float ) count / levelCount ) ; / / 每层起点偏移一点位置 var offset = place + level ; return offset % levelLength = = 0 ; } |
这样就能简单在每层生成合适的个数,其中最上面有个prefabHeight,用来控制模型中心与下边的高度,用来控制生成的模型贴着遮挡物,如图:
如下是完整代码:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
using UnityEngine; using System.Collections; public class FireMove : MonoBehaviour { public GameObject[] particlePrefabs; [Tooltip ( "半径越小,模型越密集" ) ] public float radius = 0.5 f; [Tooltip ( "高度越大,模型能越过更高的遮挡物" ) ] public float height = 0.5 f; [Tooltip ( "层级越多,向外扩展的导数越多" ) ] public int level = 10 ; [Tooltip ( "每层间隔生成时间" ) ] public float deltaTime = 0.1 f; [Tooltip ( "控制火焰显示时间" ) ] public float duration = 5.0 f; [Tooltip ( "水平偏移" ) ] public float offsetHeight = 0.1 f; [Tooltip ( "高度偏移" ) ] public float offsetPanel = 0.2 f; [Tooltip ( "模型与地面的距离" ) ] public float prefabHeight = 0.0 1 f; private int count; private float angle; #if UNITY_EDITOR public void Update ( ) { if ( Input.GetKeyDown ( KeyCode.K ) ) { extend ( ) ; } } #endif public void attack ( int level ) { this. level = level ; extend ( ) ; } / / 分成多条线向外扩散 public void extend ( ) { / / 分成多条线 count = ( int ) ( 2 * level * Mathf.PI ) ; / / 每条偏移角度 angle = 360.0 f / count; var up = transform.rotation * Vector 3. up ; for ( int i = 0 ; i < count; i + + ) { var curAngle = angle * i; var curQuat = Quaternion.AngleAxis ( curAngle , up ) ; var quat = curQuat * transform.rotation; / / forward ( transform. position , quat , level , i ) ; StartCoroutine ( forward ( transform. position , quat , level , i ) ) ; } } / / 每条线向前扩展,自动翻越遮挡 public IEnumerator forward ( Vector 3 pos , Quaternion quat , int level , int place ) { var npos = pos; var nquat = quat; int curLevel = 1 ; var prePos = npos; while ( curLevel < = level & & forward ( ref npos , ref nquat ) ) { / / Debug.DrawLine ( prePos , npos , Color.blue , 100 f , true ) ; if ( bCreate ( curLevel , place ) ) { var offset = offsetPos ( nquat , 1 ) ; var obj = Instantiate ( getPrefab ( curLevel ) , npos + offset , nquat ) ; / / Debug.DrawLine ( prePos , npos , Color.blue , 100 f , true ) ; var duration = getDuration ( curLevel ) ; Destroy ( obj , duration ) ; } yield return new WaitForSeconds ( deltaTime ) ; curLevel + + ; prePos = npos; } } / / 确定当前层上的某个位置是否需要生成 bool bCreate ( int level , int place ) { / / 当前需要显示的个数 var levelCount = ( int ) ( 2 * level * Mathf.PI ) ; var levelLength = Mathf.RoundToInt ( ( float ) count / levelCount ) ; / / 每层起点偏移一点位置 var offset = place + level ; return offset % levelLength = = 0 ; } public GameObject getPrefab ( int curLevel ) { var prfabCount = particlePrefabs.Length; / / var t = Mathf.RoundToInt ( prfabCount * ( curLevel - 1 ) / level ) ; var index = Random.Range ( 0 , prfabCount ) ; return particlePrefabs[ index ]; } / / 加上偏移 public Vector 3 offsetPos ( Quaternion quat , int level ) { var xAxis = quat * Vector 3. right * Random.Range ( - offsetPanel , offsetPanel ) * level ; var zAxis = quat * Vector 3. forward * Random.Range ( - offsetPanel , offsetPanel ) * level ; var yAxis = quat * Vector 3. up * Random.Range ( - offsetHeight , offsetHeight ) * level ; return xAxis + zAxis + yAxis; } / / 每层的生命周期 float getDuration ( int level ) { var levelDuration = duration - 2 * level * deltaTime; return levelDuration; } / / 根据一条线的上一个节点,确定这个节点如何定位 bool forward ( ref Vector 3 pos , ref Quaternion quat ) { var forward = quat * Vector 3. forward; var up = quat * Vector 3. up ; var nextPos = pos + forward * radius; RaycastHit hit; / / 前面有没挡住 / / Debug.DrawRay ( nextPos , forward , Color.red , 100 ) ; var hitForward = Physics.Raycast ( nextPos , forward , out hit , radius * 2 ) ; var hitDown = false ; / / 如果前面没有挡住 , 检查垂直位置 if ( !hitForward ) { / / height用来控制垂直扩展的高度 var upPos = pos + 2 * forward * radius + up * height * 2 ; / / Debug.DrawRay ( upPos , - up , Color.green , 100 ) ; hitDown = Physics.Raycast ( upPos , - up , out hit , height * 4 ) ; } if ( hitForward || hitDown ) { / / 新的位置 pos = hit.point + hit.normal * prefabHeight; / / Debug.DrawRay ( pos , hit.normal , Color.blue , 100 ) ; quat = Quaternion.FromToRotation ( up , hit.normal ) * quat; return true ; } return false ; } } |
直接放到一个物体上就可以了,其中radius设为相应的火焰半径大小就可,如果要密一些,降低一些就行,相应offset参数用来设定水平与垂直上的偏移,免的给人太规律了,代码上都有详细注释,可以自己改动。
GJM : 用Unity模仿CSGO里的火焰效果 [转载]的更多相关文章
- 用Unity模仿CSGO里的火焰效果
CSGO里的火焰效果和真实的情况比较像,能沿着遮挡物前进,如下是模仿效果. 思路比较简单,开始想的是一圈一圈发出去,但是前圈与后圈的联系不好做,换种思路,每个方向发射一条线,这样根据上一个位置的方位先 ...
- js模仿jquery里的几个方法parent, parentUntil, children
有时工作需要, 也是接着上一章的方法, 用js模仿jquery里的几个方法parent, parentUntil, children. function parent(node){ return no ...
- GJM:Unity导入百度地图SDK [转载]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- GJM :Unity集成Leap Motion
Demo演示视频
- GJM :Unity使用EasyAR实现脱卡功能
首先说下大致思路当卡片离开摄像头时间,ImageTarget-Image的SetActive (false),所以其子物体(model)也就不显示了,因此解决的办法就是在Target (false)时 ...
- GJM :Unity 使用SqlServer数据库 [原创]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创 ,未经作者同意必须保留此段声明! ...
- unity, 在OnDisable里一定要将Cloth禁掉
如果在OnDisable中不将Cloth组件禁掉,则当物体再次激活时布料将变形.
- js模仿jquery里的几个方法next, pre, nextAll, preAll
/*siblings函数, 选取node的所有兄弟节点*/ function siblings(node){ if(node.nodeType === 1){ node.flag = true; // ...
- 模仿jq里的选择器和color样式
(function(){ HTMLElement.prototype.css = function () { var option; if (arguments.length > 0) { op ...
随机推荐
- 如何正确选择UI自动化测试
近年流行一个词-UI,和UI搭边好像都那么高大上,软件测试行业也不例外,比如UI自动化测试. 常见的UI自动化测试程序有哪些呢? l 带UI的Unit Test,比如mock掉底层代码,仅仅测试UI ...
- 练习2 练习目标-使用引用类型的成员变量:在本练习中,将扩展银行项目,添加一个(客户类)Customer类。Customer类将包含一个Account对象。
package banking; public class Customer { private String firstName; private String lastName; private ...
- 数据访问模式:数据并发控制(Data Concurrency Control)
1.数据并发控制(Data Concurrency Control)简介 数据并发控制(Data Concurrency Control)是用来处理在同一时刻对被持久化的业务对象进行多次修改的系统.当 ...
- KendoUI系列:Window
1.基本使用 <link href="@Url.Content("~/Content/kendo/2014.1.318/kendo.common.min.css") ...
- ECMAScript 位运算符
位运算符是在数字底层(即表示数字的 32 个数位)进行操作的. 重温整数 ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数).在 ECMAScript ...
- 正则表达式之JSP、Android
对于正则表达式,很多朋友一定不陌生,因为在我们做网站或apk时,当需要用户提交表单时,很多时间需要判断用户的输入是否合法,这个时间正则表达式就可以发挥它的作用了,我们知道正则表达式在这个方面是很强大的 ...
- Oracle之DBMS_RANDOM包详解
DBMS_RANDOM是Oracle提供的一个PL/SQL包,用于生成随机数据和字符.它具有以下函数. 其中,initialize,random,terminate函数在Oracle11g中已不推荐使 ...
- 如何用Python寻找重复文件并删除
在实际生活中,经常会有文件重复的困扰,即同一个文件可能既在A目录中,又在B目录中,更可恶的是,即便是同一个文件,文件名可能还不一样.在文件较少的情况下,该类情况还比较容易处理,最不济就是one by ...
- Linux:文件权限
Linux:文件权限 1.文件权限 ☆文件所有者 ☆用户组 ☆其他人 ☆ROOT 说明: Linux系统中默认所有系统上的账号与一般身份用户,还有那个root的相关信息记录在/etc/passwd文件 ...
- Docker - Docker国内镜像的配置及使用
Docker国内镜像 DaoCloud - Docker加速器 阿里云 - 开发者平台 微镜像 - 希云cSphere 镜像广场 - 时速云 灵雀云 网易蜂巢 阿里云的Docker加速器 阿里云 - ...