天天看點

在Unity3D中開發射擊遊戲的一些思路(1)

最近有許多朋友問到我一個問題,如何實作像戰地,使命召喚那樣逼真的射擊體驗。首先我們要知道,在沒有動畫師的幫助下,要想實作人為模拟的後坐力,精準度偏移等等其實并不是什麼難事,今天我們就來用較簡短的代碼來實作一個模拟的槍械後坐力。

首先是我們需要用到的工具類代碼:

public class Spring3
{
	public Vector3 value = Vector2.zero;
	private Vector3 dampValue = Vector2.zero;
	private float damp = 1;
	private float frequence = 1;
 	public void Clear ()
	{
		value = Vector2.zero;
		dampValue = Vector2.zero;
	}
	public Spring3 (float damp, float frequence)
	{
		this.damp = damp;
		this.frequence = frequence;
	}
	public void Update (float deltaTime, Vector3 target)
	{
		value -= dampValue * deltaTime * frequence;
		dampValue = Vector3.Lerp (dampValue, value - target, deltaTime * damp);
	}
}
           
public class SpringEulerAngle
	{
		public Vector3 value = Vector2.zero;
		private Vector3 dampValue = Vector2.zero;
		private float damp;
		private float frequence = 1;


		public SpringEulerAngle (float damp, float frequence)
		{
			this.damp = damp;
			this.frequence = frequence;
		}


		public void Clear ()
		{
			value = Vector2.zero;
			dampValue = Vector2.zero;
		}


		public void Update (float deltaTime, Vector3 target)
		{
			value -= dampValue * deltaTime * frequence;
			dampValue = eulerLerp (dampValue, value - target, deltaTime * damp);
		}


		public static Vector3 eulerLerp(Vector3 left, Vector3 right, float t){
			Vector3 ret;
			ret.x = Mathf.LerpAngle (left.x, right.x, t);
			ret.y = Mathf.LerpAngle (left.y, right.y, t);
			ret.z = Mathf.LerpAngle (left.z, right.z, t);
			return ret;
		}
	}
           

這是我們在進行模拟時最常用的一個算法,我稱之為彈簧算法(實在起不出好名字了嘿嘿),算法非常簡單,我們隻需要把自己的value輸入進去,作為希望插值的目标,然後調用Update函數就可以讓value以彈性姿勢像target靠攏,需要注意的是damp和frequency這兩個浮點數的用處,可以看到damp越高插值速率越高,越快的趨近于目标點,而frequency越高彈簧震動的越快,我們在之後的模拟中會用到這兩個值的。

通過使用彈簧算法,我們可以很輕松的實作一個讓擡起的槍口歸位的動作,那麼我們怎麼實作一套完整的後坐力弧線呢。要知道我們在開槍的時候(去過射擊場的朋友應該知道),槍口是呈現一個類似抛物線的運動,在扣動扳機瞬間槍口迅速上擡,随即在胳膊與胸口的壓力下槍的上擡幅度慢慢降低并開始下降,降到開槍前的點,是以我們需要在代碼中模拟這一系列動作。

這時有同學就會問了,直接把錄影機或者槍的transform.eulerAngles綁到上邊代碼中的value不就行了麼,這期教程不就可以結束了麼,如果這樣想我隻能說這位同學有些失了智,有靈性的同學應該已經發現了問題,單純通過一個彈簧,隻能模拟槍口歸位,但是槍口上擡這個過程就隻能強行進行角度偏移,就沒法實作我們說過的抛物線效果。是以我們應該用另一個插值來模拟一整套後坐力。将以下腳本挂載到槍或錄影機上,即可觸發後坐力。

明白了道理以後,就非常容易實作了,我們這裡寫一段非常簡單的代碼,通過點選滑鼠左鍵觸發,給目标加一段随機的角度,并且實作一個抛物線性質的偏移,注意,因為後坐力控制屬于實體運動,是以應該放在FixedUpdate中執行,FixedUpdate與Update的執行關系這裡就不贅述了。

public class Recoil : MonoBehaviour {
	SpringEulerAngle recoilTarget;
	public float damp = 20;
	public float frequence = 15;
	void Awake(){
		recoilTarget = new SpringEulerAngle (damp, frequence);
	}
	
	// Update is called once per frame
	void FixedUpdate () {
		recoilTarget.Update (Time.deltaTime, Vector3.zero);
		transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.Euler (recoilTarget.value), 0.75f);	//這裡使用一個較大的插值數字以實作槍口的迅速擡升
	}

	void Update(){
		if (Input.GetMouseButtonDown (0)) {
			recoilTarget.value = new Vector3 (Random.Range (-20, 0), Random.Range (-3, 3), 0);	//這裡做一個随機偏移來模拟後坐力。
		}
	}
}
           

将這段控制後坐力的代碼儲存為Recoil.cs并且挂載到錄影機或者模型上,運作點選左鍵就可以看出效果,隻不過要想實作自己理想的後坐力,需要通過不停的調參來獲得令自己滿意,令策劃滿意的效果。

繼續閱讀