インタラクティビティ
Scene ができたら、インタラクティブにしたくなるはずです。用途に応じて、いくつかの方法があります。
ポインターイベント
Entity にポインターイベントを付与すると、ユーザー操作に応答できます。リアクティブに入力を扱う簡単な方法です。
ポインターイベントはバブルします。親の Entity にイベントを付ければ、React ツリーを通じて伝播します。
クリックで色が変わる球体を作ってみましょう。
- Demo
- Code
import { useState } from 'react'
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { useMaterial } from '@playcanvas/react/hooks'
export const Interactivity = () => {
const colors = [
'lavender', 'lightsteelblue', 'powderblue', 'rebeccapurple'
]
// Create the initial diffuse color and create the material
const [diffuse, setDiffuse] = useState('lightsteelblue')
const material = useMaterial({ diffuse })
const onRequestRandomColor = () => {
setDiffuse(colors[Math.floor(Math.random() * colors.length)])
}
// Attach hover and leave handlers to the sphere
const onHover = () => document.body.style.cursor = 'pointer'
const onLeave = () => document.body.style.cursor = 'default'
return (
// Attach an onClick handler to the sphere to request a color change
<Entity
name="sphere"
onClick={onRequestRandomColor}
onPointerOver={onHover}
onPointerOut={onLeave} >
<Render type="sphere" material={material} />
</Entity>
)
}
Entity は、DOM の Pointer Events API に近い挙動で、次のポインターイベントをサポートします。
onPointerUponPointerDownonPointerOveronPointerOutonClick
Script コンポーネント
Script コンポーネントは、Entity に独自の振る舞いを追加する便利な方法です。任意の ESM 形式の PlayCanvas Script を Entity に取り付けられます。インタラクティビティやアニメーション、React のレンダーループ外で行いたい処理に適しています。
ESM 形式の PlayCanvas Script を <Script> コンポーネントの script Prop に渡します。
- Demo
- Code
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { Script } from '@playcanvas/react/components'
import { Script as PcScript } from 'playcanvas'
/**
* A simple script that rotates the entity it's attached to.
*/
class SpinningCube extends PcScript {
static scriptName = 'spinningCube'
speed = 10
update(dt) {
this.entity.rotate(0, dt * this.speed, dt * this.speed * 2)
}
}
export const Scripting = () => (
<Entity>
<Render type="box" />
<Script script={SpinningCube} speed={10} />
</Entity>
)
PlayCanvas の Script は Script クラスを拡張した ESM モジュールです。既存の Script や自作、エンジンリポジトリの既存 Scriptも利用できます。
毎フレームアニメーションさせたい場合は、React ツリーを再レンダリングするより <Script> コンポーネントの方が一般的にパフォーマンスに有利です。ただし Script が Entity の Props を上書きすることもあります。
詳しくはドキュメントの Scriptを参照してください。
Application イベント
より React らしい方法として、useAppEvent フックがあります。PlayCanvas のアプリケーションイベントを、適切な TypeScript の型付きで購読できます。組み込みイベントと、コールバックのシグネチャが決まったカスタムイベントの両方に対応します。
次の例では、useAppEvent で update イベントを購読し、カプセルを回転させます。
- Demo
- Code
import { useAppEvent } from '@playcanvas/react/hooks'
import { Entity } from '@playcanvas/react'
import { Render } from '@playcanvas/react/components'
import { useRef } from 'react'
export const AppEvents = () => {
const speed = 10;
const boxRef = useRef(null);
useAppEvent('update', (dt) => {
boxRef.current?.rotate(0, dt * speed, dt * speed * 2);
});
const onEntityClick = () => {
console.log('Entity clicked');
}
return (
<Entity ref={boxRef}>
<Render type='capsule' />
</Entity>
)
}
フックできるアプリケーションイベントは複数あり、それぞれコールバックのシグネチャが決まっています。利用可能なイベントは Engine の Application API を確認してください。
app.fire メソッドで独自のイベントを発火することもできます。
import { useAppEvent } from '@playcanvas/react/hooks'
const MyComponent = () => {
useAppEvent('myEvent', (message) => {
console.log('My event fired.', message);
});
}
app.fire('myEvent', 'Hello, world!');