5 - プレイヤーのスポーン
概要
プレイヤーキャラクターのエンティティを作成した後は、ゲームに参加したプレイヤー毎にプレイヤーキャラクターをスポーンして、プレイヤーの入力とエンティティを連携します。
プレイヤーのプレハブ
現在、船はシーン上のオブジェクトです。Unityのシングルプレイヤーゲームでプレハブを実行時に生成するのと同じように、Quantumもエンティティを実行時にスポーンできます。シーンのAsteroidsShipゲームオブジェクトをResourcesフォルダーにドラッグして、船をプレハブにしましょう。そしたら、シーンのAsteroidsShipは削除します。
EntityPrototypeと、プレハブ内にEntityViewファイルが作成されます。これらは、エンティティをスポーンしたり、そのエンティティをUnityのビューと連携したりするために使用されます。
PlayerLinkコンポーネント
Quantumには「プレイヤー」の概念があります。各クライアントは、1つまたは複数のプレイヤーを持ちます。ただし、Quantumに「プレイヤーオブジェクト/アバター」の概念はありません。ゲームに接続した各プレイヤーにはユニークなIDが与えられ、このIDはPlayerRefと呼ばれます。エンティティを特定のプレイヤーと紐づけるために、所有者のPlayerRefを持つPlayerLinkコンポーネントを作成します。
Assets/QuantumUser/SimulationフォルダーにPlayerLink.qtnファイルを作成し、以下のコードを追加してください。
C#
component PlayerLink
{
player_ref PlayerRef;
}
プレイヤーのデータ
動的にキャラクターをスポーンするには、どのエンティティを作成すべきなのかをゲームプレイコードに知らせる必要があります。Quantumには「プレイヤーデータ」の概念があり、各プレイヤー接続時に、シミュレーションに情報を渡すことができます。情報とは、プレイヤーが選択したキャラクターや使用中のスキンなどです。
プレイヤーデータはデフォルトでAvatarエンティティとPlayer Nicknameを含んでいますが、このデータはPhoton/QuantumUser/Simulation/RuntimePlayer.User.csファイルから拡張できます。
プレイヤーエンティティをスポーンするために、定義済みのavatarフィールドを使用します。QuantumではAssetRefEntityPrototypeがプレハブと同等のものになります。
ゲームを再生すると、Quantumのシミュレーションが自動的に実行されます。これは、UnityのQuantumGameScdne上のQuantumDebugRunnerゲームオブジェクトのQuantumRunnerLocalDebugコンポーネントによって動作しています。このコンポーネントは、開発中にGameをシングルプレイヤーバージョンでローカルに実行するために使用されます。
QuantumLocalRunnerDebugは、複数のローカルプレイヤーをシミュレートできます。AsteroidsShipプレハブにあるAsteroidsShipEntityPrototypeファイルを、QuantumLocalRunnerDebugのLocal PlayersのPlayer Avatarフィールドにドラッグ&ドロップしてください。
これでプレハブがプレイヤーデータに紐づいたので、後はプレイヤー参加時にエンティティをスポーンするコードを記述するだけです。
プレイヤーオブジェクトのスポーン
新しくShipSpawnSystem.csクラスを作成して、以下のコードを追加します。
C#
using UnityEngine.Scripting;
namespace Quantum.Asteroids
{
[Preserve]
public unsafe class ShipSpawnSystem : SystemSignalsOnly, ISignalOnPlayerAdded
{
public void OnPlayerAdded(Frame frame, PlayerRef player, bool firstTime)
{
{
RuntimePlayer data = frame.GetPlayerData(player);
// resolve the reference to the avatar prototype.
var entityPrototypAsset = frame.FindAsset<EntityPrototype>(data.PlayerAvatar);
// Create a new entity for the player based on the prototype.
var shipEntity = frame.Create(entityPrototypAsset);
// Create a PlayerLink component. Initialize it with the player. Add the component to the player entity.
frame.Add(shipEntity, new PlayerLink { PlayerRef = player });
}
}
}
}
このコードでは、プレイヤー参加時に船のエンティティを作成して、そこにPlayerLinkコンポーネントを追加することでプレイヤーを連携させています。
「シグナル」はC#のイベントと似ていて、Quantumのシステム間のやり取りに使用されます。Quantumには様々な既存のシグナルが用意されていて、ISignalOnPlayerAddedはプレイヤーがセッションに参加してプレイヤーデータが共有された後に呼び出されます。
SystemSignalsOnlyは特別なシステムの型で、更新ルーチンを持たず、軽量にシグナルへ反応するためだけに使用されます。
AsteroidsShipConfigアセットのシステムリストで、AsteroidsShipSystemの後にShipSpawnSystemを追加してください。
移動の更新
今までは、AsteroidsShipSystemの船の移動には、常にプレイヤー0の入力を使用していました。
C#
var input = frame.GetPlayerInput(0);
コードを以下に置き換えて、連携したプレイヤーの入力を取得しましょう。
C#
Input* input = default;
if(frame.Unsafe.TryGetPointer(filter.Entity, out PlayerLink* playerLink))
{
input = frame.GetPlayerInput(playerLink->PlayerRef);
}
フィルターは調整していないので、PhysicsBody2Dを持ちPlayerLinkを持たないエンティティもフィルタリングされていることに注意してください。このケースでは入力のdefault値が使用され、移動せずに重力が適用されます。このパターンによって、異なるソースからの入力を渡すAI操作の船の追加が簡単になります。
Quantumはsparse set ECSを使用しているため、TryGetを使用したコンポーネントの取得はO(1)で非常に高速です。
frame.UnsafeはQuantumのunsafeなAPIへのアクセスを提供していて、一般的に高速で、ポインターを使わない方より使いやすいです。ポインタの使用を避けたい場合は、frame.Getのような安全なAPIも使用できます。
Unityに戻り、ゲームを再生しましょう。船がスポーンして、キーボード入力に反応します。
Back to top