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 Vector3 pos, ref Quaternion quat) { var forward = quat * Vector3.forward; var up = quat * Vector3.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.0f / count; var up = transform.rotation * Vector3.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(Vector3 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, 100f, true); if (bCreate(curLevel, place)) { var offset = offsetPos(nquat, 1); var obj = Instantiate(getPrefab(curLevel), npos + offset, nquat); //Debug.DrawLine(prePos, npos, Color.blue, 100f, 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.5f; [Tooltip("高度越大,模型能越过更高的遮挡物")] public float height = 0.5f; [Tooltip("层级越多,向外扩展的导数越多")] public int level = 10; [Tooltip("每层间隔生成时间")] public float deltaTime = 0.1f; [Tooltip("控制火焰显示时间")] public float duration = 5.0f; [Tooltip("水平偏移")] public float offsetHeight = 0.1f; [Tooltip("高度偏移")] public float offsetPanel = 0.2f; [Tooltip("模型与地面的距离")] public float prefabHeight = 0.01f; 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.0f / count; var up = transform.rotation * Vector3.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(Vector3 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, 100f, true); if (bCreate(curLevel, place)) { var offset = offsetPos(nquat, 1); var obj = Instantiate(getPrefab(curLevel), npos + offset, nquat); //Debug.DrawLine(prePos, npos, Color.blue, 100f, 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 Vector3 offsetPos(Quaternion quat, int level) { var xAxis = quat * Vector3.right * Random.Range(-offsetPanel, offsetPanel) * level; var zAxis = quat * Vector3.forward * Random.Range(-offsetPanel, offsetPanel) * level; var yAxis = quat * Vector3.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 Vector3 pos, ref Quaternion quat) { var forward = quat * Vector3.forward; var up = quat * Vector3.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 ...
随机推荐
- Form的enctype="multipart/form-data"作用
<form class="form-horizontal" role="form" method="post" action=&quo ...
- JS面向对象逆向学习法,让难理解的统统一边去(1)~
对于面向对象我只能说呵呵了,为什么呢,因为没对象--- 既然你看到了这里,说明你有一定的基础,虽然本系列文章并不会过多的讲述基础部分,请做好心理准备. 本篇比较简单,这篇文章的意义是让你明白学习面向对 ...
- CSS多列布局
× 目录 [1]列宽 [2]列数 [3]列间距[4]列rule[5]跨列[6]列填充[7]多列 前面的话 CSS新增了多列布局特性,可以让浏览器确定何时结束一列和开始下一列,无需任何额外的标记.简单来 ...
- SQLServer学习笔记系列2
一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继续学习Sqlserver,一步一步 ...
- 170多个Ionic Framework学习资源(转载)
在Ionic官网找到的学习资源:http://blog.ionic.io/learning-ionic-in-your-living-room/ 网上的文章比较多,但是很多时候我们很难找到自己需要的. ...
- JVM之类加载器中篇
先看一段代码吧! package com.tfdd.test; /** * @desc * @author chenqm * @date 2016年2月15日 */ public class Fina ...
- JSONP实现跨域
首先提出:什么是跨域?如何解决跨域? 跨域可以简单的理解为从一个域名访问另一个域名,由于javascript的同源政策的限制,出于安全的考虑,不允许浏览器这么做.比如a.com 域名下的js无法操作b ...
- ::selection{}
::selectiion{}这是一个伪类选择器,这个是当我们在选择网页上某些文字时(通常是为了复制文字),文字的背景颜色和文字颜色都会发生变化(一般为背景变成蓝色,文字变成白色),这样的写法在IE9及 ...
- 二维码详解(QR Code)
作者:王子旭链接:https://zhuanlan.zhihu.com/p/21463650来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 2016.7.5 更新:长文 ...
- Json字符串反序列化
using DevComponents.DotNetBar; using MyControl; using Newtonsoft.Json; using System; using System.Co ...