コンポーネント
コンポーネントは、エンティティに能力を1つ与えます。cameraコンポーネントを持つエンティティはシーンをレンダリングし、lightコンポーネントを持つエンティティはシーンを照らし、rigidbodyとcollisionのコンポーネントを持つエンティティは落下し、跳ね返り、衝突します。コンポーネントは自分の能力の設定をプロパティとして保持し、1つのエンティティが持てるコンポーネントは各タイプにつき1つまでです。
組み込みのコンポーネント
各名前は、その環境でのコンポーネントのリファレンスにリンクしています。エンジンでの名前は、addComponent()に渡す名前であり、エンティティ上でそのコンポーネントを保持するプロパティの名前でもあります。entity.camera、entity.rigidbodyなどです。
ReactとWeb Componentsは、ほとんどのアプリケーションが使うコンポーネントをラップしています。ダッシュはラッパーがないことを示しますが、後述のように、コードからエンジンのエンティティにそのコンポーネントを追加することはできます。
コンポーネントの追加
コンポーネントは、開始時の設定を指定してエンティティに追加します。指定しなかった設定はデフォルト値になります。
- Engine
- Editor
- React
- Web Components
const lamp = new pc.Entity('lamp');
lamp.addComponent('light', {
type: 'omni',
color: new pc.Color(1, 0.8, 0.6),
range: 10
});
app.root.addChild(lamp);
addComponent()は新しいコンポーネントを返し、そのコンポーネントはlamp.lightとしても参照できます。エンティティがすでにlightを持っている場合はnullを返し、デバッグ版のエンジンでは警告を出力します。アプリケーションがlightのコンポーネントシステムを登録していない場合もnullを返します。コンポーネントシステムを参照してください。
エンティティを選択してインスペクターのAdd Componentをクリックするか、ヒエラルキーでエンティティを右クリックしてAdd Componentを選択します。メニューではコンポーネントが役割ごとにグループ分けされ、エンティティがすでに持っているものはグレー表示になります。新しいコンポーネントはインスペクターにパネルとして表示され、プロパティはデフォルト値になっています。

