文章目錄
- 今天實作的内容:
-
-
-
- 槍械的瞄準動畫層
- 槍械瞄準的邏輯實作
-
-
- BUG以及缺陷:
- 值得注意的:
今天實作的内容:
槍械的瞄準動畫層
采用了和基本移動層類似的方法,射擊動畫由腳本直接播放。

瞄準狀态的進入和退出由一個bool參數Aim來控制。
Idle和Reload層的Idle在形式上和功能上是一樣的。形式上都是一個空節點,功能是為了在目前動畫權重為1并且沒有播放本層其他動畫時依然能夠播放其他層的動畫。
權重記得設定為1。之前的Reload層也可以設定為1。
槍械瞄準的邏輯實作
由于每種槍都可能有不同的瞄準邏輯(比如不同的瞄具放大倍率啥的),我們在基類Firearms中設計了抽象方法Aim,讓子類來具體實作瞄準邏輯。
// 瞄準 每種槍的瞄準會有不同(也許吧) 放大會有不同(機瞄,二倍鏡,三倍鏡) 需要派生類來具體實作
protected abstract void Aim();
通過修改錄影機的FOV來實作瞄準放大的效果。eyeCamera是錄影機的引用,originFOV用于存儲錄影機原本的FOV值。
// 錄影機 用于瞄準時修改FOV
public Camera eyeCamera;
// 錄影機FOV的原數值
protected float originFOV;
Aim方法邏輯很簡單,由于大頭都被動畫實作了,是以我們要做的就是修改動畫參數。
// 瞄準
protected override void Aim()
{
gunAnimator.SetBool("Aim", m_isAiming);
}
重點在這裡,Update方法中的瞄準邏輯,我們專門做了一個bool值m_isAiming來判斷目前是否處于瞄準狀态。由于Aim隻是修改動畫參數,是以我們要實作的邏輯是 m_isAiming要能反映目前是否處于瞄準狀态。按住瞄準鍵就能保持瞄準狀态,松開瞄準鍵退出瞄準。
// 瞄準 按住就會瞄準
if (Input.GetMouseButtonDown(1))
{
m_isAiming = true;
Aim();
}
// 松開按鍵退出瞄準
if (Input.GetMouseButtonUp(1))
{
m_isAiming = false;
Aim();
}
在Shooting方法中修改一下動畫播放代碼,由于兩個層的開火動畫節點都叫"Fire",是以動畫名稱不用改,隻需要根據是否正在瞄準修改layer就行。
// 播放開火動畫 注意我們會根據是否處于瞄準播放不同層的Fire
gunAnimator.Play("Fire", m_isAiming ? 2 : 0, 0);
接下來定義一個協程方法DoAim來實作瞄準要做的事情。在目前DoAim隻用來實作瞄準時畫面“放大”的效果。通過調整錄影機FOV值來實作。
// 目前主要處理瞄準時視野放大功能
private IEnumerator DoAim()
{
float temp_currentFOV = 0;
while (true)
{
yield return null;
eyeCamera.fieldOfView =
Mathf.SmoothDamp(eyeCamera.fieldOfView,
m_isAiming ? m_targetFOV : originFOV,
ref temp_currentFOV,
Time.deltaTime * 10f);
if(Mathf.Abs(eyeCamera.fieldOfView - m_targetFOV) < 0.0001f)
{
eyeCamera.fieldOfView = m_targetFOV;
yield break;
}
}
}
接下來再按照UP的方式來進行防協程沖突的代碼編寫,以下代碼實作在Aim中。
// 開啟DoAim協程
if (doAimCoroutine == null) // 說明協程還沒有打開
{
doAimCoroutine = DoAim();
StartCoroutine(doAimCoroutine);
}
else // 不為空說明協程已經打開了
{
// 首先停下之前的協程
StopCoroutine(doAimCoroutine);
doAimCoroutine = null;
// 指派以後再執行起來
doAimCoroutine = DoAim();
StartCoroutine(doAimCoroutine);
}
BUG以及缺陷:
各個層由于權重都是1,是以會出現很多動畫沖突和BUG,比如瞄準時換彈并不能看到換彈但是換彈邏輯是在執行的,我覺得要麼為每個層再單獨做每個功能的動畫(就像COD16瞄準時也能換彈,而且有單獨的換彈動畫那樣),要麼就好好掰扯一下各個層的權重之間的協調。
如果在BaseLayer狀态下開槍的同時按下瞄準鍵會出現BUG,之後在瞄準開槍時動畫會在Aim Layer的Fire和Base Layer的idle(Fire?)之間快速切換。十分鬼畜。
目前這個BUG已經解決了,應該是要播放開火動畫的同時又要播放舉槍動畫所引起的BUG。方法就是在要舉槍時不要再播放開火動畫就行了。又添加了一些參數和代碼。
// ------------------------------Shooting--------------------------------------
// 是否正在舉槍 為了規避BUG 舉槍動畫播放時不能播放Fire動畫
if (!m_isAimingIn)
{
// 播放開火動畫 注意我們會根據是否處于瞄準播放不同層的Fire
gunAnimator.Play("Fire", m_isAiming ? 2 : 0, 0);
}
// ------------------------------Update---------------------------------------
// 瞄準 按住就會瞄準
if (Input.GetMouseButtonDown(1))
{
m_isAiming = true;
m_isAimingIn = true;
m_startAimInTime = Time.time;
Aim();
}
if (Input.GetMouseButtonUp(1))// 松開按鍵退出瞄準
{
m_isAiming = false;
Aim();
}
if(!(Time.time - m_startAimInTime < 0.3f)) //是否正在舉槍 舉槍時無法開槍
{
m_isAimingIn = false;
}
值得注意的:
關于Mathf.SmoothDamp,這個方法的smoothTime也就是緩沖時間的值越大,current到target的數值的變化速度就越慢。
不同倍率瞄具的資料儲存可以通過ScriptableObject來實作。