Quantum 104 - プレイヤーのスポーニング
概要
プレイヤーキャラクターのエンティティを作成した後は、ゲームに参加するプレイヤーごとにプレイヤーキャラクターを生成し、プレイヤーの入力をエンティティにリンクさせるという手順が必要です。
プレイヤーキャラクターのプレファブ
現在、キャラクターはシーンオブジェクトです。Quantumは、1人用のUnityゲームでプレハブを実行時に生成できるのと同様に、エンティティを実行時に生成することができます。シーンから PlayerCharacter GameObject を Resources/DB フォルダにドラッグして PlayerCharacter プレファブを作成します。その後、PlayerCharacter をシーンから削除してください。
プレハブの下に EntityPrototype と EntityView ファイルが作成されていることに注目してください。これらは Quantum がエンティティを生成し、Unity のビューにリンクさせるために使用されます。
重要: Quantum のすべてのプレハブは Resources/DB フォルダかそのサブフォルダ内にある必要があります。外部にあるプレハブには、EntityPrototypeファイルは作成されません。
プレイヤーリンクコンポーネント
Quantumはプレイヤーという概念を持っています。各クライアントは、1つまたは複数のプレーヤーを持つことができます。しかし、Quantumには、プレイヤーオブジェクト/アバターという概念は組み込まれていません。ゲームに接続された各プレイヤーには、一意のIDが与えられます。このIDは PlayerRef と呼ばれます。エンティティを特定のプレイヤーにリンクさせるには、オーナーの PlayerRef を含む PlayerLink コンポーネントを作成します。
quantum-code プロジェクトの Platformer フォルダに PlayerLink.qtn ファイルを作成し、次のコードを追加します。
C#
component PlayerLink
{
player_ref Player;
}
プレイヤーデータ
キャラクターを動的に生成するためには、ゲームプレイコードにどのようなエンティティを生成するかを知らせる必要があります。Quantumにはプレイヤーデータという概念があります。プレイヤーデータにより、各プレイヤーは接続時にシミュレーションに情報を渡すことができます。これは、プレイヤーがどのキャラクターを演じているか、どのスキンを使っているかなど、あらゆる情報を伝えることができます。
プレイヤーデータ は RuntimePlayer.User ファイルにあります。quantum_code プロジェクトの RuntimePlayer.User ファイルを開き、その内容を以下のように置き換えます。
C#
using Photon.Deterministic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Quantum
{
partial class RuntimePlayer
{
public AssetRefEntityPrototype CharacterPrototype;
partial void SerializeUserData(BitStream stream)
{
stream.Serialize(ref CharacterPrototype);
}
}
}
ビルド(ctrl + shift + b)を押してください。
このコードでは、プレハブに相当する AssetRefEntityPrototype をプレイヤーデータに追加しています。これはプレハブに相当するもので、後でプレイヤーキャラクターの実体を生成するために使用されます。
IMPORTANT: RuntimePlayer クラスに追加されるすべてのデータは SerializeUserData 関数でシリアライズする必要があります。BitStream はすべての基本的な型のシリアライズを提供します。
プレイモードに入ると、Quantum シミュレーションが自動的に実行されます。これは Unity の Game シーンの QuantumRunnerDebug GameObject にある QuantumLocalRunnerDebug コンポーネントによって駆動されます。このコンポーネントは、開発用にローカルで Game のシングルプレイヤー版をデバッグするために使用されます。
QuantumLocalRunnerDebug では、任意の人数のローカルプレイヤーをシミュレートすることができます。 QuantumLocalRunnerDebug の Players の下に新しいエントリーを追加してください。このエントリには CharacterPrototype フィールドが含まれていますが、これは以前にプレイヤーデータに追加されたフィールドです。このフィールドに、プレハブ PlayerCharacter の下にある PlayerCharacterEntityPrototype ファイルをドラッグ&ドロップしてください。
プレハブとプレイヤーデータの連携が完了したので、あとはプレイヤーが参加したときにエンティティをスポーンするコードを書くだけです。
プレイヤーオブジェクトを生成する
Create a new PlayerSpawnsystem.cs class. Add the following code:
C#
namespace Quantum.Platformer
{
unsafe class PlayerSpawnSystem : SystemSignalsOnly, ISignalOnPlayerDataSet
{
public void OnPlayerDataSet(Frame frame, PlayerRef player)
{
var data = frame.GetPlayerData(player);
// resolve the reference to the prototype.
var prototype = frame.FindAsset<EntityPrototype>(data.CharacterPrototype.Id);
// Create a new entity for the player based on the prototype.
var entity = frame.Create(prototype);
// Create a PlayerLink component. Initialize it with the player. Add the component to the player entity.
var playerLink = new PlayerLink()
{
Player = player,
};
frame.Add(entity, playerLink);
// Offset the instantiated object in the world, based in its ID.
if (frame.Unsafe.TryGetPointer<Transform3D>(entity, out var transform))
{
transform->Position.X = 0 + player;
}
}
}
}
このコードでは、プレイヤーが参加したときにキャラクターの実体を作り、それにPlayerLinkコンポーネントを追加することでプレイヤーにリンクさせます。
シグナルは、C#のイベントに似ています。Quantumのシステムが互いに通信するために使用されます。例えば、ISignalOnPlayerDataSetはプレイヤーがセッションに参加し、プレイヤーデータを共有した後に呼び出されるシグナルです。
SystemSignalsOnlyは、それ自身では何もしない特別なタイプのシステムです。シグナルを聞くだけのシステムを実装することができます。
PlayerSpawnSystem を SystemSetup.cs の MovementSystem の後のシステムのリストに追加してください。
MovementSystemのアップデート
今までMovementSystemは常に0プレイヤーからの入力を使って次のようなコードで移動していました。
C#
var input = *f.GetPlayerInput(0);
これを次のように置き換えると、リンク先のプレイヤーから入力されるようになります。
C#
Input input = default;
if(f.Unsafe.TryGetPointer(filter.Entity, out PlayerLink* playerLink))
{
input = *f.GetPlayerInput(playerLink->Player);
}
フィルターは調整されていないため、システムは引き続き CharacterController を持つが PlayerLink コンポーネントを持たないエンティティをフィルター処理することに注意してください。この場合、入力には default 値が使用されます。重力以外の動きはありません。
QuantumのTryGetを使ったコンポーネントの取得は、QuantumがスパースセットECSを使っているため、O(n)と非常に高速になります。
ビルド(ctrl + shift + b)を押してUnityに切り替えてプレイモードにします。すでにシーンにいるキャラクターに加えて、プレイヤーキャラクターが生成され、キーボード入力に反応するようになります。