1. 程式人生 > >在Unity3D中開發射擊遊戲的一些思路(1)

在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並且掛載到攝像機或者模型上,執行點選左鍵就可以看出效果,只不過要想實現自己理想的後坐力,需要通過不停的調參來獲得令自己滿意,令策劃滿意的效果。