關於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節點掛在槍的指定位置作為子節點,運行的效果
關於Unity中紅外線瞄準的效果實現