關於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節點掛在槍的指定位置作為子節點,運行的效果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM