zoukankan      html  css  js  c++  java
  • 关于Unity中红外线瞄准的效果实现

    今天做一个FPS游戏的时候,由于我做的是第三人称的射击,所以需要一个枪的红外线瞄准的效果。

    一开始我在枪上挂一个很细很长的聚光灯,瞄准远处物体的时候,看起来有点红外线的样子,但是靠近之后光线就变成一个手电筒的那种光,不是我想要的效果。

    后来我用粒子特效,虽然远处近处都是一条射线,但是效果很粗糙,不是那种细细的有穿透的感觉,而是像激光一样,而且感觉不断生成粒子,性能消耗会很大。

    最后在网上看到有人用Unity3.5自带的例子AngryBots里面有红外瞄准效果,但是代码有点问题,就改了一下,感觉效果还可以。

    红外线瞄准的效果实现:

    1.创建一个空节点叫Laser,添加Line Renderer组件,里面关联一个材质,材质使用AngryBots里面的LaserMaterial.mat,材质纹理贴图是LaserTexture.psd和SimpleNoise.psd。Shader使用AngryBots里面的LaserScope.shader。这个是射线。

    2.创建一个平面叫LaserDot作为Laser节点的子节点,Scale都设置为0.02,材质使用AngryBots里面的LaserDot.mat,材质纹理贴图是LaserDot.psd和SimpleNoise.psd。Shader使用AngryBots里面的LaserScope.shader。这个是射到物体表面时的一个红色的点。

    3.创建一个脚本组件PreFrameRaycast挂载在Laser下面,用来发射一条射线,并返回射线的碰撞信息

    using UnityEngine;
    using System.Collections;
    //转载请说明出处
    
    public class PreFrameRaycast : MonoBehaviour
    {
        private RaycastHit hitInfo;
        private Transform tr;
        // Use this for initialization
        void Start()
        {
    
        }
    
        void Awake()
        {
            tr = this.transform;
        }
    
        // Update is called once per frame
        void Update()
        {
            hitInfo = new RaycastHit();
            Physics.Raycast(tr.position, tr.forward, out hitInfo);
            Debug.DrawRay(tr.position, tr.forward, Color.red);
        }
        //返回射线的碰撞信息
        public RaycastHit GetHitInfo()
        {
            if (hitInfo.Equals(null))
            {
                Debug.LogWarning("hitInfo is null");
            }
            return hitInfo;
        }
    }

    4.创建一个脚本组件pointerCtrl挂载在Laser下面,用来绘制红外射线

     打开pointerCtrl.cs

    using UnityEngine;
    using System.Collections;
    //转载请说明出处
    public class pointerCtrl : MonoBehaviour
    {
        public float scrollSpeed = 0.5f;
        public float pulseSpeed = 1.5f;
        public float noiseSize = 1.0f;
        public float maxWidth = 0.5f;
        public float minWidth = 0.5f;
        private float aniTime = 0.0f;
        private float aniDir = 1.0f;
        private LineRenderer lRenderer;
        public GameObject pointer = null;  //小红点
        private PreFrameRaycast raycast;   //光线投射
    
        void Start()
        {
            lRenderer = gameObject.GetComponent (typeof(LineRenderer)) as LineRenderer;
            raycast = gameObject.GetComponent(typeof(PreFrameRaycast)) as PreFrameRaycast;// Update is called once per frame
        }
        void Update()
        {
            //光线看起来有动感
            GetComponent<Renderer>().material.mainTextureOffset += new Vector2(Time.deltaTime * aniDir * scrollSpeed, 0);
            //设置纹理偏移量
            GetComponent<Renderer>().material.SetTextureOffset("_NoiseTex", new Vector2(-Time.time * aniDir * scrollSpeed, 0.0f));
    
            float aniFactor = Mathf.PingPong(Time.time * pulseSpeed, 1.0f);
            aniFactor = Mathf.Max(minWidth, aniFactor) * maxWidth;
            //设置光线的宽
            lRenderer.SetWidth(aniFactor, aniFactor);
            //光线的起点,枪口的地方
            lRenderer.SetPosition(0, this.gameObject.transform.position);
            if (raycast == null)
            {
                Debug.Log("raycast is null");
                return;
            }
            //获取光线的碰撞信息
            RaycastHit hitInfo = raycast.GetHitInfo();
            //光线碰撞到物体
            if (hitInfo.transform)
            {
                //光线的终点,即光线的碰撞点
                lRenderer.SetPosition(1, hitInfo.point);
                GetComponent<Renderer>().material.mainTextureScale = new Vector2(0.1f * (hitInfo.distance), GetComponent<Renderer>().material.mainTextureScale.y);
                GetComponent<Renderer>().material.SetTextureScale("_NoiseTex", new Vector2(0.1f * hitInfo.distance * noiseSize, noiseSize));
    
                if (pointer)
                {
                    pointer.GetComponent<Renderer>().enabled = true;
                    //pointer.transform.position = hitInfo.point + (transform.position - hitInfo.point) * 0.01f;
                    pointer.transform.position = hitInfo.point;
                    pointer.transform.rotation = Quaternion.LookRotation(hitInfo.normal, transform.up);
                    pointer.transform.eulerAngles = new Vector3(90, pointer.transform.eulerAngles.y, pointer.transform.eulerAngles.z);
                }
            }
            else
            {    //光线没有碰撞到物体
                if (pointer)
                {
                    pointer.GetComponent<Renderer>().enabled = false;
                }
                //光线的最大长度
                float maxDist = 200.0f;
                //当光线没有碰撞到物体,终点就是枪口前方最大距离处
                lRenderer.SetPosition(1, (this.transform.forward * maxDist));
                GetComponent<Renderer>().material.mainTextureScale = new Vector2(0.1f * maxDist, GetComponent<Renderer>().material.mainTextureScale.y);
                GetComponent<Renderer>().material.SetTextureScale("_NoiseTex", new Vector2(0.1f * maxDist * noiseSize, noiseSize));
            }
        }
    }

    5.把这个Laser节点挂在枪的指定位置作为子节点,运行的效果

  • 相关阅读:
    前端必看的数据可视化入门指南
    win10下查看进程,杀死进程
    前端如何使用proxyTable和nginx解决跨域问题
    vue-wechat-title动态修改title
    npm与cnpm混用导致的问题
    sass与less对比学习
    nginx,作为前端的你会多少?
    Ubuntu16.04安装python3.7及相应的pip
    漫游Kafka设计篇之性能优化(7)
    漫游Kafka设计篇之消息传输的事务定义(5)
  • 原文地址:https://www.cnblogs.com/HangZhe/p/7419978.html
Copyright © 2011-2022 走看看