メインコンテンツまでスキップ

エンティティ・コンポーネント・システム

PlayCanvasのシーンにあるものは、すべてエンティティです。シーンを映すカメラも、照らすライトも、あらゆるモデル、サウンド、UIの部品、そしてゲームのオブジェクトもそうです。エンティティそのものは、位置、回転、スケールを持ち、ほかのエンティティとの階層の中に居場所を持つ、名前の付いた空間上の一点にすぎません。エンティティに能力を与えるのがコンポーネントです。cameraコンポーネントはエンティティをカメラにし、renderコンポーネントはその位置にメッシュを描画し、rigidbodyコンポーネントはエンティティを物理エンジンに委ね、scriptコンポーネントはその上で独自のコードを実行します。アプリケーションには、コンポーネントのタイプごとに1つのシステムがあり、そのタイプのすべてのコンポーネントを実行します。

app.rootの下にあるエンティティのツリー。camera、light、carと、carの下にbodyとwheelがあり、各エンティティの横にそのコンポーネントが並んでいます。各コンポーネントはapp.systems内の自分のシステムの列に置かれているため、renderの列にはcar、body、wheelのrenderコンポーネントが並びます

このパターンは、エンティティ・コンポーネント・システム(ECS)と呼ばれます。どの方法で開発しても、このパターンを使います。エディター、React、Web Componentsはいずれも、エンジンに対して書いたコードと同じエンティティとコンポーネントを作成します。このセクションの各ページでは、概念を一度説明してから、それぞれの環境での使い方を示します。

エンティティ​

エンティティは、Entityクラスのオブジェクトです。エンティティを見つけるのに使える名前とタグ、そしてその下にあるすべてのものと一緒にエンティティのオンとオフを切り替える有効状態を持ちます。位置、回転、スケールは親に対する相対値なので、エンティティを動かすと子も一緒に動きます。

シーンのエンティティは、app.rootをルートとするツリーを形作ります。エンティティは、このツリーに追加されたときにシーンに加わります。それまでは描画されず、スクリプトも実行されません。階層とトランスフォームを参照してください。

コンポーネント​

コンポーネントは、エンティティに能力を1つ追加し、その能力の設定をentity.light.colorやentity.camera.fovのようなプロパティとして保持します。1つのエンティティが持てるコンポーネントは、各タイプにつき1つまでです。1つのオブジェクトに2つのライトを持たせるには、それぞれにライトを持つ2つの子エンティティを与えます。

エンジンには、カメラ、ライト、レンダリング、サウンド、物理、アニメーション、パーティクル、ユーザーインターフェースを扱う、およそ20種類のコンポーネントがあります。独自の振る舞いのために、新しい種類のコンポーネントを書くことはありません。代わりにスクリプトを書き、scriptコンポーネントがそのエンティティ上で任意の数のスクリプトを実行します。

システム​

コンポーネントのタイプごとに、システムが1つあります。これは、そのタイプのすべてのコンポーネントを作成、更新、破棄し、それらが共有する設定を保持するComponentSystemです。システムを直接扱う必要はほとんどありません。例外の1つが共有の設定で、たとえばapp.systems.rigidbody.gravityは、すべてのRigidBodyを引っ張る重力です。

アプリケーションが実行するのは、登録されたシステムだけです。pc.AppBaseは1つも登録されていない状態で始まるので、使うシステムを列挙します。そうすれば、バンドラーは残りをビルドから除外できます。pc.Applicationは組み込みのシステムをすべて登録し、エディター、React、Web Componentsも同様です。コンポーネントシステムを参照してください。

注記

Unityから移行する場合、エンティティはゲームオブジェクトに、コンポーネントはコンポーネントに当たります。Unityからの移行を参照してください。UnityのDOTSやBevyのようなデータ指向のECSから移行する場合は、PlayCanvasのエンティティが単なる識別子ではなくシーングラフ内のオブジェクトであること、そしてコンポーネントがデータと振る舞いの両方を持つことに注意してください。

1つのシーンを4つの方法で​

カメラ、ライト、オレンジ色の箱という3つのエンティティからなるシーンです。カメラは高い位置から下に傾けて箱を見下ろし、箱は3つの面が見えるように回してあります。

上面と2つの側面が見えるように回され、暗い背景の前で左上から照らされたオレンジ色の箱

Engineをスタンドアロンで使用するのとおりにアプリケーションを設定し、render、camera、lightのコンポーネントシステムを登録した状態で、次のようにします。

const camera = new pc.Entity('camera');
camera.addComponent('camera', {
clearColor: new pc.Color(0.11, 0.12, 0.17)
});
camera.setPosition(0, 1.1, 3.2);
camera.setEulerAngles(-20, 0, 0);
app.root.addChild(camera);

const light = new pc.Entity('light');
light.addComponent('light');
light.setEulerAngles(45, -30, 0);
app.root.addChild(light);

const material = new pc.StandardMaterial();
material.diffuse = new pc.Color(1, 0.55, 0.2);
material.update();

const box = new pc.Entity('box');
box.addComponent('render', { type: 'box', material: material });
box.setEulerAngles(0, 35, 0);
app.root.addChild(box);

どの方法で開発しても、結果はapp.rootの下にある同じエンティティのツリーで、それぞれが1つのコンポーネントを持ちます。エディター、React、Web Componentsはこれらのエンジンオブジェクトを代わりに作成し、必要なときにそれらへアクセスする方法をそれぞれ用意しています。

EngineEditorReactWeb Components
エンティティnew pc.Entity('box')ヒエラルキーの項目<Entity name="box"><pc-entity name="box">
ツリー内の位置parent.addChild(box)ヒエラルキーで親の上にドラッグ親の<Entity>の中に入れ子にする親の<pc-entity>の中に入れ子にする
コンポーネントbox.addComponent('render', { type: 'box' })インスペクターのAdd Component<Entity>の中の<Render type="box" /><pc-entity>の中の<pc-render type="box">
プロパティbox.render.castShadows = falseインスペクターのフィールドcastShadows={false}cast-shadows="false"
独自の振る舞いbox.addComponent('script').create(Spin)Scriptコンポーネントのスクリプト<Script script={Spin} /><pc-script>の中の<pc-script-instance name="spin">
コードから見たエンジンのエンティティboxそのエンティティ上のスクリプトのthis.entity<Entity>のref<pc-entity>のentityプロパティ

このセクションの内容​

関連情報​