<Entity>の中にコンポーネントを置き、設定をpropsとして渡します。
import { Entity } from '@playcanvas/react';
import { Light } from '@playcanvas/react/components';
<Entity name="lamp">
<Light type="omni" color="#ffcc99" range={10} />
</Entity>
<pc-entity>の中にコンポーネントのタグを置き、設定を属性として指定します。
<pc-entity name="lamp">
<pc-light type="omni" color="#ffcc99" range="10"></pc-light>
</pc-entity>
実行時に<pc-entity>へ追加したコンポーネントのタグは、すぐにそのコンポーネントを追加します。
ラッパーのないコンポーネント
ReactとWeb Componentsでは、ラッパーのないコンポーネントも、コードからエンジンのエンティティに追加できます。
- React
- Web Components
置かれたエンティティにエンジンのコンポーネントを追加し、アンマウント時に取り除くコンポーネントを書きます。useParent()は、それを囲む<Entity>のエンジンのエンティティを返します。
import { useEffect } from 'react';
import { Entity } from '@playcanvas/react';
import { useParent } from '@playcanvas/react/hooks';
function AudioListener() {
const entity = useParent();
useEffect(() => {
entity.addComponent('audiolistener');
return () => {
// エンティティごとアンマウントした場合、そのコンポーネントはすでに破棄されています
if (entity.audiolistener) entity.removeComponent('audiolistener');
};
}, [entity]);
return null;
}
<Entity name="camera">
<AudioListener />
</Entity>
エンティティの準備ができるのを待ってから、コンポーネントを追加します。
<pc-entity name="logo"></pc-entity>
<script type="module">
import { whenReady } from '@playcanvas/web-components';
const logo = await whenReady('pc-entity[name="logo"]');
logo.entity.addComponent('sprite', { type: 'simple' });
</script>
プロパティの読み取りと変更
コンポーネントの設定はプロパティで、いつでも読み取りと変更ができ、コンポーネントはすぐに反応します。ベクトルや色のプロパティを変更するには、新しい値を代入します。
- Engine
- Editor
- React
- Web Components
lamp.light.intensity = 2;
lamp.light.color = new pc.Color(1, 0, 0);
console.log(lamp.light.range); // 10
インスペクターでコンポーネントのパネルのフィールドを編集します。シーンを起動している間は、変更が実行中のアプリケーションに送られるので、結果を見ながら値を調整できます。フィールドを右クリックすると、その値をコピーして、同じ型のフィールドに貼り付けられます。
実行時にプロパティを変更するには、スクリプトから設定します。たとえばthis.entity.light.intensity = 2です。
propを変更します。コンポーネントのプロパティは、そのコンポーネントがレンダリングされるときに更新されます。
function Lamp({ on }) {
return (
<Entity name="lamp">
<Light type="omni" intensity={on ? 2 : 0} />
</Entity>
);
}
属性を変更します。
const light = document.querySelector('pc-entity[name="lamp"] > pc-light');
light.setAttribute('intensity', '2');
要素の準備ができると、そのcomponentプロパティがエンジンのコンポーネントになるので、属性のないプロパティはこれを通して扱います。
コンポーネントの無効化と削除
すべてのコンポーネントはenabledプロパティを持っています。無効にしたコンポーネントは働かなくなります。無効なrenderコンポーネントは描画されず、無効なscriptコンポーネントはスクリプトの実行を止めますが、再び有効にするまで設定は保持されます。コンポーネントを削除すると、コンポーネントもその設定も消えます。エンティティ全体を無効にすると、そのすべてのコンポーネントがまとめて無効になります。有効化と無効化を参照してください。
- Engine
- Editor
- React
- Web Components
box.render.enabled = false; // boxの描画を止めます
box.render.enabled = true; // 再び描画します
box.removeComponent('render');
コンポーネントのオンとオフは、パネルのヘッダーにあるスイッチで切り替えます。ヘッダーの歯車アイコンからは、Copy Component、別のエンティティへのPaste Component、Remove Componentを行うメニューを開けます。
コンポーネントを取り除くには、そのレンダリングをやめます。コンポーネントにはenabled propがないので、設定を保ったまま無効にするには、エンティティへのrefを通してエンジンのコンポーネントのenabledを設定します。
import { useEffect, useRef } from 'react';
import { Entity } from '@playcanvas/react';
import { Light, Render } from '@playcanvas/react/components';
function Box({ visible, lit }) {
const ref = useRef(null);
useEffect(() => {
ref.current.render.enabled = visible;
}, [visible]);
return (
<Entity ref={ref} name="box">
<Render type="box" />
{lit && <Light type="omni" />}
</Entity>
);
}
コンポーネントを無効にするにはタグのenabled属性を設定し、削除するにはタグを取り除きます。
<pc-entity name="box">
<pc-render type="box" enabled="false"></pc-render>
</pc-entity>
独自の振る舞いの追加
組み込みのコンポーネントは、エンジンが提供する能力をカバーしています。開くドアからゲームのルールまで、それ以外のすべてについてはスクリプトを書き、scriptコンポーネントでエンティティにアタッチします。1つのscriptコンポーネントは任意の数のスクリプトを実行でき、各スクリプトはthis.entityで自分のエンティティにアクセスします。次のスクリプトは、エンティティを垂直軸の周りに回転させます。
import { Script } from 'playcanvas';
export class Spin extends Script {
static scriptName = 'spin';
/**
* 回転の速さ(度/秒)。
*
* @attribute
*/
speed = 90;
update(dt) {
this.entity.rotate(0, this.speed * dt, 0);
}
}
- Engine
- Editor
- React
- Web Components
box.addComponent('script');
box.script.create(Spin, { properties: { speed: 45 } });
スクリプトをspin.mjsのようなアセットとして保存し、エンティティにScriptコンポーネントを追加して、そのAdd Scriptの一覧からspinを選択します。すると、インスペクターにspeed属性のフィールドが表示されます。あなたのスクリプトの管理を参照してください。
script以外のpropsは、スクリプトのインスタンスに代入されます。
import { Script } from '@playcanvas/react/components';
<Entity name="box">
<Render type="box" />
<Script script={Spin} speed={45} />
</Entity>
スクリプトをその名前でアプリケーションに登録し、<pc-script>の中の<pc-script-instance>で追加します。
<pc-entity name="box">
<pc-render type="box"></pc-render>
<pc-script>
<pc-script-instance name="spin" attributes='{"speed": 45}'></pc-script-instance>
</pc-script>
</pc-entity>
<script type="module">
import { registerScript } from 'playcanvas';
import { whenReady } from '@playcanvas/web-components';
import { Spin } from './spin.mjs';
await whenReady('pc-app');
registerScript(Spin, 'spin');
</script>
コンポーネントシステム
アプリケーションには、コンポーネントのタイプごとに1つのコンポーネントシステムがあり、そのタイプのすべてのコンポーネントを作成し、毎フレーム更新し、破棄します。システムはコンポーネントと同じ名前でapp.systemsに置かれ、その一部はすべてのコンポーネントが共有する設定を保持しています。
// すべてのRigidBodyを引っ張る重力
app.systems.rigidbody.gravity = new pc.Vec3(0, -1.62, 0);
アプリケーションが追加できるのは、システムを登録したコンポーネントだけです。pc.Applicationは組み込みのシステムをすべて登録し、エディター、React、Web Componentsも同様です。pc.AppBaseは列挙したシステムだけを登録するので、バンドラーはそれ以外をビルドから除外できます。
const options = new pc.AppOptions();
options.graphicsDevice = device;
options.componentSystems = [
pc.RenderComponentSystem,
pc.CameraComponentSystem,
pc.LightComponentSystem,
pc.ScriptComponentSystem
];
const app = new pc.AppBase(canvas);
app.init(options);
設定の残りについては、Engineをスタンドアロンで使用するを参照してください。
関連情報
- エンティティ - コンポーネントを持つエンティティの作成、有効化、破棄、複製
- スクリプティング - スクリプトの書き方、ライフサイクル、属性
- インスペクターパネル - エディターでのコンポーネントの編集
- PlayCanvas ReactとWeb Components - Reactのコンポーネントと、Web Componentsのタグ
- ComponentとComponentSystem - エンジンのAPIリファレンス