カメラコントロール
ほとんどのアプリケーションでは、ユーザーがカメラを動かす手段が必要です。これを一から書く代わりに、エンジンに付属する scripts/esm/camera-controls.mjs の CameraControls スクリプトを使用できます。1つのスクリプトで、プロダクション品質のナビゲーションが手に入ります:
- オービット — マウスの左ドラッグでフォーカスポイントを中心に回転、中ボタンのドラッグでパン、マウスホイールでズームします。
- フライ — WASDキーでカメラを自由に移動でき、右ボタンのドラッグで視点を動かします。
- タッチとゲームパッド — マルチタッチジェスチャーとゲームパッド入力を標準でサポートします。
スクリプトをカメラエンティティにアタッチします:
- Engine
- Editor
- React
- Web Components
// スクリプトを読み込む(ここではCDNから。アプリにバンドルすることも可能)
const asset = new Asset('camera-controls', 'script', {
url: 'https://cdn.jsdelivr.net/npm/playcanvas/scripts/esm/camera-controls.mjs'
});
app.assets.add(asset);
app.assets.load(asset);
asset.ready(() => {
// カメラエンティティにアタッチする
camera.addComponent('script');
camera.script.create('cameraControls', {
properties: {
focusPoint: new Vec3(0, 1, 0)
}
});
});
バンドラーを使用してアプリをビルドする場合は、代わりにスクリプトクラスを直接インポートできます:
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
camera.addComponent('script');
camera.script.create(CameraControls);
camera-controls.mjs をスクリプトアセットとしてプロジェクトに追加します(エンジンリポジトリからコピーしてください)。次に、カメラエンティティを選択してScriptコンポーネントを追加し、cameraControls スクリプトを追加します。スクリプトの属性はインスペクターで調整できます。
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
import { Script } from '@playcanvas/react/components';
<Entity name="camera" position={[0, 1, 4]}>
<Camera />
<Script script={CameraControls} />
</Entity>
<pc-app>
<pc-asset src="https://cdn.jsdelivr.net/npm/playcanvas/scripts/esm/camera-controls.mjs"></pc-asset>
<pc-scene>
<pc-entity name="camera" position="0 1 4">
<pc-camera></pc-camera>
<pc-script>
<pc-script-instance name="cameraControls"></pc-script-instance>
</pc-script>
</pc-entity>
</pc-scene>
</pc-app>
設定
このスクリプトは豊富な属性を公開しています。よく使われるものは次のとおりです:
| 属性 | デフォルト | 説明 |
|---|---|---|
enableOrbit | true | オービットコントロールを有効にする |
enableFly | true | フライコントロールを有効にする |
enablePan | true | パンを有効にする |
focusPoint | [0, 0, 0] | カメラが周回する中心点 |
rotateSpeed | 0.2 | 回転の感度 |
moveSpeed | 10 | フライの移動速度(moveFastSpeed と moveSlowSpeed のバリエーションあり) |
zoomSpeed | 0.001 | ズームの感度 |
pitchRange | [-360, 360] | カメラのピッチ角の制限(度単位) |
zoomRange | [0.01, 0] | ズーム距離の最小/最大(最大が0の場合は無制限) |
leftButton | orbit | マウス左ボタンのアクション。マウスボタンを参照 |
middleButton | pan | マウス中ボタンのアクション |
rightButton | look | マウス右ボタンのアクション |
groundPan | false | ビューの平面ではなく地面に沿ってパンする。マップのように地面をドラッグするを参照 |
ダンピング属性(rotateDamping、moveDamping、zoomDamping、focusDamping、すべてデフォルトは 0.98)は、動きがどれだけ滑らかに減速するかを制御します。0にすると即座に停止します。純粋なオービットカメラを作るにはフライを無効に、純粋なフライカメラを作るにはオービットを無効にしてください。
マウスボタン
leftButton、middleButton、rightButton 属性で、各マウスボタンの動作を設定します:
| アクション | 説明 |
|---|---|
orbit | フォーカスポイントを中心にビューを回転します。Shiftキーを押している間は、代わりにパンします。 |
pan | ビューをパンします。 |
look | キーでフライするときのように、その場でビューを回転します。enableFly がオフの場合は、代わりにオービットします。 |
none | ボタンを無視し、アプリケーションに任せます。 |
デフォルトでは、左ボタンでオービット、中ボタンでパン、右ボタンでルックします。Editorでは、これらの属性はインスペクターのドロップダウンとして表示されます。たとえば、左ボタンで見回し、右ボタンでオービットするには:
camera.script.create(CameraControls, {
properties: {
leftButton: 'look',
rightButton: 'orbit'
}
});
ドラッグは、それを開始したボタンに従います。ブラウザーは新しい押下として報告しないため、ドラッグ中に2つ目のボタンを押しても何も変わりません。
アプリケーション用にボタンを確保する
none に設定したボタンは、その押下とそれに続くドラッグの両方が完全に無視されるため、アプリケーションで(たとえばペイントや選択に)使用できます。他のボタンとマウスホイールは引き続きナビゲーションに使えます:
camera.script.create(CameraControls, {
properties: {
rightButton: 'none'
}
});
app.mouse.on(EVENT_MOUSEDOWN, (event) => {
if (event.button === MOUSEBUTTON_RIGHT) {
// ペイントを開始する
}
});
Paintサンプルがこの方法を使っています。
マップのように地面をドラッグする
デフォルトでは、パンはカメラをビューの平面に沿って移動します。groundPan を有効にすると、ドラッグはマップをドラッグするときのようにカーソルの下の地面の点を保持し、カメラの高さは変わりません。地面は focusPoint の高さにある水平面なので、フォーカスポイントを地面の高さに置いてください。2本指のタッチによるパンも地面に沿って移動します。左ボタンでマップをドラッグし、他のボタンでオービットするには:
camera.script.create(CameraControls, {
properties: {
leftButton: 'pan',
middleButton: 'orbit',
rightButton: 'orbit',
groundPan: true,
focusPoint: new Vec3(0, 0, 0)
}
});
サンプル
エンジンのサンプルでスクリプトの動作を確認できます:
独自のカメラロジックを構築したい場合は、Orbit Cameraチュートリアルで完全な実装を解説しています。