create-playcanvas 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/package.json +1 -1
  2. package/skills/apply-conventions/SKILL.md +2 -0
  3. package/skills/assemble-scene/references/web-components.md +2 -2
  4. package/skills/bake-lighting/SKILL.md +61 -0
  5. package/skills/build-app/references/web-components.md +4 -4
  6. package/skills/build-hud/SKILL.md +2 -0
  7. package/skills/find-examples/references/web-components.md +1 -1
  8. package/skills/light-scene/SKILL.md +10 -0
  9. package/skills/override-shader-chunks/SKILL.md +59 -0
  10. package/skills/reduce-draw-calls/SKILL.md +61 -0
  11. package/skills/reuse-scripts/references/web-components.md +3 -3
  12. package/skills/verify-pixels/SKILL.md +50 -0
  13. package/templates/web-components/base/README.md +3 -3
  14. package/templates/web-components/base/package.json +1 -1
  15. package/templates/web-components/first-person-controller/index.html +26 -26
  16. package/templates/web-components/first-person-controller/src/main.ts +1 -1
  17. package/templates/web-components/interactive-sphere/src/main.ts +1 -1
  18. package/templates/web-components/model-viewer/src/main.ts +1 -1
  19. package/templates/web-components/physics-playground/index.html +3 -3
  20. package/templates/web-components/physics-playground/src/main.ts +1 -1
  21. package/templates/web-components/product-configurator/src/main.ts +3 -1
  22. package/templates/web-components/spinning-cube/src/main.ts +1 -1
  23. package/templates/web-components/splat-viewer/src/main.ts +1 -1
  24. package/templates/web-components/third-person-controller/index.html +15 -15
  25. package/templates/web-components/third-person-controller/src/main.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-playcanvas",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Scaffold a PlayCanvas project",
