武器と射撃

概要

Weapons コンポーネントは、プレイヤーの武器の取り扱いを担当します。現在の武器のリストを保持し、武器の切り替えを処理する。さらに、FireReload のような一般的な武器のアクションのためのインターフェイスを提供します。武器のオブジェクトは拾ったり、地面に落としたりすることができます。詳しくは Weapon Drops セクションを参照してください。

武器には、WeaponWeaponFirearm という2つの基本クラスがあります。Weapon は最低限の武器を保持し、WeaponFirearm は発射ロジック、マガジンハンドリング、拡散、リコイルのような銃器の基本機能をカプセル化します。

Fusion BR の武器と弾丸は、このプロジェクトで便利だったため、ヒットスキャン機能を主に使用しています。より詳細な武器と弾のアプローチや、様々な弾のアプローチについてのドキュメントは、Fusion Projectiles サンプルを参照してください。

トップに戻る

ヒットスキャン武器

Hitscan武器は、このゲームにおける主要な武器です。発射されたとき、Hitscan武器はレイキャストを使用して命中判定を行います。すべての発射物に対してネットワークオブジェクトは生成されず、小さな ProjectileData 構造体がピアへの視覚効果を計算するために円形バッファに格納されます。ヒットスキャン武器にはダミーの視覚効果のみの投射物を作成し、ターゲットに飛ばすオプションがあります(DummyProjectileスクリプトを確認してください)。

public struct ProjectileData : INetworkStruct
{
    public Vector3 Destination;
    [Networked, Accuracy(0.01f)]
    public Vector3 ImpactNormal { get; set; }
    public int     ImpactTagHash;
}

[Networked, Capacity(25)]
private NetworkArray<ProjectileData> _projectileData { get; }

トップに戻る

弾丸兵器

投射型武器 (ProjectileWeapon, ThrowableWeapon) は時間経過とともに移動する独立した投射物オブジェクトを生成します。弾丸はシミュレーションティックごとに、前の位置と新しい位置の間で短いレイキャストを実行します。このプロジェクトでは、投射型武器は手榴弾にのみ使用されます。より詳細な実装は、Fusion Projectiles サンプルを参照してください。

トップに戻る

反動

武器の反動は、実際の武器に基づく一般的なゲームの動作で、連続射撃中に武器が上向きになる傾向があります。通常、ゲーム内の武器は固定または半不規則な軌道を描き、プレイヤーはプレイを重ねることで反動を学習し、筋肉に記憶させることができ、プレイヤーは入力によって反動効果に対抗することができます。

Fusion BRには、リコイルシステムが搭載されています。すべての武器にリコイルパターン(スプレーパターン とも呼ばれる)を割り当てることができます。リコイルパターンはスクリプト可能なオブジェクトで、連射中のウェポンの軌道を定義します。反動はプレイヤーの視線回転に直接影響を与え、プレイヤーはそれに対抗することができます。対抗する処理は Recoil Reduction と呼ばれ、Agent スクリプトの SetLookRotation メソッドで確認することができます。射撃が停止した後、ルックローテーションは自動的に初期値に戻ります。

Recoil pattern
分散させずに発射した場合のリコイルパターンと実弾の穴。

リコイルパターンは、シーケンス内のすべての弾丸の正確な位置を定義します。最初のリコイルシーケンス(リコイル開始値)が完了した後、リコイルは無限ループ(リコイルエンドレス値)に従います。

武器の分散はリコイル位置の上に適用されるため、分散値に基づいた射撃のランダム性が残っていることに注意してください。

トップに戻る

動的分散

すべての銃器には分散動作が設定されています。

Weapon Dispersion

連射中は分散が大きくなり、連射が止まると自動的に初期値に戻ります。武器の拡散は、キャラクターの状態(走行、空中、照準)によってさらに倍率が上がります。

Weapon Dispersion
分散とリコイルのセットアップ

トップに戻る

ピアッシング

射線貫通(貫通ともいう)とは、ゲーム世界の特定のオブジェクトを射抜く能力のことです。これは通常、ダメージペナルティが伴います。

貫通力は HitscanWeapon でヒット数を処理する際に直接計算されます。すべての弾丸は、異なる材料に対するダメージ倍率を指定するPiercingセットアップを割り当てることができます。投射物はダメージ倍率が0のオブジェクトは貫通しません。素材はゲームオブジェクトに割り当てられた Unity Tag に基づいて区別され、タグのハッシュに基づいてランタイムで確認されます。

Piercing Setup

トップに戻る

ダメージ低下

弾丸のダメージは、発射元からの距離によって低下します。ダメージの低下は DummyProjectile コンポーネントで定義された設定によって制御されます。

Dummy Projectile

トップに戻る

サードパーソンシューティング

サードパーソンシューティングでは、プレイヤーがカメラを通して見ているものと、プレイヤーキャラクターがゲームワールドの中で実際に打てるものとの差を処理する必要があります。

命中率を計算する場合、まずターゲットポイントを知る必要があります。ターゲットポイントはプレイヤーが狙う場所を指定し、武器のスクリプトである FixedUpdateNetwork 毎にカメラから直接レイキャストを発射することによって計算されます。射撃入力が処理されると、武器はターゲットポイントを取得し、実際のヒットを取得するためにキャラクターの射撃位置からターゲットポイントまで別のレイキャストを発射します。

