在Unity3D中開發射擊遊戲的一些思路(1)
阿新 • • 發佈:2019-01-28
最近有許多朋友問到我一個問題,如何實現像戰地,使命召喚那樣逼真的射擊體驗。首先我們要知道,在沒有動畫師的幫助下,要想實現人為模擬的後坐力,精準度偏移等等其實並不是什麼難事,今天我們就來用較簡短的程式碼來實現一個模擬的槍械後坐力。
首先是我們需要用到的工具類程式碼:
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); } }
這是我們在進行模擬時最常用的一個演算法,我稱之為彈簧演算法(實在起不出好名字了嘿嘿),演算法非常簡單,我們只需要把自己的value輸入進去,作為希望插值的目標,然後呼叫Update函式就可以讓value以彈性姿勢像target靠攏,需要注意的是damp和frequency這兩個浮點數的用處,可以看到damp越高插值速率越高,越快的趨近於目標點,而frequency越高彈簧震動的越快,我們在之後的模擬中會用到這兩個值的。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; } }
通過使用彈簧演算法,我們可以很輕鬆的實現一個讓擡起的槍口歸位的動作,那麼我們怎麼實現一套完整的後坐力弧線呢。要知道我們在開槍的時候(去過射擊場的朋友應該知道),槍口是呈現一個類似拋物線的運動,在扣動扳機瞬間槍口迅速上擡,隨即在胳膊與胸口的壓力下槍的上擡幅度慢慢降低並開始下降,降到開槍前的點,所以我們需要在程式碼中模擬這一系列動作。
這時有同學就會問了,直接把攝像機或者槍的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並且掛載到攝像機或者模型上,執行點選左鍵就可以看出效果,只不過要想實現自己理想的後坐力,需要通過不停的調參來獲得令自己滿意,令策劃滿意的效果。