5
5
  "keywords": [
6
6
  "playcanvas",
@@ -43,6 +43,8 @@ details. Apply these stable conventions throughout the project.
43
43
  - Materials cull back faces by default; counter-clockwise winding defines the front face.
44
44
  - Clone a material before per-instance tinting or edits, and assign the clone; never mutate one
45
45
  shared by other instances, including default and asset-imported materials.
46
+ - `setParameter` uploads raw values; author colours in sRGB and convert with `Color#linear()`
47
+ before upload — do not hand-roll gamma.
46
48
  - Entities do not have an `aabb`. Union descendant `meshInstance.aabb` values after transforms have
47
49
  synchronized.
48
50
  - Let `Mesh.update()` calculate local bounds. If passing `false` for `updateBoundingBox`, assign an
@@ -4,7 +4,7 @@ Represent the whole gameplay object below one semantic root:
4
4
 
5
5
  ```html
6
6
  <pc-entity name="Enemy_1" position="4 0 -3" rotation="0 90 0">
7
- <pc-rigidbody type="dynamic" mass="1"></pc-rigidbody>
7
+ <pc-rigid-body type="dynamic" mass="1"></pc-rigid-body>
8
8
  <pc-collision type="capsule"></pc-collision>
9
9
  <pc-entity position="0 0.8 0" rotation="0 180 0" scale="0.01 0.01 0.01">
10
10
  <pc-model asset="enemy"></pc-model>
@@ -14,6 +14,6 @@ Represent the whole gameplay object below one semantic root:
14
14
 
15
15
  Keep component tags as direct children of the owning `<pc-entity>`. Register the model with a
16
16
  direct-child `<pc-asset>` under `<pc-app>`. Before using rigid bodies, load Ammo with a direct-child
17
- `<pc-module name="Ammo">` carrying its `glue`, `wasm`, and `fallback` attributes; `<pc-app>` awaits
17
+ `<pc-wasm name="Ammo">` carrying its `glue`, `wasm`, and `fallback` attributes; `<pc-app>` awaits
18
18
  its direct-child modules before creating the graphics device, so every body in the document depends
19
19
  on that one element. Add and remove the semantic root as one DOM subtree.
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: bake-lighting
3
+ description: Use when a PlayCanvas scene's static lighting, shadows, or ambient occlusion costs too much per frame, or lighting must ship precomputed for startup or payload budgets.
4
+ ---
5
+
6
+ # Precompute static lighting
7
+
8
+ Static geometry lit by static lights can bake into lightmap textures once, removing per-frame
9
+ shadow-map rendering and per-pixel dynamic lighting for that light entirely.
10
+
11
+ ## Engine `Lightmapper` flags
12
+
13
+ - Engine-only bootstraps must register it: `AppOptions.lightmapper = Lightmapper`. `Application`
14
+ wires this by default; only a manual `AppOptions` assembly needs the explicit line.
15
+ - Per light: `light.bake = true`, then `light.affectDynamic = false` once every mesh it lights is
16
+ lightmapped, so it stops contributing to the real-time pass.
17
+ - Per mesh: `render.lightmapped = true` — required for the mesh to receive any light once
18
+ `affectDynamic` is false, a correctness requirement, not just an optimization —
19
+ `render.lightmapSizeMultiplier` to size its lightmap, `render.castShadowsLightmap` so lightmapped
20
+ meshes still shadow each other in the bake.
21
+ - Bake mode: `BAKE_COLOR` for flat diffuse materials; `BAKE_COLORDIR` adds a dominant-light-direction
22
+ pass for normal- or specular-mapped materials that need one.
23
+ - Baked ambient occlusion, independent of any light: `scene.ambientBake` plus
24
+ `ambientBakeNumSamples`, `ambientBakeOcclusionBrightness`/`OcclusionContrast`.
25
+ - Run `app.lightmapper.bake(null, mode)` once the scene exists; `null` bakes every lightmapped node.
26
+
27
+ ## Verify UVs before trusting this on real assets
28
+
29
+ Procedural primitives auto-generate a usable UV set; imported GLB models often do not ship a second,
30
+ non-overlapping UV channel suitable for a lightmap atlas. Read the installed engine's source for
31
+ what its `Lightmapper` actually requires — which UV set it samples, whether it unwraps one for you —
32
+ before assuming a real model will bake correctly. Do not carry a primitive-only test result into
33
+ production assets unchecked.
34
+
35
+ ## Choose the rung by budget, not by default
36
+
37
+ On-device bake cost scales with baked-node count and lightmap resolution; estimate it against the
38
+ startup budget before choosing a rung. Stay on-device unless:
39
+
40
+ - the estimated bake time does not fit the startup or first-paint budget on the target device, or
41
+ - the result needs stylized material detail beyond lighting that the runtime `Lightmapper` cannot
42
+ produce.
43
+
44
+ Only then move to an offline bake shipped as assets, following the same shape as any other
45
+ generated-asset pipeline: registry-keyed per-asset configs (a new asset is a config change, not new
46
+ pipeline code), a CLI with per-target fast paths, staged size logging, worker-thread parallelism for
47
+ build time, and a coverage self-audit that fails the bake when an expected output is missing or
48
+ empty.
49
+
50
+ ## Keep dynamic objects consistent
51
+
52
+ Whichever rung you use, dynamic objects moving through baked lighting must not read as ignoring it:
53
+ sample or approximate the baked occlusion/shadow field for them and their attachments so they dim to
54
+ the same levels as the static geometry around them, and ground them with a contact shadow. A
55
+ dynamic object whose custom shading must meet baked maps is `override-shader-chunks` territory.
56
+
57
+ ## Prove it
58
+
59
+ Capture `verify-pixels`-style frames both in and out of the baked shadow, before and after the
60
+ change, and compare them. A screenshot glanced at once is not proof the bake reproduced the lighting
61
+ it removed.
@@ -35,10 +35,10 @@ Build supported application structure declaratively:
35
35
  - Treat a present boolean attribute as true unless its value is `false`; remove it to restore the
36
36
  Engine default.
37
37
 
38
- Load Engine `Script` modules with `<pc-asset>`, then attach them through `<pc-scripts>` and
39
- `<pc-script>`. Match the element's `name` to the class's static `scriptName`. Extra kebab-case
40
- attributes map to camelCase properties; use the `attributes` JSON attribute for nested or reserved
41
- values.
38
+ Load Engine `Script` modules with `<pc-asset>`, then attach them through `<pc-script>` and
39
+ `<pc-script-instance>`. Match the instance element's `name` to the class's static `scriptName`.
40
+ Extra kebab-case attributes map to camelCase properties; use the `attributes` JSON attribute for
41
+ nested or reserved values.
42
42
 
43
43
  Use `whenReady` for occasional page-level Engine access:
44
44
 
@@ -20,6 +20,8 @@ each transition; never store gameplay truth in the DOM or a UI element.
20
20
 
21
21
  - Map each overlay to a game state and each indicator to a snapshot field. A transition shows or
22
22
  hides overlays; it does not duplicate the state the game already owns (see `manage-game-state`).
23
+ - An indicator that is idle most of the time toggles `enabled` with its visibility; an element left
24
+ drawing at opacity 0 still costs a draw call every frame (see `reduce-draw-calls`).
23
25
  - Anchor and scale elements to the viewport so the layout holds at the target resolution and on
24
26
  resize. Verify at the acceptance resolution, not the default window size.
25
27
  - Keep copy minimal and legible over the scene: back text with a plate or shadow where the frame is
@@ -9,7 +9,7 @@ update logic. Drop its graphics device and application bootstrap because `<pc-ap
9
9
  - Express supported entities and components with `pc-*` elements.
10
10
  - Register assets as direct children of `<pc-app>` with `<pc-asset>`.
11
11
  - Put per-entity behavior in an Engine `Script` loaded through `<pc-asset>` and attached with
12
- `<pc-scripts>` and `<pc-script>`.
12
+ `<pc-script>` and `<pc-script-instance>`.
13
13
  - Use `whenReady` for page-level glue or Engine APIs with no declarative element.
14
14
  - Fetch example assets from the same Engine tag as the source example.
15
15
 
@@ -33,6 +33,16 @@ Keep the two named production integrations visible in the implementation:
33
33
  Do not continue to cosmetic tuning while either integration is missing or diagnostics report a
34
34
  shader, texture, or framebuffer error.
35
35
 
36
+ ## Stylized and prebaked scenes
37
+
38
+ When the art direction is deliberately flat or stylized rather than photoreal, or the platform's
39
+ startup, frame, or payload budget rules out the runtime pipeline above, do not treat `Water`,
40
+ `CameraFrame`, and the sky/IBL bake as mandatory. The sanctioned alternative is baked static
41
+ lighting via the `bake-lighting` skill plus custom material shading via the `override-shader-chunks`
42
+ skill. Either way, dynamic objects and their attachments must sample or approximate the baked
43
+ occlusion so they dim to the same levels as the baked surfaces, grounded with contact shadows. Fall
44
+ back to the runtime pipeline above as the default path when neither trigger holds.
45
+
36
46
  ## Light and expose
37
47
 
38
48
  - Establish one dominant key light with a clear direction and warm or cool intent, then add soft
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: override-shader-chunks
3
+ description: Use when a PlayCanvas StandardMaterial needs custom shading its properties cannot express — procedural or stylized looks, custom vertex displacement, per-material screen effects — before writing a standalone shader from scratch.
4
+ ---
5
+
6
+ # Override shading through chunks
7
+
8
+ A `StandardMaterial`'s shader is assembled from named chunks (lighting, combine, transform, and
9
+ more). Overriding one keeps the rest of the pipeline — fog, tonemapping, shadows, skinning,
10
+ instancing — intact. Reach for a fully custom `ShaderMaterial` only when the look needs a stage the
11
+ chunk system does not expose at all (its own vertex/fragment pair and attribute layout); a chunk
12
+ override is the default for everything else, since it is cheaper and stays integrated.
13
+
14
+ ## Pin the version, read the source
15
+
16
+ Set `material.shaderChunksVersion` to the installed engine's major.minor (for example `'2.21'`)
17
+ before shipping any override. Chunk names and their contracts — what a chunk defines, what globals
18
+ it reads or writes — are version-keyed and change between releases. Read the installed `playcanvas`
19
+ source for the exact chunk being touched; do not recall its contract from memory or an older
20
+ version's documentation.
21
+
22
+ ## Set chunks through the documented accessor
23
+
24
+ Use `material.getShaderChunks(SHADERLANGUAGE_GLSL).set(name, source)`, and the WGSL equivalent —
25
+ the public, documented method — not the underlying `shaderChunks` maps, which are internal. Call
26
+ `material.update()` after any change so cached shader variants are cleared.
27
+
28
+ ## Emissive-only overrides
29
+
30
+ An `emissivePS` override implements `void getEmission()`, writing the result into `dEmission`. When
31
+ the override is meant to fully drive the visible color, zero the material's `diffuse`/`specular` and
32
+ disable `useSkybox` so no other lighting term still contributes underneath it.
33
+
34
+ ## Uniforms are raw
35
+
36
+ `setParameter` uploads exactly what it is given, with no color-space conversion. Convert any
37
+ authored sRGB color with `Color#linear()` before calling `setParameter`; an sRGB color passed
38
+ straight through renders visibly darker and less saturated than it was authored.
39
+
40
+ ## Keep vertex chunks instancing-aware
41
+
42
+ A custom `transformCoreVS` (or any vertex chunk reading the model matrix) must keep the engine's
43
+ `INSTANCING` define path — pulling the per-instance matrix under that define — with a
44
+ non-instanced fallback that uses `matrix_model` directly, matching the stock chunk's structure.
45
+ Dropping this path silently breaks instancing for any mesh instance using the material.
46
+
47
+ ## Provide GLSL and WGSL, or pin to WebGL
48
+
49
+ Override both `SHADERLANGUAGE_GLSL` and `SHADERLANGUAGE_WGSL` chunks for anything touched. On a
50
+ WebGPU device, a chunk supplied only in GLSL forces the material's entire shader — not just that
51
+ chunk — onto a GLSL-compiled-then-transpiled path; without the optional transpiler modules loaded
52
+ (the common case), that shader fails to compile. Supply both languages, or explicitly pin the
53
+ graphics device to WebGL if WGSL support is not required.
54
+
55
+ ## Expand bounds for vertex displacement
56
+
57
+ If the override displaces vertices, expand the mesh's bounds by the maximum displacement (see
58
+ `apply-conventions`) — CPU-computed bounds never observe shader-side deformation, so culling breaks
59
+ silently otherwise.
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: reduce-draw-calls
3
+ description: Use when a PlayCanvas application submits too many draw calls or frame time is CPU-bound — repeated meshes, dense grids, always-on interface elements — before hand-writing mesh merging or custom renderers.
4
+ ---
5
+
6
+ # Cut draw calls, ranked by cost
7
+
8
+ Work the ladder in order and stop at the first rung that clears the budget. Each rung trades away
9
+ less flexibility than the next; skipping straight to a custom renderer or hand-written mesh merge
10
+ costs more engineering time than the draw calls it saves.
11
+
12
+ ## Measure first
13
+
14
+ Read `app.stats.drawCalls.total` (or the `forward`/`depth`/`shadow` breakdown) before changing
15
+ anything, or drop in `MiniStats` for a live overlay. Every rung below is proved against this number,
16
+ not against intuition about what "looks expensive."
17
+
18
+ ## Rung 1: stop drawing invisible things
19
+
20
+ An element at opacity 0 still submits a draw call — its mesh instance exists and is still in a
21
+ layer, so the GPU processes it every frame for no visible result. Toggle `enabled` on the entity to
22
+ actually skip it. Check every element that is ever fully transparent, not only the ones on screen
23
+ when you're profiling — this rung is easy to skip precisely because nothing looks wrong.
24
+
25
+ ## Rung 2: `BatchManager` — merge without touching shaders
26
+
27
+ `app.batcher.addGroup(name, dynamic, maxAabbSize)`, then set `batchGroupId` on each member's
28
+ component (render, sprite, or UI element). Use `dynamic: false` for geometry that never moves.
29
+
30
+ Contract: the `batchGroupId` setter only inserts into the batcher while `entity.enabled` is true,
31
+ and that flag requires both the local enable state and hierarchy attachment — set `batchGroupId`
32
+ after the entity is parented into the live tree, not before, or the member silently drops out of the
33
+ group. `BatchManager.generate()` runs once automatically on the app's first rendered frame; if group
34
+ membership changes afterward, call `app.batcher.markGroupDirty(id)` (or `generate([id])`) yourself.
35
+ An Engine-only app without the full `Application` bootstrap must register the class via
36
+ `AppOptions.batchManager` before it can batch anything.
37
+
38
+ ## Rung 3: hardware instancing — merge without touching layout
39
+
40
+ Reach for this once distinct materials or per-frame transform updates would defeat `BatchManager`.
41
+ Build a per-instance vertex buffer with `VertexFormat.getDefaultInstancingFormat(device)` (one mat4
42
+ per instance), call `meshInstance.setInstancing(vb)`, and set `instancingCount`. A custom vertex
43
+ chunk needs its own `INSTANCING` code path with an identity-matrix fallback for the non-instanced
44
+ case (cross-reference `override-shader-chunks`).
45
+
46
+ Culling trade-off: instanced meshes cull as one unit against a single bounding volume — an
47
+ off-screen instance inside an otherwise-visible group still draws unless you opt in. Pass
48
+ `setInstancing(vb, true)` and set a `RenderComponent#customAabb` spanning every instance's world
49
+ extent so the renderer has something correct to cull against instead of culling nothing or
50
+ culling the whole group by one instance's bounds.
51
+
52
+ Adapt the official recipes rather than deriving the buffer layout or vertex-shader wiring from
53
+ memory: `graphics/instancing-basic` for the format/buffer contract, `graphics/instancing-custom` for
54
+ the vertex-shader side. Locate both at the installed engine version via `find-examples`.
55
+
56
+ ## Prove and report
57
+
58
+ Verify the rendered image is unchanged with `verify-pixels` before calling the change done —
59
+ merging or instancing must not move a single pixel. Re-measure `app.stats.drawCalls` afterward and
60
+ state the before/after counts in the change description; "fewer draw calls" without numbers is not
61
+ a result.
@@ -8,9 +8,9 @@ Expose an Engine script as an ES module and register it as an asset:
8
8
  <pc-scene>
