Weapons & Shooting
概述
Weapons
部分負責處理玩家武器。它維護當前武器的清單並處理武器切換。此外,它也為常見的武器操作提供了一個介面,如Fire
和Reload
。武器物件可以被撿起或扔到地上,詳見武器掉落部分。
武器有兩個基本類別:Weapon
和WeaponFirearm
。Weapon
持有了最低限度的手持武器,WeaponFirearm
包含了基本的槍支功能,如射擊邏輯、彈匣操作、分散和後座力。
BR200中的武器和拋射物主要基於命中掃描功能,因為這對這個專案來說很方便。有關武器和拋射物的更詳細方法以及關於不同拋射物方法的更詳細檔案,請查看拋射物基礎與拋射物進階範例。
命中掃描武器
命中掃描武器是遊戲中的主要武器。命中掃描武器在發射時會使用光線投射來評估命中情況。沒有為每個拋射物生成網路物件,而是在環形緩衝區中存儲一個小的ProjectileData
結構,以在同儕節點上計算視覺效果。命中掃描武器可以選擇建立一個飛向目標的虛擬視覺拋射物(檢查DummyProjectile
指令碼)。
C#
public struct ProjectileData : INetworkStruct
{
public Vector3 Destination;
public Vector3 ImpactNormal;
public int ImpactTagHash;
}
[Networked, Capacity(10)]
private NetworkArray<ProjectileData> _projectileData { get; }
拋射物武器
拋射物武器(ProjectileWeapon
、ThrowableWeapon
)會生成隨著時間推移而移動的獨立拋射物。拋射物在每次模擬刷新時都會在其先前位置和新位置之間執行短光線投射。在本專案中,拋射物武器僅用於手榴彈。如需了解更深入的執行方式,請查看拋射物基礎與拋射物進階範例。
後座力
武器後座力是一種基於真實武器的常見遊戲行為,在連續射擊過程中,武器往往會向上瞄準。通常在遊戲中,武器遵循固定或半隨機的路徑,玩家可以透過大量的遊戲來學習和肌肉記憶,這使得玩家能夠透過輸入來對抗後座力效應。
BR200配備了一個反後座力系統。每種武器都可以指定一種後座力模式(也稱為 發散模式)。後座力模式是一個可指令碼的物件,它定義了連續射擊過程中武器的路徑。反後座力直接影響玩家的查看旋轉,玩家可以對抗它。對抗過程稱為 減少後座力,您可以在Agent
指令碼中的SetLookRotation
方法中找到它。射擊停止後,查看旋轉會自動返回到初始值。

後座力模式定義了序列中每顆子彈的確切位置。初始後座力序列(後座力起始值)完成後,後座力遵循無休止迴圈(後座力無休止的值)。
請注意,武器分散是在後座力位置的上部應用的,因此根據分散值仍然存在一些射擊隨機性。
動態分散
每種槍支都有一個分散行為設定。

在連續射擊過程中,分散度會增加,在射擊停止後會自動減少到預設值。武器分散度進一步會乘以角色的狀態(奔跑、空中、瞄準)。

穿孔
拋射物穿孔(也稱為穿透)是射擊遊戲世界中某些物件的能力。這通常伴隨著傷害懲罰。
穿孔是在處理HitscanWeapon
中的命中時直接計算的。每枚拋射物都可以指定一個穿孔設定,為不同的材質指定一個傷害乘數。拋射物不會穿透傷害乘數為零的物件。根據分配給遊戲物件的Unity標籤來區分資料,並在運行階段基於標籤的雜湊進行檢查。

傷害下降
拋射物的傷害隨著距離開火的距離而下降。傷害下降由DummyProjectile
元件中定義的設定所控制。

第三人稱射擊
第三人稱射擊需要處理玩家透過相機看到的東西和玩家角色在遊戲世界中的實際位置所能擊中的東西之間的差異。
在計算命中率時,我們首先需要知道目標點。目標點指定玩家的瞄準位置,並透過每隔FixedUpdateNetwork()
就從武器指令碼中的相機直接發射光線投射來計算。當處理火力輸入時,武器將獲取目標點,並從角色的開火位置向目標點進行另一次光線投射,以獲得實際命中。

除了這些基本計算之外,還有一些額外的改進,以獲得更好的射擊體驗:
- 當玩家角色無法到達目標點時,會顯示紅十字以指示實際著陸點

- 從開火位置到目標點的光線投射忽略不靠近開火位置或目標點的環境命中,以緩解我們稱之為 角落問題 的問題行為。這大大改善了在角落、樹木和其他物件周圍的射擊行為。玩家實際上是向十字準線指向的地方射擊,但如果瞄準的是角落旁邊的玩家,則會引入一個小的邊緣量來射擊角落後面的玩家。這種忽略行為可以在所有拋射物計算所使用的
ProjectileUtility
中找到。

- 當目標點靠近玩家角色,並且到目標點的方向和角色向前之間的角度太大時,將計算目標點在向前方向上的某個距離。

拋射物
隨著時間的推移在遊戲世界中前進的拋射物在BR200中並沒有真正使用,除了手榴彈。查看拋射物基礎與拋射物進階範例,瞭解更詳細的拋射物示例。
手榴彈
手榴彈可以在物品箱中找到。當手榴彈被裝備起來時,一個小的倒數計時會減少手榴彈的引爆時間,直到達到一定的最小值(見ThrowableWeapon
)。手榴彈是由特殊武器處理的,就像是從隱形榴彈發射器中射出的一樣。
爆炸性手榴彈
產生爆炸物件的手榴彈。

閃光彈
手榴彈引爆時,如果玩家朝著手榴彈的方向看,就會使一定距離內的玩家失明。簡單的玩家失明效應是在AgentSenses
元件中計算的。

煙霧彈
產生煙霧效果的手榴彈。

健康與損傷系統
每個命中都在建立HitData
結構的HitUtility
中進行處理,並將損傷乘以可能的身體部位乘數。BodyPart
是預設延遲補償的Hitbox
的下層類別,新增了損傷乘數(例如,頭部的乘數高於1,而四肢的乘數低於1)。HitData
然後由目標的Health
元件進行處理。
健康元件建立一個BodyHitData
結構,該結構只包含將命中同步到所有客戶端所需的資訊。命中被存儲在一個BodyHitData
結構的小型連網環形緩衝區中。
C#
public struct BodyHitData : INetworkStruct
{
public EHitAction Action;
public float Damage;
public Vector3 RelativePosition;
public Vector3 Direction;
public PlayerRef Instigator;
}
[Networked, Capacity(4)]
private NetworkArray<BodyHitData> _hitData { get; }
相對位置
是如何存儲在身體命中資料
中而不是絕對位置的。由於代理的位置是在從伺服器接收到的最後兩個刷新之間插值的,因此相對位置更適合將命中效果(如血液飛濺)正確地放置在身體上。
根據命中緩衝區的變化,觸發適當的命中反應——UI中的命中方向,向損傷發起者顯示命中確認和數字,產生血液效果。