Third Person Shooting
サードパーソンシューティングの図

Note: 発射位置は、銃身の先端ではありません。もともとは銃身の位置を使っていたのですが、武器の位置はアニメーションの影響を受けるため、斜行のような急激な動きでは発射感が安定しません。そこで、キャラクターの肩付近で固定する発射位置に変更しました。

これらの基本的な計算に加えて、より良い射撃のためにいくつかの改良が加えられています。

  • プレイヤーキャラクターから目標地点に到達できない場合、実際の着陸地点を示す赤い十字が表示さ れます

    Red Cross
    ターゲットポイントに到達できない場合は、赤い十字が表示されます。

  • 射撃位置からターゲットポイントまでのレイキャストは、射撃位置やターゲットポイントに近くない環境でのヒットを無視し、私たちがコーナー問題と呼ぶ問題行動を軽減します。これにより、コーナー、木、その他のオブジェクトの周りでの射撃動作が大幅に改善されました。プレイヤーは実際に十字線が指している場所を撃ちますが、コーナーのすぐ横を狙った場合、コーナーの後ろのプレイヤーを撃つわずかなマージンが導入されています。この無視動作は、すべての投射計算で使用される ProjectileUtility で見つけることができます。

    Corner Issue
    投射物は角を無視して目標地点に到達します。

  • ターゲットポイントがプレイヤーキャラクターに近い場合、ターゲットポイントへの方向とキャラクターの前方との角度が大きすぎる場合、代わりに前方方向にある程度離れたターゲットポイントが計算されます。

    Angle Ignore
    クロスヘアに対する角度が大きすぎる場合、武器は前方に発射されます。

トップに戻る

投射物

時間と共にゲーム世界を移動する弾丸は、Fusion BRでは手榴弾を除いてあまり使われません。 Fusion Projectiles で、より精巧な投射物の例を見ることができます。

手榴弾

手榴弾はアイテムボックスで手に入ります。手榴弾はアイテムボックスの中にあります。手榴弾が装填されると、小さなカウントダウンによって手榴弾の起爆時間がある最小値まで減少します (ThrowableWeapon を参照してください)。手榴弾の弾丸は特殊武器によって、見えない手榴弾発射装置から発射されたように扱われます。

Note: プレイヤーは英数字キー4で手榴弾を循環させることができます。

トップに戻る

爆発手榴弾

爆発オブジェクトを生成する手榴弾。

Explosive Grenade

トップに戻る

フラッシュ手榴弾

爆発時に手榴弾の方向を見ていると、一定距離内のプレイヤーの目が見えなくなる手榴弾。単純なプレイヤーの盲目効果は AgentSenses コンポーネントで計算さ れます。

Flash Grenade

トップに戻る

スモーク手榴弾

スモークを発生させる手榴弾。

Smoke Grenade

トップに戻る

ヘルス&ダメージシステム

すべてのヒットは HitUtility で処理され、 HitData 構造体が作成され、ダメージは可能なボディパーツの倍率で掛け合わされる。BodyPart はデフォルトのラグ補正された Hitbox の子クラスで、ダメージの倍率が追加されています(例えば、頭部は1より高い倍率、手足は1より低い倍率になります)。次に、HitDataはターゲットの Health コンポーネントによって処理されます。

ヘルスコンポーネントは、すべてのクライアントにヒットを同期させるために必要な情報のみを含む BodyHitData 構造体を作成します。ヒットデータは BodyHitData 構造体の小さなネットワーク上の円形バッファに格納されます。

public struct BodyHitData : INetworkStruct
{
    public EHitAction Action;
    public float      Damage;
    [Networked, Accuracy(0.01f)]
    public Vector3    RelativePosition { get; set; }
    [Networked, Accuracy(0.01f)]
    public Vector3    Direction { get; set; }
    public PlayerRef  Instigator;
}

[Networked, Capacity(8)]
private NetworkArray<BodyHitData> _hitData { get; }
Note: ヒットの RelativePosition が絶対位置ではなく BodyHitData に格納されていることに注意してください。 プロキシの位置は、サーバーから受信した最後の 2 つのティックの間で補間されるため、血しぶきなどのヒット エフェクトをボディに正しく配置するには、相対位置の方が適しています。

ヒット バッファーの変更に基づいて、適切なヒット リアクションがトリガーされます - UI のヒット方向、ヒット確認とダメージ インスティゲーターの数、血の効果のスポーンを表示します。

プレイヤーが別のプレイヤーを攻撃すると、弾丸の影響とヒット効果 (血) がすぐに表示されます。 ただし、新しいサーバー状態の一部としてヒットが受信された後、ヒット確認 (UI の赤い十字とヒット番号) がプレーヤーに表示されます (ヒットはサーバーによって「確認」されます)。 これにより (ネットワークの状態に基づいて) わずかな遅延が発生しますが、有効なヒットのみがプレイヤーに表示されるようになります。


ドキュメントのトップへ戻る