9
9
  <pc-entity name="Camera">
10
10
  <pc-camera></pc-camera>
11
- <pc-scripts>
12
- <pc-script name="cameraControls" move-speed="4"></pc-script>
13
- </pc-scripts>
11
+ <pc-script>
12
+ <pc-script-instance name="cameraControls" move-speed="4"></pc-script-instance>
13
+ </pc-script>
14
14
  </pc-entity>
15
15
  </pc-scene>
16
16
  </pc-app>
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: verify-pixels
3
+ description: Use when changing PlayCanvas rendering code that must not change the rendered image — draw-call optimization, hardware instancing, shader or material refactors, or asset pipeline swaps — to prove the output unchanged before shipping.
4
+ ---
5
+
6
+ # Prove pixels unchanged
7
+
8
+ A rendering change that must not alter the image is not proven by eyeballing a screenshot at one
9
+ pose. Build a deterministic capture, compare byte-exact counts across a pose × phase matrix, and
10
+ prove the capture harness itself is trustworthy before trusting what it reports about the change.
11
+
12
+ ## Make the frame deterministic
13
+
14
+ - Drive every animated shader or vertex effect from one app-owned time value, never `Date.now()` or
15
+ `performance.now()` read inside the render path, so a captured phase is exactly reproducible.
16
+ - Freeze the clock with `app.timeScale = 0` before capturing; nothing should advance between frames
17
+ you did not explicitly step.
18
+ - Step frames explicitly: set `app.autoRender = false` once, then set `app.renderNextFrame = true`
19
+ before each frame you want rendered. The engine renders exactly that frame and clears the flag —
20
+ do not rely on the free-running render loop plus a timed screenshot.
21
+ - Read the rendered pixels with `await device.readPixelsAsync(x, y, w, h, pixels)` against the exact
22
+ backbuffer, not a re-encoded screenshot (e.g. `canvas.toDataURL`) that can introduce compression or
23
+ colour-management differences the eye won't catch. In the installed engine this method lives on
24
+ `WebglGraphicsDevice`, not the base `GraphicsDevice` type, so narrow to it (or branch on
25
+ `device.isWebGL2`) before calling; a WebGPU project needs its own equivalent readback. If the
26
+ project already has a screenshot path, hold it to the same rule: fixed size, fixed pose, no lossy
27
+ step before the byte comparison.
28
+
29
+ ## Build a pose × phase matrix
30
+
31
+ Single-pose, single-frame proof cannot see everything a rendering refactor can break. Choose at
32
+ least two representative camera poses — angles that would expose a dropped instance, a wrong batch
33
+ bound, or a seam differently — and at least two animation phases, including one mid-animation, not
34
+ only frame zero. Capture every pose × phase pair for the build before the change and the build after
35
+ it, with the same canvas size, camera, and lighting each time.
36
+
37
+ ## Run a same-build control first
38
+
39
+ Before trusting any diff between the old and new build, capture the same pose × phase matrix twice
40
+ from the *unmodified* build. Two captures of identical, frozen state must be bit-identical. If they
41
+ are not, the capture path itself is the source of noise — an unseeded animation, an asset still
42
+ loading, a GPU timing race — and must be fixed before it can say anything about the real change.
43
+
44
+ ## Gate and report
45
+
46
+ Byte-compare each pose × phase pair between the two builds; do not diff by looking. Zero differing
47
+ pixels passes outright. Any nonzero diff must be reviewed on-screen, and its cause and extent stated
48
+ in the change description — never merged silently. Report the actual count every time, for example
49
+ "0 of 65536 pixels differ" or "312 of 65536 pixels differ, confined to the object's silhouette edge".
50
+ "Looks the same" or "no visible difference" is not a result.
@@ -39,9 +39,9 @@ so `document.querySelector` reaches them and `setAttribute` changes them.
39
39
 
