Karts
概要
Fusion Kartサンプルは、サーバー権限とクライアント予測モデルを使用してレースゲームを作成する方法を示しており、プレイヤーは名前をルーム識別子として使用してルームを作成し参加することができます。
始める前に
サンプルを実行するには、まずPhotonEngine DashboardでFusion AppIdを作成し、それをFusionメニューからアクセスできるリアルタイム設定の「App Id Fusion」フィールドに貼り付けます。Photonアプリの設定アセットは、FusionメニューのFusion > Realtime Settingsから選択できます。
ダウンロード
| Version | Release Date | Download |
|---|---|---|
| 2.0.5 | 3月 04, 2025 | Fusion Karts 2.0.5 |
特徴
このプロジェクトは完全なゲームループを備えており、最大8人のユーザーが互いに参加し、誰が勝つかを競い合ったり、タイマーなしで無限ラップのトラックで一緒に練習したりすることができます。主な特徴は以下の通りです:
- 2つの異なるモード(レースとプラクティス)
- 2つのレーストラック
- 異なるステータスを持つカート
- ブースト/バナナ障害物、コインなどの共有アイテム
- 拡張可能なスクリプタブルオブジェクトベースのアイテムシステム
- クライアントが参加するためのコードを使用してホストとしてルームを設定でき、"ルームが見つかりません"、"ルームが満員です"、"ルームは現在セッション中です" などのエッジケースを処理します。
フォルダ構造
主なScriptsフォルダ/Scriptsには、ネットワーキング特有のコンポーネントに関連するNetworkingやFusion Helpersなどのサブフォルダが含まれており、その他のサブフォルダにはゲームプレイを管理するためのさまざまなインターフェースやマネージャーコンポーネントなどが含まれています。
ゲームランチャー
GameLauncher.csクラスは、ユーザーがPlaymodeメニューから選択したオプションに応じて、ユーザーをHostまたはClientとして設定する役割を担います。UIへの参照を保持し、プレイヤーの生成、デスポーン、およびシャットダウンなどの処理を担当します。
初回起動
サンプルを初めて起動する際、ユーザーはニックネームを入力するよう求められ(希望する場合)、リージョンを選択する必要があります。この画面には、どのタイミングでもオプションメニューからアクセスできます。提供されたニックネームは次の3つの場所で使用されます:
- ユーザーがルームを作成または参加する際、提供されたニックネームを持つUIアイテムが生成されます。
- レース中、各カートの上にニックネームがワールドスペースキャンバスに表示されます。
- レースの終了時に表示される結果画面では、ニックネームが1位、2位、3位などを示すために使用されます。
ルーム
Fusion Kartsサンプルは、Photon Cloudセッションの上にある抽象化であるルームを使用しています。このサンプルでは、最大8人のユーザーが同時にルームに接続できます。この上限は、1から8の間でオプションとして設定することも可能です。
ルームの作成
CreateGameUIスクリプトは、キャンバスの階層にあるCreate Room ScreenのさまざまなUI要素への参照を保持しています。Room Codeの入力フィールドでは、このルームのIDが設定されます。ユーザーがロビーに参加しようとすると、同様の入力フィールドが表示され、認識されたコードを提示する必要があります。プレイヤー数のスライダーは、ホストがCreateGameUIスクリプトにおいてServerInfo.MaxUsersを設定することで、ルーム内のユーザー数を制限できるようにします。サンプルには2つの異なるゲームモードと2つの異なるトラックが含まれており、ルーム作成時に次のメソッドを通じて適切な整数値がServerInfo.csに設定されます。
C#
public void SetGameType(int gameType)
{
ServerInfo.GameMode = gameType;
}
public void SetTrack(int trackId)
{
ServerInfo.TrackId = trackId;
trackImage.sprite = ResourceManager.Instance.tracks[trackId].trackIcon;
}
ルームへの参加
ルームに参加するためには、ユーザーがルームコードを提供する必要があります。存在しないルームに参加しようとした場合、ユーザーにはその旨を示すUIメッセージが表示されます。ユーザーは現在セッション中のルームに参加することはできず、また接続しようとしているルームと同じリージョンにいることを確認する必要があります。JoinGameUIスクリプトは、必要なコードを提供するための入力フィールドへの参照を保持しています。入力フィールドにテキストが提供されていない場合、確認ボタンは操作不可に設定されます。これは、コードなしでルームを作成することが不可能であるためです。
C#
private void SetLobbyName(string lobby)
{
ClientInfo.LobbyName = lobby;
confirmButton.interactable = !string.IsNullOrEmpty(lobby);
}
準備
各ユーザーの準備状態はプレイヤーリストのニックネームの横に表示され、準備ができているユーザーは緑のチェックマークで示されます。全プレイヤーはレースが開始される前に準備を整える必要があります。LobbyUI.cs内のEnsureAllPlayersReady関数は、各RoomPlayerのNetworkBehaviourのPlayerChangedイベントにサブスクライブされています。このRoomPlayerのIsReadyネットワークプロパティは、FusionのNetworked属性を通じて提供されるOnChangedコールバックによって呼び出されます。関数が呼ばれると、各RoomPlayerのIsReadyブールがtrueに設定されているかを確認し、対応するインデックスを持つ選択されたトラックのためにsceneIndexパラメータを設定してLevelManager.LoadTrackを呼び出します。このメソッドはFusionのアクティブシーンを設定し、それによって登録済みのシーンオブジェクトプロバイダーを呼び出します。
入力の処理
このサンプルは新しいInput Systemを使用しており、InputActionクラスを利用してキーボードおよびゲームパッドコントロールのサポートを処理しています。新しいInput Systemは、さまざまなコントローラをサポートするのを容易にします。キーボードとジョイスティックのサポートがデフォルトで含まれており、ハプティックフィードバックも利用可能です。
キーボード
- AおよびDまたは左矢印キーと右矢印キーでステアリング
- Wまたは上矢印キーで加速
- Sまたは下矢印キーでリバース
- Altで後ろを見る
- Spaceでホップ/ドリフト
- Shiftでホーン/アイテムを使用
ゲームパッド
- 左アナログスティックでステアリング
- 南ボタンで加速
- 東ボタンでリバース
- D-Padの下で後ろを見る
- 右バンパーでホップ/ドリフト
- 左バンパーでホーン/アイテムを使用
(コントローラーの振動をサポート)
カート
カートは多くの個別の振る舞いで構成されており、すべてKartComponentから派生しています。KartEntityはそれらのハブとして機能し、周辺機器を提供します。コンポーネントは以下の通りです:
KartAnimator-Animatorコンポーネント、パーティクルシステムやトレイルなどの視覚要素への参照、およびアニメーションやエフェクトを再生するためのメソッドを持ちます。KartAudio- カートにある各永続的なオーディオソースへの参照を持ち、エンジンのピッチや音量、ドリフト音の再生を担当します。KartCamera- カメラの視点、視野、スピードラインのパーティクルシステムを制御します。KartController- 大部分のロジックとネットワーク処理がここで行われます。加速、ステアリング、ドリフト、ブースト、ホイールの回転、道路への向き合わせなどが含まれます。KartInput- ローカルで入力をポーリングし、InputActionの有効/無効化やコールバックを処理します。KartLapController- カートの現在のラップとチェックポイントを管理します。KartItemController- アイテム使用ボタンが押された際の動作を管理します。
さらに、KartEntityはGameUI HUDインターフェースへの参照を保持しており、これはコンポーネント構造の一部ではありませんが、カートの状態をプレイヤーに外部的に反映する方法を提供します。
ピックアップ
ピックアップは、このサンプルでカートが相互作用できるゆるやかに定義されたエンティティの集合を指す用語です。すべてのピックアップはICollidableインターフェースを実装しており、特定の動作はICollidable.Collideの実装によって決まります。KartEntityは相互作用を開始する役割を担い、OnTriggerStayメソッドで実行され、そこにはKartEntityインスタンスへの参照が渡されます。OnTriggerStayが使用されるのは、ネットワークコンテキストにおけるOnTriggerEnter関数の信頼性の低さによるものです。
- コイン: コインはゲームプレイの観点では機能的な目的はありませんが、1人のプレイヤーによって収集される基本的なエンティティを示す機能があります。コインはデスポーンされ、UIに表示されるカウンターに加算されます。
- アイテムボックス: ピックアップ自体ではありませんが、アイテムボックスもその動作を促進するために
ICollidableを実装しています。アイテムボックスは、ヒットした際にKartEntity.SetHeldItemメソッドを通じてカートにPowerupを割り当てる役割を持っています。
パワーアップ
パワーアップは、アイテムボックスから取得され、プレイヤーの裁量で収集後に任意のタイミングで使用できる特別な種類のピックアップです。パワーアップを構成する2つのコンポーネントがあります。それは、Powerup ScriptableObjectと、抽象クラスSpawnedPowerupです。
SpawnedPowerupはICollidableから継承され、ICollidable.Collideを仮想的に実装することで、派生クラスにとってオプションの実装となります。また、オプションの初期化のために仮想メソッドInitも提供されており、これはPowerup.Useメソッドによって生成された直後に呼び出されます。
- バナナ: 使用すると、バナナはカートの後ろに物理的なエンティティとして落とされ、プレイヤーにとっての危険要素として機能します。
BananaPowerupはSpawnedPowerup.Collideをオーバーライドし、通過したカートをスピンアウトさせる機能を持っています。 - ブースト: 即座にレベル2のブーストを提供します。ブーストパワーアップにはバナナのような物理的な表現がなく、ブーストが与えられた後にすぐにデスポーンします。