This document is about: FUSION 1
SWITCH TO

プレイヤー

Level 4

概要

Player (Player スクリプト、Player プレハブ) はゲーム内で接続された仲間を表し、ビジュアルはありません。プレイヤーは共通のメタデータ - ユーザーID、ニックネーム、選択したキャラクター、その他 Agent (ゲーム世界で生成されるビジュアル表現) がリスポーンしても生き残るべきデータにアクセスすることができます。

**Agent** (Agentスクリプト、AgentBase プレハブ、およびその亜種) は、プレイヤーが操作するゲーム内のキャラクターを表します。GameplayMode によって生成され、HealthWeapons` などのコンポーネントを持っています。このキャラクターは必要に応じてスポーン、デスポーンされます。

次の図は、コンポーネント階層を実行のウォーターフォールとして示しています。

agent components

入力処理

次の図は、入力の処理とアクションの実行を表しています。

input processing

Notes:

  1. Frame: Unity のレンダリングフレーム番号、Tick: Fusion の固定更新ティック数
  2. 各フレームの開始時に、デバイスからの入力を BeforeUpdate() で収集し、 Render Input データ構造に書き込みます(入力権限のみ実行)。
  3. 同じ入力は Cached Input にも蓄積されます (たとえば、ルックローテーションデルタ)
  4. 累積された差分時間が次の固定ティックをシミュレートするのに十分な大きさである場合 (フレーム 103)
    • NetworkEvents.OnInput()コールバックを通じて Cached Input がポーリングされ、消費されます。
    • 最新の Render Input は既に蓄積されており、次の FixedUpdateNetwork() で処理されるため、クリアする必要があり、二度適用されません (FixedUpdateNetwork()Render() から)
    • プレイヤーの入力は BeforeTick() で Fusion から読み込まれ、Fixed Input に格納されます (入力と状態の権限で実行されます)
    • 他のスクリプトで呼ばれる FixedUpdateNetwork()Fixed Input を使ってゲームプレイのアクションを生成します。
  • 他のスクリプトで呼ばれる Render()Render Input を使用してゲームプレイアクションを生成します。(動きを予測したレンダリング、射撃は FUN からのみ行われます。)
  1. 累積された差分時間が次の固定ティックをシミュレートするのに十分でない場合 (フレーム 101, 102)
    • 他のスクリプトで呼ばれた Render()Render InputCached Input を使ってゲームプレイアクションを生成します (予測された動きをレンダリング、回転を見る)。

この図は簡易版であり、すべてのエッジケースをカバーしているわけではありません。詳細については、ドキュメントを参照してください。

ルックローテーションスムージング

Fusion BRには、どのような条件下でもスムーズなルックローテーションを実現するためのカスタムソリューションが用意されています。

以下のログは、一般的なハードウェア(125Hzのマウスポーリング)と高いレンダリング/出力リフレッシュレート(200FPS以上)を使用した場合のRaw入力でのエイリアシングの問題を示しています。レンダリング出力は、CPU/GPUがどれほど優れていても、常にジッターを感じることになります。

look rotation smoothing

この問題を解決するために、入力値をタイムスタンプで記録し、現在のフレームの値を定義された時間スパンの平均値として計算します(Fusion BRはデフォルトで25msのウィンドウを使用します)。この結果、滑らかな知覚が得られますが(特に高リフレッシュレートのモニターで顕著)、ごくわずかな入力遅延が発生します。より高いサンプリングレートのハードウェアを使用することで、スムージングウィンドウを最小にすることができます。

次のグラフは、生の マウスデルタ(下線)とキャラクターのルックローテーション(上線)を時間軸で示したものです。

look rotation smoothing

次のグラフは、マウスのデルタ(下線)とキャラクターの視線回転(上線)を時間軸で平滑化したものです。

look rotation smoothing

また、サンプリングエラー(机上面)や手やマウスの動きの不均一性(机上摩擦、筋肉)による微小ジッターを低減することができます。

キャラクターアニメーション

このプロジェクトでは、Playables APIをベースにしたカスタムアニメーションコントローラーの実装があります。これは、ティックアキュレートなアニメーション評価と動的なパフォーマンスのスケーリングに対応しています。

以下の図は、Mecanimに類似したアーキテクチャを表しています。

animation controller

エージェントのオブジェクト階層におけるアニメーションのレイヤーとステートの設定。

animation layers

アニメーションのレイヤー:

  • Locomotion:移動のためのベースフルボディレイヤー
  • FullBody: Locomotion とブレンドされたフルボディのオーバーライドレイヤー
  • LowerBody: 下半身のキャラクター回転用のオーバーライドレイヤー -UpperBody: 上半身のアクションのオーバーライドレイヤーです。
  • Shoot: 手の動作(射撃)のレイヤーをオーバーライドします。
  • Look: 上半身のレイヤーを追加して、上や下を向くようにします。

アニメーションコントローラの複雑さにもよりますが、200人のプレイヤーを評価することは、サーバーのボトルネックになりがちです。パフォーマンスを向上させるために、サーバーは接続されたプレーヤーの数に基づいて n 番目のフレームごとにインターレースされた PlayableGraph を評価できるようにしています。レイヤーやステートの重みのような重要なプロパティは、依然として毎フレーム計算されます。次の表は、インターレース評価に関するルールを示しています。

接続されたプレイヤー プレイアブルグラフの評価
> 150 4フレーム毎
> 100 3フレーム毎
> 50 2フレーム毎
その他 毎フレーム
このプロジェクトでは、一般的なリグでベイクしたアニメーションを使用しています。ヒューマノイドリグを使用すると、リターゲットによるパフォーマンスのオーバーヘッドが追加されます。

キャラクターコントローラー

このサンプルでは、移動に Fusion KCC (高度なキネマティックキャラクターコントローラーアドオン) を使用しています。これは、パフォーマンス、ゲームプレイのインタラクション、カスタマイズに重点を置いた、一般的な低レベルキャラクターコントローラーです。

Fusion KCC の特徴:

  • 位置と視線方向の回転(ピッチ+ヨー)の制御
  • カプセルコライダーで定義された形状
  • ローカルプレイヤーのレンダリング動作の予測
  • ダイナミック(物理的)およびキネマティック(非現実的)な速度ベースの動きの組み合わせ
  • 外力 - 爆発、移動するプラットフォームなどによるもの
  • 加速度や摩擦の移動
  • カスタマイズのための高度なKCCプロセッサーのパイプライン(速度と方向のオーバーライド、ブロッキング)
  • デフォルトプロパティ(半径、高さ、質量など)のネットワーク同期、その他のプロパティの同期もオプションで可能
  • カスタムコライダーフィルタリングと無視リスト
  • CCD (連続衝突検出)
  • コリジョンコールバック
  • グランドスナップとステップ高さのサポート
  • ローカルモード(ネットワークトラフィックなし)のサポート
  • ネットワークとパフォーマンスの最適化
  • プラットフォーム非依存、モバイルフレンドリー
  • フレーム毎のデバッグの基本サポート - エディタ描画とロギング

プレイヤーの体力が一定以下になり、現在戦闘中でない場合、自動回復が作動し、プレイヤーの体力を補充し始めます。

ジェットパック

ジェットパックは、燃料を消耗しながら飛行し、レベル内を素早く移動する能力を提供します。燃料はアイテムボックスの中にある燃料缶を拾うことで補充することができます。

ジェットパックの状態は、燃料消費、プロペラ、サウンド、オン/オフの状態を処理する Jetpack スクリプトによって処理されます。実際の空中の動きはJetpackKCCProcessorによって処理さ れます。このスクリプトはKCC速度をオーバーライドし、デフォルトの挙動を抑制します。

jetpack

観戦者モード

プレイヤーが脱落したり、ゲームに参加するのが遅れたりすると、観戦モードになります。観戦モードでは、プレイヤーは他のプレイヤーの視点からゲームを観察することができます。コード上では、これは実際には非常に単純に処理されます。カメラと UI は SceneContext に割り当てられた ObservedAgent に基づいて動作します。ObservedAgent には、ローカルプレイヤーエージェントと観戦プレイヤーエージェントのどちらかを指定します。

Back to top