40
40
  `src/main.ts` covers the two things HTML alone cannot do:
41
41
 
42
- - **Attaching engine scripts.** `<pc-script name="...">` resolves scripts that `<pc-asset>` fetched at
43
- runtime. Scripts imported through the bundler — like `CameraControls` and `Grid` here — are attached
44
- through the entity instead, reached via `whenReady()` and the element's `.entity` property.
42
+ - **Attaching engine scripts.** `<pc-script-instance name="...">` resolves scripts that `<pc-asset>`
43
+ fetched at runtime. Scripts imported through the bundler — like `CameraControls` and `Grid` here — are
44
+ attached through the entity instead, reached via `whenReady()` and the element's `.entity` property.
45
45
  - **Responding to pointer input.** `<pc-app>` picks whatever is under the pointer and dispatches an
46
46
  ordinary `PointerEvent` on the `<pc-entity>` it hit, so `addEventListener('pointerup', ...)` works on a
47
47
  3D entity exactly as it would on a `<button>`. Events are only generated for entities that have a
@@ -15,7 +15,7 @@
15
15
  "typecheck": "tsc --noEmit"
16
16
  },
17
17
  "dependencies": {
18
- "@playcanvas/web-components": "^0.16.0",
18
+ "@playcanvas/web-components": "^0.17.0",
19
19
  "playcanvas": "^2.21.4"
20
20
  },
