Karts
概要
Fusion Kart サンプルはServer Authoritative, Client Predicted モデルを使用したレースゲームの作成方法を示しており、プレイヤーは名前をルームの識別子としてルームを作成し参加することができます。
開始する前に
サンプルを実行するには、まず、PhotonEngine Dashboard で Fusion AppId を作成し、Real Time Settingsの App Id Fusion
欄(Fusion メニューからアクセスできます)に貼り付けます。Fusionメニューの Fusion
> Realtime Settings
から、Photonアプリ設定アセットを選択することができます。
ダウンロード
バージョン | リリース日 | ダウンロード | ||
---|---|---|---|---|
1.1.7 | Jun 21, 2023 | Fusion Karts 1.1.7 Build 198 |
特徴
このプロジェクトは完全なゲームループを持ち、最大8人のユーザーが参加し、勝利を競うレースや、無限にループするコースでタイマーなしで一緒に練習することができます。主な機能は以下の通りです:
- 2種類のモード(レースと練習)
- 2つのレーストラック
- 様々な特性を持つレースカート
- ブースト/バナナ障害物、コインなどの共有アイテム
- スクリプト可能なオブジェクトベースのアイテムシステム(拡張可能)
- クライアントが参加するためのコードを使用してホストとしてルームを設定し、「ルームが見つかりません」、「ルームがいっぱいです」、「ルームは現在セッション中です」などのエッジケースを処理することができます。
フォルダの構成
メインのScriptsフォルダ /Scripts
には、ネットワークに特化したコンポーネントである Networking
と Fusion Helpers
が、その他のサブフォルダにはゲームプレイを司る様々なインターフェースとマネージャコンポーネントなどが格納されています。
ゲームランチャー
GameLauncher.cs
クラスは、ユーザーを Host
または Client
として設定する役割を果たします。UIへの参照を持ち、プレイヤーの生成、デスポーン、シャットダウンなどの制御を行います。
初回起動時
初回起動時には、ニックネームとリージョンを選択する画面が表示されます。この画面は、オプションメニューからいつでも呼び出すことができます。入力されたニックネームは、次の3つの場面で使用されます。
- ユーザーがルームを作成したり参加したりするとき、UI アイテムは提供されたニックネームでインスタンス化されます。
- レース中、ワールドスペースキャンバスの各カートの上のニックネームがインスタンス化されます。
- レース終了時の結果画面では、1位、2位、3位などを表示するためにニックネームが使われます。
ルーム
Fusion Kartsのサンプルでは、Photon Cloud Sessionsの抽象化として、ルームを使用しています。1つのルームに同時に接続できるユーザは最大8人です。この上限は、任意で1〜8まで設定することができます。
ルームの作成
CreateGameUI
スクリプトは、Canvas 階層にある 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
イベントを受信し、その IsReady
ネットワーク属性が、Fusion の Networked
属性の OnChanged
コールバックを通じて呼び出されるように設定されています。この関数が呼ばれると、それぞれの RoomPlayer
が IsReady
ブール値を true に設定しているかどうかをチェックし、sceneIndex
パラメータに選択中のトラックに対応するインデックスを指定して LevelManager.LoadTrack
を呼び出します。このメソッドはFusionのアクティブなシーンを設定し、登録されたシーンオブジェクトプロバイダを呼び出します。
入力の処理
このサンプルでは、新しい入力システムを使用し、InputAction
クラスを利用して、キーボードとゲームパッドの両方のコントロールをサポートを処理します。新しいInput Systemにより、様々なコントローラのサポートが容易になりました。キーボードとジョイスティックをサポートしており、ハプティックフィードバックもあります。
キーボード
- A、Dまたは左右の矢印キーでステアリング操作
- Wまたは上矢印キーで加速
- Sまたは下矢印キーで後退
- Altキーで後方確認
- スペースでホップ/ドリフト
- Shiftキーでホーン/アイテム使用
ゲームパッド
- 左アナログスティック:ステアリング
- 南ボタンで加速
- 東ボタンで後退
- Dパッドボタン押下で後方確認
- 右バンパーでホップ/ドリフト
- 左バンパーでホーン/アイテム使用
(コントローラランブルに対応)
Kart
カートは多くの個別の動作から構成され、すべて KartComponent
から派生します。KartEntity
がそれらの間のハブとなり、周辺を提供します。コンポーネントは以下の通りです。
KartAnimator
-Animator
コンポーネントへの参照、パーティクルシステムやトレイルなどのビジュアル要素、アニメーションやエフェクトを再生するためのメソッドです。KartAudio
- カートの各永続的なオーディオソースを参照し、エンジンのピッチやボリューム、ドリフトのオーディオを再生する役割を担ります。KartCamera
- カメラの視点、視野、スピードラインパーティクルシステムをコントロールします。KartController
- 加速、ステアリング、ドリフト、ブースト、ホイール回転、路面への追従など、ロジックとネットワークのほとんどがここで行われます。KartInput
- ローカルで入力をポーリングし、InputAction
の有効化/無効化とコールバックを処理します。KartLapController
- カートの現在のラップとチェックポイントを処理します。KartItemController
- アイテムの使用ボタンを押したときの振る舞いを処理します。
さらに、KartEntity
は GameUI
HUD インターフェースへの参照を保持しています。それ自体はコンポーネント構造の一部ではありませんが、カートの状態をプレイヤーに外部に反映させる方法を提供します。
Pickup
Pickupはこのサンプルで使用される用語です。カートがインタラクトするエンティティを示します。すべてのPickupは ICollidable
インターフェースを実装しており、特定の動作は ICollidable.Collide
の実装によって決定されます。 KartEntity
はインタラクションを開始する役割を担っており、 OnTriggerStay
メソッドで実行され、 KartEntity
インスタンスへの参照が渡されます。 OnTriggerStay
を使用するのは、ネットワークコンテキストでの OnTriggerEnter
関数の信頼性が低いためです。
- コイン: ゲームプレイの観点からはコインに機能的な目的がありません。一人のプレイヤーが集めることができる基本的なエンティティを示します。デスポーンされ、その後UIに表示されるカウンターに追加されます。
- アイテムボックス:アイテムボックスはピックアップではありませんが、その振る舞いを容易にするために
ICollidable
を実装しています。アイテムボックスはKartEntity.SetHeldItem
メソッドによって、ヒットしたときにPowerup
をカートに割り当てる役割を担っています。
PPowerup
Powerupはアイテムボックスから得られる特殊なピックアップです。回収後、プレイヤーの判断で任意のタイミングで使用することができます。
パワーアップを構成するコンポーネントには、Powerup
ScriptableObject と SpawnnedPowerup
クラスの2つがあります。
SpawnedPowerup
は ICollidable
を継承し、ICollidable.Collide
を仮想的に実装したもので、派生クラスではオプションとして実装することができます。また、任意で初期化用の仮想的な Init
メソッドも用意されています。このメソッドは Powerup.Use
メソッドによって生成された直後に呼び出されます。
- バナナ: 使用すると、バナナは物理的な実体としてカートの後ろに落とされ、プレイヤーにとって障害物として機能します。
BananaPowerup
はSpawnedPowerup.Collide
をオーバーライドし、バナナをひいたカートをスピンさせやすくします。 - ブースト:レベル2のブーストを瞬時に行う。ブーストパワーアップはバナナのような物理的な表現を持たないので、ブーストがかかるとすぐにデスポーンします。