Examples are implemented as classes in JavaScript located at ./src/examples/<category>/<exampleName>.example.mjs. An example typically consists of two main modules:
1. <exampleName>.example.mjs (Required)
This file contains the core logic. The code is executed every time the example is played. It must retrieve the canvas from the DOM and initialize a PlayCanvas Application or AppBase.
Configuration via Comments: You can define metadata and engine settings using special comment blocks:
@config: Default configuration.@keybinds: Key bindings.@credit: Metadata (title, author, license).@flag: Engine flags (e.g., WEBGPU_DISABLED, ENGINE=performance).
2. <exampleName>.controls.jsx (Optional)
Used to create a PCUI-based control panel via React. The component must be named Controls and accepts a single prop: observer (a pcui observer).
3. Sidecar Files
Any file added to the example folder with the example name prepended (e.g., <exampleName>.shader.vert) can be imported.
.frag, .vert, .wgsl, .glsl, .html, .css, .txt are imported as strings..json files are imported as parsed values.
// <exampleName>.example.mjs
import { Application } from 'playcanvas';
// @config
// @flag WEBGPU_DISABLED
const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('application-canvas'));
window.focus();
const app = new Application(canvas, {});
// Export destroy if you need to clean up non-app resources
export function destroy() {
// cleanup logic
}
// <exampleName>.controls.jsx
import { Button } from '@playcanvas/pcui/react';
/**
* @param {{ observer: Observer }} props
*/
export function Controls({ observer }) {
return (
<Button
text='Flash'
onClick={() => observer.set('flash', !observer.get('flash'))}
/>
);
}