21
21
  "devDependencies": {
@@ -14,12 +14,12 @@
14
14
  <pc-material id="green-material" diffuse="#2e6638" emissive="#09140b" gloss="0.2"></pc-material>
15
15
  <pc-material id="wood-material" diffuse="#7a451a" emissive="#180e05" gloss="0.2"></pc-material>
16
16
  <pc-material id="metal-material" diffuse="#475461" emissive="#0e1113" gloss="0.5"></pc-material>
17
- <pc-module
17
+ <pc-wasm
18
18
  name="Ammo"
19
19
  glue="/ammo/ammo.wasm.js"
20
20
  wasm="/ammo/ammo.wasm.wasm"
21
21
  fallback="/ammo/ammo.js"
22
- ></pc-module>
22
+ ></pc-wasm>
23
23
  <pc-scene>
24
24
  <pc-entity name="light" rotation="50 30 0"
25
25
  ><pc-light
@@ -36,121 +36,121 @@
36
36
  <pc-entity name="floor" position="0 -0.1 0" scale="18 0.2 18"
37
37
  ><pc-render type="box" material="floor-material"></pc-render
38
38
  ><pc-collision type="box" half-extents="9 0.1 9"></pc-collision
39
- ><pc-rigidbody type="static"></pc-rigidbody
39
+ ><pc-rigid-body type="static"></pc-rigid-body
40
40
  ></pc-entity>
41
41
  <pc-entity name="back-wall" position="0 1.5 -9" scale="18 3 0.3"
42
42
  ><pc-render type="box" material="wall-material"></pc-render
43
43
  ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
44
- ><pc-rigidbody type="static"></pc-rigidbody
44
+ ><pc-rigid-body type="static"></pc-rigid-body
45
45
  ></pc-entity>
46
46
  <pc-entity name="front-wall" position="0 1.5 9" scale="18 3 0.3"
47
47
  ><pc-render type="box" material="wall-material"></pc-render
48
48
  ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
49
- ><pc-rigidbody type="static"></pc-rigidbody
49
+ ><pc-rigid-body type="static"></pc-rigid-body
50
50
  ></pc-entity>
51
51
  <pc-entity name="left-wall" position="-9 1.5 0" scale="0.3 3 18"
52
52
  ><pc-render type="box" material="wall-material"></pc-render
53
53
  ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
54
- ><pc-rigidbody type="static"></pc-rigidbody
54
+ ><pc-rigid-body type="static"></pc-rigid-body
55
55
  ></pc-entity>
56
56
  <pc-entity name="right-wall" position="9 1.5 0" scale="0.3 3 18"
57
57
  ><pc-render type="box" material="wall-material"></pc-render
58
58
  ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
59
- ><pc-rigidbody type="static"></pc-rigidbody
59
+ ><pc-rigid-body type="static"></pc-rigid-body
60
60
  ></pc-entity>
61
61
  <pc-entity name="blue-crate" position="-2 0.75 -3" scale="1.5 1.5 1.5"
62
62
  ><pc-render type="box" material="blue-material"></pc-render
63
63
  ><pc-collision type="box" half-extents="0.75 0.75 0.75"></pc-collision
64
- ><pc-rigidbody type="static"></pc-rigidbody
64
+ ><pc-rigid-body type="static"></pc-rigid-body
65
65
  ></pc-entity>
66
66
  <pc-entity name="green-crate" position="3 0.5 1" scale="2.5 1 1"
67
67
  ><pc-render type="box" material="green-material"></pc-render
68
68
  ><pc-collision type="box" half-extents="1.25 0.5 0.5"></pc-collision
69
- ><pc-rigidbody type="static"></pc-rigidbody
69
+ ><pc-rigid-body type="static"></pc-rigid-body
70
70
  ></pc-entity>
71
71
  <pc-entity name="cargo-left-0" position="-5.5 0.75 -5.5" scale="2 1.5 2"
72
72
  ><pc-render type="box" material="wood-material"></pc-render
73
73
  ><pc-collision type="box" half-extents="1 0.75 1"></pc-collision
74
- ><pc-rigidbody type="static"></pc-rigidbody
74
+ ><pc-rigid-body type="static"></pc-rigid-body
75
75
  ></pc-entity>
76
76
  <pc-entity name="cargo-left-1" position="-5.5 2 -5.5" scale="1.5 1 1.5"
77
77
  ><pc-render type="box" material="blue-material"></pc-render
78
78
  ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
79
- ><pc-rigidbody type="static"></pc-rigidbody
79
+ ><pc-rigid-body type="static"></pc-rigid-body
80
80
  ></pc-entity>
81
81
  <pc-entity name="cargo-right-0" position="5.3 0.6 -4.8" scale="2.4 1.2 2"
82
82
  ><pc-render type="box" material="green-material"></pc-render
83
83
  ><pc-collision type="box" half-extents="1.2 0.6 1"></pc-collision
84
- ><pc-rigidbody type="static"></pc-rigidbody
84
+ ><pc-rigid-body type="static"></pc-rigid-body
85
85
  ></pc-entity>
86
86
  <pc-entity name="cargo-right-1" position="5.3 1.7 -4.8" scale="1.5 1 1.5"
87
87
  ><pc-render type="box" material="wood-material"></pc-render
88
88
  ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
89
- ><pc-rigidbody type="static"></pc-rigidbody
89
+ ><pc-rigid-body type="static"></pc-rigid-body
90
90
  ></pc-entity>
91
91
  <pc-entity name="cargo-center" position="0 0.6 -6.5" scale="2.2 1.2 1.8"
92
92
  ><pc-render type="box" material="blue-material"></pc-render
93
93
  ><pc-collision type="box" half-extents="1.1 0.6 0.9"></pc-collision
94
- ><pc-rigidbody type="static"></pc-rigidbody
94
+ ><pc-rigid-body type="static"></pc-rigid-body
95
95
  ></pc-entity>
96
96
  <pc-entity name="shelf-left-post-0" position="-6.8 1.4 -3.5" scale="0.25 2.8 0.25"
97
97
  ><pc-render type="box" material="metal-material"></pc-render
98
98
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
99
- ><pc-rigidbody type="static"></pc-rigidbody
99
+ ><pc-rigid-body type="static"></pc-rigid-body
100
100
  ></pc-entity>
101
101
  <pc-entity name="shelf-left-post-1" position="-6.8 1.4 0" scale="0.25 2.8 0.25"
102
102
  ><pc-render type="box" material="metal-material"></pc-render
103
103
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
104
- ><pc-rigidbody type="static"></pc-rigidbody
104
+ ><pc-rigid-body type="static"></pc-rigid-body
105
105
  ></pc-entity>
106
106
  <pc-entity name="shelf-left-post-2" position="-6.8 1.4 3.5" scale="0.25 2.8 0.25"
107
107
  ><pc-render type="box" material="metal-material"></pc-render
108
108
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
109
- ><pc-rigidbody type="static"></pc-rigidbody
109
+ ><pc-rigid-body type="static"></pc-rigid-body
110
110
  ></pc-entity>
111
111
  <pc-entity name="shelf-right-post-0" position="6.8 1.4 -3.5" scale="0.25 2.8 0.25"
112
112
  ><pc-render type="box" material="metal-material"></pc-render
113
113
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
114
- ><pc-rigidbody type="static"></pc-rigidbody
114
+ ><pc-rigid-body type="static"></pc-rigid-body
115
115
  ></pc-entity>
116
116
  <pc-entity name="shelf-right-post-1" position="6.8 1.4 0" scale="0.25 2.8 0.25"
117
117
  ><pc-render type="box" material="metal-material"></pc-render
118
118
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
119
- ><pc-rigidbody type="static"></pc-rigidbody
119
+ ><pc-rigid-body type="static"></pc-rigid-body
120
120
  ></pc-entity>
121
121
  <pc-entity name="shelf-right-post-2" position="6.8 1.4 3.5" scale="0.25 2.8 0.25"
122
122
  ><pc-render type="box" material="metal-material"></pc-render
123
123
  ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
124
- ><pc-rigidbody type="static"></pc-rigidbody
124
+ ><pc-rigid-body type="static"></pc-rigid-body
125
125
  ></pc-entity>
126
126
  <pc-entity name="shelf-left-low" position="-6.8 0.65 0" scale="1.1 0.18 7.5"
127
127
  ><pc-render type="box" material="metal-material"></pc-render
128
128
  ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
129
- ><pc-rigidbody type="static"></pc-rigidbody
129
+ ><pc-rigid-body type="static"></pc-rigid-body
130
130
  ></pc-entity>
131
131
  <pc-entity name="shelf-left-high" position="-6.8 2.1 0" scale="1.1 0.18 7.5"
132
132
  ><pc-render type="box" material="metal-material"></pc-render
133
133
  ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
134
- ><pc-rigidbody type="static"></pc-rigidbody
134
+ ><pc-rigid-body type="static"></pc-rigid-body
135
135
  ></pc-entity>
136
136
  <pc-entity name="shelf-right-low" position="6.8 0.65 0" scale="1.1 0.18 7.5"
137
137
  ><pc-render type="box" material="metal-material"></pc-render
138
138
  ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
139
- ><pc-rigidbody type="static"></pc-rigidbody
139
+ ><pc-rigid-body type="static"></pc-rigid-body
140
140
  ></pc-entity>
141
141
  <pc-entity name="shelf-right-high" position="6.8 2.1 0" scale="1.1 0.18 7.5"
142
142
  ><pc-render type="box" material="metal-material"></pc-render
143
143
  ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
144
- ><pc-rigidbody type="static"></pc-rigidbody
144
+ ><pc-rigid-body type="static"></pc-rigid-body
145
145
  ></pc-entity>
146
146
  <pc-entity name="pallet" position="-2.5 0.15 2.5" scale="3 0.3 2"
147
147
  ><pc-render type="box" material="wood-material"></pc-render
148
148
  ><pc-collision type="box" half-extents="1.5 0.15 1"></pc-collision
149
- ><pc-rigidbody type="static"></pc-rigidbody
149
+ ><pc-rigid-body type="static"></pc-rigid-body
150
150
  ></pc-entity>
151
151
  <pc-entity name="player" position="0 1 5">
152
152
  <pc-collision type="capsule" radius="0.45" height="1.8"></pc-collision>
153
- <pc-rigidbody type="dynamic" mass="80" angular-factor="0 0 0"></pc-rigidbody>
153
+ <pc-rigid-body type="dynamic" mass="80" angular-factor="0 0 0"></pc-rigid-body>
154
154
  <pc-entity name="camera" position="0 0.65 0"
155
155
  ><pc-camera clear-color="#61a3db" fov="80"></pc-camera
156
156
  ></pc-entity>
@@ -6,7 +6,7 @@ import './starter.css';
6
6
 
7
7
  await Promise.all([
8
8
  whenReady('pc-entity[name="player"] > pc-collision'),
9
- whenReady('pc-entity[name="player"] > pc-rigidbody')
9
+ whenReady('pc-entity[name="player"] > pc-rigid-body')
10
10
  ]);
11
11
  const [player, camera] = await Promise.all([
12
12
  whenReady<EntityElement>('pc-entity[name="player"]'),
@@ -47,7 +47,7 @@ if (skyboxLayer) {
47
47
  }
48
48
 
49
49
  // Engine scripts are resolved by the bundler, so they are attached through the entity rather than
50
- // with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
50
+ // with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>
51
51
  const camera = cameraComponent.closestEntity;
52
52
  camera?.entity?.addComponent('script');
53
53
  camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 3 } });
