• 感谢您的阅读。喜欢的、有用的就请大哥大嫂们高抬贵手“推荐一下”吧!你的精神支持是博主强大的写作动力以及转载收藏动力。欢迎转载!
  • 版权声明:本文原创发表于 【请点击连接前往】 ,未经作者同意必须保留此段声明!如有问题请联系我,侵立删,谢谢!
  • 我的博客:http://www.cnblogs.com/GJM6/  -  传送门:【点击前往

本文章由天天不在编写,转载请注明出处。 所有权利保留。 
文章链接:http://www.cnblogs.com/zhouxin/p/5910257.html
作者:天天不在

  CSGO里的火焰效果和真实的情况比较像,能沿着遮挡物前进,如下是模仿效果。

 

  思路比较简单,开始想的是一圈一圈发出去,但是前圈与后圈的联系不好做,换种思路,每个方向发射一条线,这样根据上一个位置的方位先向前进,如果前面有遮挡,则计算好新的位置与方向,反之前面没有遮挡,选择合适的位置,并从这个方向的上面向下检测,检测这个方向的垂直位置有没遮挡,如果有遮挡,计算新的方向与位置,没有,则表明延展不下去。如下图所示.

  相关主要代码:  

[AppleScript] 纯文本查看 复制代码
 
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表示扩展多少层,层数越多,我们每条线的相隔的角度也应该越小,如下效果。

 

  相关代码:  

[AppleScript] 纯文本查看 复制代码
 
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;
        }
    }

  这些蓝线确定了火焰沿线步局,但是现在最中心会比较密集,我们需要有选择的是否生成,如下图:

 

  相关代码:  

[AppleScript] 纯文本查看 复制代码
 
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,用来控制模型中心与下边的高度,用来控制生成的模型贴着遮挡物,如图:

 

  如下是完整代码:  

[AppleScript] 纯文本查看 复制代码
 
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里的火焰效果 [转载]的更多相关文章

  1. 用Unity模仿CSGO里的火焰效果

    CSGO里的火焰效果和真实的情况比较像,能沿着遮挡物前进,如下是模仿效果. 思路比较简单,开始想的是一圈一圈发出去,但是前圈与后圈的联系不好做,换种思路,每个方向发射一条线,这样根据上一个位置的方位先 ...

  2. js模仿jquery里的几个方法parent, parentUntil, children

    有时工作需要, 也是接着上一章的方法, 用js模仿jquery里的几个方法parent, parentUntil, children. function parent(node){ return no ...

  3. GJM:Unity导入百度地图SDK [转载]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  4. GJM :Unity集成Leap Motion

        Demo演示视频

  5. GJM :Unity使用EasyAR实现脱卡功能

    首先说下大致思路当卡片离开摄像头时间,ImageTarget-Image的SetActive (false),所以其子物体(model)也就不显示了,因此解决的办法就是在Target (false)时 ...

  6. GJM :Unity 使用SqlServer数据库 [原创]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创 ,未经作者同意必须保留此段声明! ...

  7. unity, 在OnDisable里一定要将Cloth禁掉

    如果在OnDisable中不将Cloth组件禁掉,则当物体再次激活时布料将变形.

  8. js模仿jquery里的几个方法next, pre, nextAll, preAll

    /*siblings函数, 选取node的所有兄弟节点*/ function siblings(node){ if(node.nodeType === 1){ node.flag = true; // ...

  9. 模仿jq里的选择器和color样式

    (function(){ HTMLElement.prototype.css = function () { var option; if (arguments.length > 0) { op ...

随机推荐

  1. LLBL Gen Template Studio 2.x

    Template Studio for LLBLGen Pro released Today we released Template Studio, a full-featured IDE for ...

  2. ASP.NET MVC TagBuilder使用

    ASP.NET MVC在需要进行新建HTML辅助方法时,可以来使用TagBuilder类. TagBuilder类常用方法: 方法名称 说明 AddCssClass() 可在卷标中添加一个新的Clas ...

  3. 基于TCPCopy的Dubbo服务引流工具-DubboCopy

    TCPCopy顾名思义,就是一个可以将tcp流量复制的工具(其实也可以复制UDP).有了这样一个工具,我们就可以真实的复制线上流量,然后将这些流量复制到我们的测试服务器上.这样就可以很容易模拟线上真实 ...

  4. Hard Drive Inspector Pro 4.26.208(硬盘检测工具)简体中文特别版

    Hard Drive Inspector监视硬盘错误并且接收警报,检查变化并实施诊断.例如:驱动器旋转时间增加以及数次重试才能运转驱动器通常意味着发动机和/或者轴存在可以导致数据丢失的错误.HardD ...

  5. 微软Team Foundation Service 的Scrum模板中的Feature和Backlog Items 的区别【转载】

    Features help us plan work better in Team Foundation Service Scrum process [原文:http://www.nsilverbul ...

  6. [转载]TFS源代码管理

    以下主要描述了: TFS源代码控制系统的基本场景 如何把一个项目添加到源代码管理中 如何与服务器同步 如何做Check-In 如何做分支与合并 什么是上架与下架 我们知道工作项是项目管理的基本元素,但 ...

  7. SQL查询~ 存在一个表而不在另一个表中的数据

    A.B两表,找出ID字段中,存在A表,但是不存在B表的数据.A表总共13w数据,去重后大约3W条数据,B表有2W条数据,且B表的ID字段有索引. 方法一 使用 not in ,容易理解,效率低  ~执 ...

  8. 轻松自动化---selenium-webdriver(python) (四)

    本节要解决的问题: 如何定位一组元素? 场景 从上一节的例子中可以看出,webdriver可以很方便的使用findElement方法来定位某个特定的对象,不过有时候我们却需要定位一组对象, 这时候就需 ...

  9. Git的奇技淫巧🙈

    Git的奇技淫巧

  10. Windows Azure Cloud Service (38) 微软IaaS与PaaS比较

    <Windows Azure Platform 系列文章目录> 最近一直想总结Azure IaaS和PaaS的区别与比较,写个博文详细说明一下.建议读者在阅读之前,先熟悉微软PaaS和Ia ...