@@ -14,7 +14,7 @@ const [cameraComponent, sky] = await Promise.all([
14
14
  ]);
15
15
 
16
16
  // Engine scripts are resolved by the bundler, so they are attached through the entity rather than
17
- // with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
17
+ // with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>
18
18
  const camera = cameraComponent.closestEntity;
19
19
  camera?.entity?.addComponent('script');
20
20
  camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 2.5 } });
@@ -8,12 +8,12 @@
8
8
  </head>
9
9
  <body>
10
10
  <pc-app>
11
- <pc-module
11
+ <pc-wasm
12
12
  name="Ammo"
13
13
  glue="/ammo/ammo.wasm.js"
14
14
  wasm="/ammo/ammo.wasm.wasm"
15
15
  fallback="/ammo/ammo.js"
16
- ></pc-module>
16
+ ></pc-wasm>
17
17
  <pc-material id="floor-material" diffuse="#2e333d" gloss="0.2"></pc-material>
18
18
  <pc-material id="cyan-material" diffuse="#29ade6" gloss="0.45"></pc-material>
19
19
  <pc-material id="coral-material" diffuse="#f25738" gloss="0.45"></pc-material>
@@ -34,7 +34,7 @@
34
34
  <pc-entity name="floor" position="0 -0.1 0" scale="10 0.2 10"
35
35
  ><pc-render type="box" material="floor-material"></pc-render
36
36
  ><pc-collision type="box" half-extents="5 0.1 5"></pc-collision
37
- ><pc-rigidbody type="static"></pc-rigidbody
37
+ ><pc-rigid-body type="static"></pc-rigid-body
38
38
  ></pc-entity>
39
39
  <pc-entity id="bodies"></pc-entity>
40
40
  </pc-scene>
@@ -18,7 +18,7 @@ const spawn = () => {
18
18
  const type = TYPES[i % TYPES.length];
19
19
  bodies.insertAdjacentHTML(
20
20
  'beforeend',
21
- `<pc-entity data-body position="${((i % 4) - 1.5) * 1.1} ${0.7 + Math.floor(i / 4) * 1.1} ${(Math.floor(i / 4) - 1) * 1.4}" rotation="${i * 13} ${i * 29} 0" scale="${SCALES[i % SCALES.length]}"><pc-render type="${type}" material="${MATERIALS[i % MATERIALS.length]}"></pc-render><pc-collision type="${type}"></pc-collision><pc-rigidbody type="dynamic" mass="1" restitution="0.35"></pc-rigidbody></pc-entity>`
21
+ `<pc-entity data-body position="${((i % 4) - 1.5) * 1.1} ${0.7 + Math.floor(i / 4) * 1.1} ${(Math.floor(i / 4) - 1) * 1.4}" rotation="${i * 13} ${i * 29} 0" scale="${SCALES[i % SCALES.length]}"><pc-render type="${type}" material="${MATERIALS[i % MATERIALS.length]}"></pc-render><pc-collision type="${type}"></pc-collision><pc-rigid-body type="dynamic" mass="1" restitution="0.35"></pc-rigid-body></pc-entity>`
22
22
  );
23
23
  };
24
24
  const reset = () => {
@@ -58,8 +58,10 @@ ground.addComponent('render', {
58
58
  receiveShadows: true
59
59
  });
60
60
 
61
+ // The element's entity is a host whose transform composes with the GLB's authored root rotation
62
+ // (a -90° X up-axis fix), so only the yaw is set here
61
63
  const entity = model.entity!;
62
- entity.setLocalEulerAngles(-90, -25, 0);
64
+ entity.setLocalEulerAngles(0, -25, 0);
63
65
  entity.root.syncHierarchy();
64
66
  const meshes = (entity.findComponents('render') as RenderComponent[]).flatMap((render) => render.meshInstances);
65
67
  const bounds = meshes[0].aabb.clone();
@@ -14,7 +14,7 @@ class Rotate extends Script {
14
14
  }
15
15
 
16
16
  // Engine scripts are resolved by the bundler, so they are attached through the entity rather than
17
- // with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
17
+ // with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>
18
18
  const cube = await whenReady<EntityElement>('pc-entity[name="cube"]');
19
19
 
20
20
  cube.entity?.addComponent('script');
@@ -9,7 +9,7 @@ import './style.css';
9
9
  const cameraComponent = await whenReady('pc-camera');
10
10
 
11
11
  // Engine scripts are resolved by the bundler, so they are attached through the entity rather than
12
- // with <pc-script name="...">, which only resolves scripts fetched at runtime by <pc-asset>
12
+ // with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>
13
13
  const camera = cameraComponent.closestEntity;
14
14
  camera?.entity?.addComponent('script');
15
15
  camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 2 } });
@@ -16,12 +16,12 @@
16
16
  <pc-material id="shirt-material" diffuse="#268bd2"></pc-material>
17
17
  <pc-material id="skin-material" diffuse="#c78759"></pc-material>
18
18
  <pc-material id="pants-material" diffuse="#2e4a85"></pc-material>
19
- <pc-module
19
+ <pc-wasm
20
20
  name="Ammo"
21
21
  glue="/ammo/ammo.wasm.js"
22
22
  wasm="/ammo/ammo.wasm.wasm"
23
23
  fallback="/ammo/ammo.js"
24
- ></pc-module>
24
+ ></pc-wasm>
25
25
  <pc-scene>
26
26
  <pc-entity name="camera" position="0 3 6"><pc-camera clear-color="#7ab8e6"></pc-camera></pc-entity>
27
27
  <pc-entity name="light" rotation="45 30 0"
@@ -36,32 +36,32 @@
36
36
  <pc-entity name="ground" position="0 -0.1 0" scale="20 0.2 20"
37
37
  ><pc-render type="box" material="ground-material"></pc-render
38
38
  ><pc-collision type="box" half-extents="10 0.1 10"></pc-collision
39
- ><pc-rigidbody type="static"></pc-rigidbody
39
+ ><pc-rigid-body type="static"></pc-rigid-body
40
40
  ></pc-entity>
41
41
  <pc-entity name="block-0" position="-4.5 0.5 -3.5" scale="2.4 1 2.4"
42
42
  ><pc-render type="box" material="block-material"></pc-render
43
43
  ><pc-collision type="box" half-extents="1.2 0.5 1.2"></pc-collision
44
- ><pc-rigidbody type="static"></pc-rigidbody
44
+ ><pc-rigid-body type="static"></pc-rigid-body
45
45
  ></pc-entity>
46
46
  <pc-entity name="block-1" position="4.2 0.5 -2.8" rotation="0 25 0" scale="2.4 1 2.4"
47
47
  ><pc-render type="box" material="block-material"></pc-render
48
48
  ><pc-collision type="box" half-extents="1.2 0.5 1.2"></pc-collision
49
- ><pc-rigidbody type="static"></pc-rigidbody
49
+ ><pc-rigid-body type="static"></pc-rigid-body
50
50
  ></pc-entity>
51
51
  <pc-entity name="block-2" position="-3.7 0.5 3.2" rotation="0 50 0" scale="2.4 1 2.4"
52
52
  ><pc-render type="box" material="block-material"></pc-render
53
53
  ><pc-collision type="box" half-extents="1.2 0.5 1.2"></pc-collision
54
- ><pc-rigidbody type="static"></pc-rigidbody
54
+ ><pc-rigid-body type="static"></pc-rigid-body
55
55
  ></pc-entity>
56
56
  <pc-entity name="block-3" position="3.8 0.5 3.6" rotation="0 75 0" scale="2.4 1 2.4"
57
57
  ><pc-render type="box" material="block-material"></pc-render
58
58
  ><pc-collision type="box" half-extents="1.2 0.5 1.2"></pc-collision
59
- ><pc-rigidbody type="static"></pc-rigidbody
59
+ ><pc-rigid-body type="static"></pc-rigid-body
60
60
  ></pc-entity>
61
61
  <pc-entity name="tree-0-trunk" position="-7 0.99 -6" scale="0.418 1.98 0.418"
62
62
  ><pc-render type="box" material="wood-material"></pc-render
63
63
  ><pc-collision type="box" half-extents="0.209 0.99 0.209"></pc-collision
64
- ><pc-rigidbody type="static"></pc-rigidbody
64
+ ><pc-rigid-body type="static"></pc-rigid-body
65
65
  ></pc-entity>
66
66
  <pc-entity name="tree-0-crown-0" position="-7 2.09 -6" scale="2.31 1.98 2.31"
67
67
  ><pc-render type="cone" material="leaves-material"></pc-render
@@ -75,7 +75,7 @@
75
75
  <pc-entity name="tree-1-trunk" position="6.5 1.125 -6.5" scale="0.475 2.25 0.475"
76
76
  ><pc-render type="box" material="wood-material"></pc-render
77
77
  ><pc-collision type="box" half-extents="0.2375 1.125 0.2375"></pc-collision
78
- ><pc-rigidbody type="static"></pc-rigidbody
78
+ ><pc-rigid-body type="static"></pc-rigid-body
79
79
  ></pc-entity>
80
80
  <pc-entity name="tree-1-crown-0" position="6.5 2.375 -6.5" scale="2.625 2.25 2.625"
81
81
  ><pc-render type="cone" material="leaves-material"></pc-render
@@ -89,7 +89,7 @@
89
89
  <pc-entity name="tree-2-trunk" position="-7.5 0.81 5" scale="0.342 1.62 0.342"
90
90
  ><pc-render type="box" material="wood-material"></pc-render
91
91
  ><pc-collision type="box" half-extents="0.171 0.81 0.171"></pc-collision
92
- ><pc-rigidbody type="static"></pc-rigidbody
92
+ ><pc-rigid-body type="static"></pc-rigid-body
93
93
  ></pc-entity>
94
94
  <pc-entity name="tree-2-crown-0" position="-7.5 1.71 5" scale="1.89 1.62 1.89"
95
95
  ><pc-render type="cone" material="leaves-material"></pc-render
@@ -103,7 +103,7 @@
103
103
  <pc-entity name="tree-3-trunk" position="7 1.035 5.5" scale="0.437 2.07 0.437"
104
104
  ><pc-render type="box" material="wood-material"></pc-render
105
105
  ><pc-collision type="box" half-extents="0.2185 1.035 0.2185"></pc-collision
106
- ><pc-rigidbody type="static"></pc-rigidbody
106
+ ><pc-rigid-body type="static"></pc-rigid-body
107
107
  ></pc-entity>
108
108
  <pc-entity name="tree-3-crown-0" position="7 2.185 5.5" scale="2.415 2.07 2.415"
109
109
  ><pc-render type="cone" material="leaves-material"></pc-render
@@ -117,7 +117,7 @@
117
117
  <pc-entity name="tree-4-trunk" position="-2.2 0.765 -8" scale="0.323 1.53 0.323"
118
118
  ><pc-render type="box" material="wood-material"></pc-render
119
119
  ><pc-collision type="box" half-extents="0.1615 0.765 0.1615"></pc-collision
120
- ><pc-rigidbody type="static"></pc-rigidbody
120
+ ><pc-rigid-body type="static"></pc-rigid-body
121
121
  ></pc-entity>
122
122
  <pc-entity name="tree-4-crown-0" position="-2.2 1.615 -8" scale="1.785 1.53 1.785"
123
123
  ><pc-render type="cone" material="leaves-material"></pc-render
@@ -131,16 +131,16 @@
131
131
  <pc-entity name="fallen-log" position="0 0.35 6" scale="3.8 0.7 0.7"
132
132
  ><pc-render type="box" material="wood-material"></pc-render
133
133
  ><pc-collision type="box" half-extents="1.9 0.35 0.35"></pc-collision
134
- ><pc-rigidbody type="static"></pc-rigidbody
134
+ ><pc-rigid-body type="static"></pc-rigid-body
135
135
  ></pc-entity>
136
136
  <pc-entity name="stump" position="-1.8 0.4 -2.2" scale="0.9 0.8 0.9"
137
137
  ><pc-render type="box" material="wood-material"></pc-render
138
138
  ><pc-collision type="box" half-extents="0.45 0.4 0.45"></pc-collision
139
- ><pc-rigidbody type="static"></pc-rigidbody
139
+ ><pc-rigid-body type="static"></pc-rigid-body
140
140
  ></pc-entity>
141
141
  <pc-entity name="player" position="0 1.1 0">
142
142
  <pc-collision type="capsule" radius="0.5" height="2.4" linear-offset="0 0.1 0"></pc-collision>
143
- <pc-rigidbody type="dynamic" mass="70" angular-factor="0 0 0"></pc-rigidbody>
143
+ <pc-rigid-body type="dynamic" mass="70" angular-factor="0 0 0"></pc-rigid-body>
144
144
  <pc-entity name="character" position="0 0.2 0">
145
145
  <pc-entity name="body" scale="0.56 0.88 0.38"
146
146
  ><pc-render type="box" material="shirt-material"></pc-render
@@ -6,7 +6,7 @@ import './starter.css';
6
6
 
7
7
  await Promise.all([
8
8
  whenReady('pc-entity[name="player"] > pc-collision'),
9
- whenReady('pc-entity[name="player"] > pc-rigidbody')
9
+ whenReady('pc-entity[name="player"] > pc-rigid-body')
10
10
  ]);
11
11
  const [player, camera, model] = await Promise.all([
12
12
  whenReady<EntityElement>('pc-entity[name="player"]'),