create-playcanvas 0.10.0 → 0.10.1
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.
- package/package.json +1 -1
- package/templates/_shared/third-person-controller/src/controller.ts +25 -3
- package/templates/engine/base/package.json +2 -2
- package/templates/engine/third-person-controller/src/main.ts +10 -5
- package/templates/react/base/package.json +3 -3
- package/templates/react/third-person-controller/src/App.tsx +5 -2
- package/templates/web-components/base/package.json +2 -2
- package/templates/web-components/third-person-controller/index.html +17 -2
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Entity, RigidBodyComponentSystem } from 'playcanvas';
|
|
2
|
-
import { Script } from 'playcanvas';
|
|
2
|
+
import { Script, Vec3 } from 'playcanvas';
|
|
3
3
|
import { ThirdPersonController } from 'playcanvas/scripts/esm/third-person-controller.mjs';
|
|
4
4
|
|
|
5
|
+
/** Ground probes under the player's box collider (half width 0.4): centre, edges and corners */
|
|
6
|
+
const FEET = [-0.38, 0, 0.38].flatMap((x) => [-0.38, 0, 0.38].map((z) => [x, z]));
|
|
7
|
+
|
|
5
8
|
class RobotAnimation extends Script {
|
|
6
9
|
static scriptName = 'robotAnimation';
|
|
7
10
|
|
|
@@ -28,9 +31,10 @@ class RobotAnimation extends Script {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export const addThirdPersonController = (player: Entity, camera: Entity, model: Entity) => {
|
|
31
|
-
|
|
34
|
+
const sys = player.rigidbody!.system as RigidBodyComponentSystem;
|
|
35
|
+
sys.gravity.set(0, -18, 0);
|
|
32
36
|
if (!player.script) player.addComponent('script');
|
|
33
|
-
player.script!.create(ThirdPersonController, {
|
|
37
|
+
const controller = player.script!.create(ThirdPersonController, {
|
|
34
38
|
properties: {
|
|
35
39
|
camera,
|
|
36
40
|
characterModel: model,
|
|
@@ -41,6 +45,24 @@ export const addThirdPersonController = (player: Entity, camera: Entity, model:
|
|
|
41
45
|
jumpForce: 520,
|
|
42
46
|
speedGround: 60
|
|
43
47
|
}
|
|
48
|
+
})!;
|
|
49
|
+
|
|
50
|
+
// The stock ground check is one ray from the centre, so a player standing on a ledge reads as
|
|
51
|
+
// airborne and can't jump. Count it grounded when any probe under the collider finds a solid
|
|
52
|
+
// surface; triggers (colliders without a rigid body) only stop the camera
|
|
53
|
+
const [from, to] = [new Vec3(), new Vec3()];
|
|
54
|
+
const solid = { filterCallback: (e: Entity) => !!e.rigidbody };
|
|
55
|
+
let grounded = false;
|
|
56
|
+
Object.defineProperty(controller, '_grounded', {
|
|
57
|
+
get: () => grounded,
|
|
58
|
+
set: () => {
|
|
59
|
+
const p = player.getPosition();
|
|
60
|
+
grounded = FEET.some(([x, z]) => {
|
|
61
|
+
from.set(p.x + x, p.y, p.z + z);
|
|
62
|
+
to.set(from.x, p.y - 1.1, from.z);
|
|
63
|
+
return !!sys.raycastFirst(from, to, solid);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
44
66
|
});
|
|
45
67
|
|
|
46
68
|
if (!model.script) model.addComponent('script');
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"playcanvas": "^2.23.
|
|
18
|
+
"playcanvas": "^2.23.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@playcanvas/eslint-config": "3.0.0-beta.8",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"eslint": "^9.39.5",
|
|
24
24
|
"prettier": "^3.9.9",
|
|
25
25
|
"typescript": "~6.0.3",
|
|
26
|
-
"vite": "^8.3.
|
|
26
|
+
"vite": "^8.3.4"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
29
|
"node": ">=22.23.2"
|
|
@@ -134,6 +134,9 @@ for (const [i, [x, z, size]] of TREES.entries()) {
|
|
|
134
134
|
crown.setPosition(x, size * y, z);
|
|
135
135
|
crown.setLocalScale(size * width, size * height, size * width);
|
|
136
136
|
crown.addComponent('render', { type: 'cone', material: j === 1 ? tips : leaves });
|
|
137
|
+
|
|
138
|
+
// A trigger: it stops the camera's line of sight but the player walks through it
|
|
139
|
+
crown.addComponent('collision', { type: 'cone', radius: (size * width) / 2, height: size * height });
|
|
137
140
|
app.root.addChild(crown);
|
|
138
141
|
}
|
|
139
142
|
}
|
|
@@ -142,11 +145,13 @@ prop('stump', [-1.8, 0.4, -2.2], [0.9, 0.8, 0.9], wood);
|
|
|
142
145
|
|
|
143
146
|
const player = new Entity('player');
|
|
144
147
|
player.setPosition(0, 1.1, 0);
|
|
148
|
+
|
|
149
|
+
// A box rather than a capsule, so the player stands on ledges instead of sliding off them. Its
|
|
150
|
+
// bottom sits 1 m below the body, inside the controller's 1.1 m ground probes
|
|
145
151
|
player.addComponent('collision', {
|
|
146
|
-
type: '
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
linearOffset: new Vec3(0, 0.1, 0)
|
|
152
|
+
type: 'box',
|
|
153
|
+
halfExtents: new Vec3(0.4, 1.2, 0.4),
|
|
154
|
+
linearOffset: new Vec3(0, 0.2, 0)
|
|
150
155
|
});
|
|
151
156
|
player.addComponent('rigidbody', { type: 'dynamic', mass: 70, angularFactor: Vec3.ZERO });
|
|
152
157
|
app.root.addChild(player);
|
|
@@ -162,7 +167,7 @@ pants.diffuse = new Color(0.18, 0.29, 0.52);
|
|
|
162
167
|
pants.update();
|
|
163
168
|
|
|
164
169
|
const model = new Entity('character');
|
|
165
|
-
model.setLocalPosition(0, 0.
|
|
170
|
+
model.setLocalPosition(0, 0.3, 0);
|
|
166
171
|
const part = (
|
|
167
172
|
parent: Entity,
|
|
168
173
|
name: string,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@playcanvas/react": "^0.11.7",
|
|
19
|
-
"playcanvas": "^2.23.
|
|
19
|
+
"playcanvas": "^2.23.1",
|
|
20
20
|
"react": "^19.3.0",
|
|
21
21
|
"react-dom": "^19.3.0"
|
|
22
22
|
},
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"@playcanvas/inspector": "^0.2.0",
|
|
26
26
|
"@types/react": "^19.3.0",
|
|
27
27
|
"@types/react-dom": "^19.3.0",
|
|
28
|
-
"@vitejs/plugin-react": "^6.1.
|
|
28
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
29
29
|
"eslint": "^9.39.5",
|
|
30
30
|
"prettier": "^3.9.9",
|
|
31
31
|
"typescript": "~6.0.3",
|
|
32
|
-
"vite": "^8.3.
|
|
32
|
+
"vite": "^8.3.4"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
35
35
|
"node": ">=22.23.2"
|
|
@@ -79,6 +79,8 @@ function Pine({
|
|
|
79
79
|
scale={[size * width, size * height, size * width]}
|
|
80
80
|
>
|
|
81
81
|
<Render type="cone" material={i === 1 ? tips : leaves} />
|
|
82
|
+
{/* A trigger: it stops the camera's line of sight but the player walks through it */}
|
|
83
|
+
<Collision type="cone" radius={(size * width) / 2} height={size * height} />
|
|
82
84
|
</Entity>
|
|
83
85
|
))}
|
|
84
86
|
</>
|
|
@@ -139,9 +141,10 @@ function Scene() {
|
|
|
139
141
|
<Block name="fallen-log" position={[0, 0.35, 6]} scale={[3.8, 0.7, 0.7]} material={wood} />
|
|
140
142
|
<Block name="stump" position={[-1.8, 0.4, -2.2]} scale={[0.9, 0.8, 0.9]} material={wood} />
|
|
141
143
|
<Entity name="player" ref={player} position={[0, 1.1, 0]}>
|
|
142
|
-
|
|
144
|
+
{/* A box rather than a capsule, so the player stands on ledges instead of sliding off them */}
|
|
145
|
+
<Collision type="box" halfExtents={[0.4, 1.2, 0.4]} linearOffset={[0, 0.2, 0]} />
|
|
143
146
|
<RigidBody type="dynamic" mass={70} angularFactor={[0, 0, 0]} />
|
|
144
|
-
<Entity name="character" ref={model} position={[0, 0.
|
|
147
|
+
<Entity name="character" ref={model} position={[0, 0.3, 0]}>
|
|
145
148
|
<Entity name="body" scale={[0.56, 0.88, 0.38]}>
|
|
146
149
|
<Render type="box" material={shirt} />
|
|
147
150
|
</Entity>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@playcanvas/web-components": "^0.28.0",
|
|
19
|
-
"playcanvas": "^2.23.
|
|
19
|
+
"playcanvas": "^2.23.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@playcanvas/eslint-config": "3.0.0-beta.8",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"eslint": "^9.39.5",
|
|
25
25
|
"prettier": "^3.9.9",
|
|
26
26
|
"typescript": "~6.0.3",
|
|
27
|
-
"vite": "^8.3.
|
|
27
|
+
"vite": "^8.3.4"
|
|
28
28
|
},
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=22.23.2"
|
|
@@ -65,12 +65,15 @@
|
|
|
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
|
|
68
|
+
><pc-collision type="cone" radius="1.155" height="1.98"></pc-collision
|
|
68
69
|
></pc-entity>
|
|
69
70
|
<pc-entity name="tree-0-crown-1" position="-7 2.915 -6" scale="1.76 1.705 1.76"
|
|
70
71
|
><pc-render type="cone" material="tips-material"></pc-render
|
|
72
|
+
><pc-collision type="cone" radius="0.88" height="1.705"></pc-collision
|
|
71
73
|
></pc-entity>
|
|
72
74
|
<pc-entity name="tree-0-crown-2" position="-7 3.63 -6" scale="1.21 1.54 1.21"
|
|
73
75
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
76
|
+
><pc-collision type="cone" radius="0.605" height="1.54"></pc-collision
|
|
74
77
|
></pc-entity>
|
|
75
78
|
<pc-entity name="tree-1-trunk" position="6.5 1.125 -6.5" scale="0.475 2.25 0.475"
|
|
76
79
|
><pc-render type="box" material="wood-material"></pc-render
|
|
@@ -79,12 +82,15 @@
|
|
|
79
82
|
></pc-entity>
|
|
80
83
|
<pc-entity name="tree-1-crown-0" position="6.5 2.375 -6.5" scale="2.625 2.25 2.625"
|
|
81
84
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
85
|
+
><pc-collision type="cone" radius="1.3125" height="2.25"></pc-collision
|
|
82
86
|
></pc-entity>
|
|
83
87
|
<pc-entity name="tree-1-crown-1" position="6.5 3.3125 -6.5" scale="2 1.9375 2"
|
|
84
88
|
><pc-render type="cone" material="tips-material"></pc-render
|
|
89
|
+
><pc-collision type="cone" radius="1" height="1.9375"></pc-collision
|
|
85
90
|
></pc-entity>
|
|
86
91
|
<pc-entity name="tree-1-crown-2" position="6.5 4.125 -6.5" scale="1.375 1.75 1.375"
|
|
87
92
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
93
|
+
><pc-collision type="cone" radius="0.6875" height="1.75"></pc-collision
|
|
88
94
|
></pc-entity>
|
|
89
95
|
<pc-entity name="tree-2-trunk" position="-7.5 0.81 5" scale="0.342 1.62 0.342"
|
|
90
96
|
><pc-render type="box" material="wood-material"></pc-render
|
|
@@ -93,12 +99,15 @@
|
|
|
93
99
|
></pc-entity>
|
|
94
100
|
<pc-entity name="tree-2-crown-0" position="-7.5 1.71 5" scale="1.89 1.62 1.89"
|
|
95
101
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
102
|
+
><pc-collision type="cone" radius="0.945" height="1.62"></pc-collision
|
|
96
103
|
></pc-entity>
|
|
97
104
|
<pc-entity name="tree-2-crown-1" position="-7.5 2.385 5" scale="1.44 1.395 1.44"
|
|
98
105
|
><pc-render type="cone" material="tips-material"></pc-render
|
|
106
|
+
><pc-collision type="cone" radius="0.72" height="1.395"></pc-collision
|
|
99
107
|
></pc-entity>
|
|
100
108
|
<pc-entity name="tree-2-crown-2" position="-7.5 2.97 5" scale="0.99 1.26 0.99"
|
|
101
109
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
110
|
+
><pc-collision type="cone" radius="0.495" height="1.26"></pc-collision
|
|
102
111
|
></pc-entity>
|
|
103
112
|
<pc-entity name="tree-3-trunk" position="7 1.035 5.5" scale="0.437 2.07 0.437"
|
|
104
113
|
><pc-render type="box" material="wood-material"></pc-render
|
|
@@ -107,12 +116,15 @@
|
|
|
107
116
|
></pc-entity>
|
|
108
117
|
<pc-entity name="tree-3-crown-0" position="7 2.185 5.5" scale="2.415 2.07 2.415"
|
|
109
118
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
119
|
+
><pc-collision type="cone" radius="1.2075" height="2.07"></pc-collision
|
|
110
120
|
></pc-entity>
|
|
111
121
|
<pc-entity name="tree-3-crown-1" position="7 3.0475 5.5" scale="1.84 1.7825 1.84"
|
|
112
122
|
><pc-render type="cone" material="tips-material"></pc-render
|
|
123
|
+
><pc-collision type="cone" radius="0.92" height="1.7825"></pc-collision
|
|
113
124
|
></pc-entity>
|
|
114
125
|
<pc-entity name="tree-3-crown-2" position="7 3.795 5.5" scale="1.265 1.61 1.265"
|
|
115
126
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
127
|
+
><pc-collision type="cone" radius="0.6325" height="1.61"></pc-collision
|
|
116
128
|
></pc-entity>
|
|
117
129
|
<pc-entity name="tree-4-trunk" position="-2.2 0.765 -8" scale="0.323 1.53 0.323"
|
|
118
130
|
><pc-render type="box" material="wood-material"></pc-render
|
|
@@ -121,12 +133,15 @@
|
|
|
121
133
|
></pc-entity>
|
|
122
134
|
<pc-entity name="tree-4-crown-0" position="-2.2 1.615 -8" scale="1.785 1.53 1.785"
|
|
123
135
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
136
|
+
><pc-collision type="cone" radius="0.8925" height="1.53"></pc-collision
|
|
124
137
|
></pc-entity>
|
|
125
138
|
<pc-entity name="tree-4-crown-1" position="-2.2 2.2525 -8" scale="1.36 1.3175 1.36"
|
|
126
139
|
><pc-render type="cone" material="tips-material"></pc-render
|
|
140
|
+
><pc-collision type="cone" radius="0.68" height="1.3175"></pc-collision
|
|
127
141
|
></pc-entity>
|
|
128
142
|
<pc-entity name="tree-4-crown-2" position="-2.2 2.805 -8" scale="0.935 1.19 0.935"
|
|
129
143
|
><pc-render type="cone" material="leaves-material"></pc-render
|
|
144
|
+
><pc-collision type="cone" radius="0.4675" height="1.19"></pc-collision
|
|
130
145
|
></pc-entity>
|
|
131
146
|
<pc-entity name="fallen-log" position="0 0.35 6" scale="3.8 0.7 0.7"
|
|
132
147
|
><pc-render type="box" material="wood-material"></pc-render
|
|
@@ -139,9 +154,9 @@
|
|
|
139
154
|
><pc-rigid-body type="static"></pc-rigid-body
|
|
140
155
|
></pc-entity>
|
|
141
156
|
<pc-entity name="player" position="0 1.1 0">
|
|
142
|
-
<pc-collision type="
|
|
157
|
+
<pc-collision type="box" half-extents="0.4 1.2 0.4" linear-offset="0 0.2 0"></pc-collision>
|
|
143
158
|
<pc-rigid-body type="dynamic" mass="70" angular-factor="0 0 0"></pc-rigid-body>
|
|
144
|
-
<pc-entity name="character" position="0 0.
|
|
159
|
+
<pc-entity name="character" position="0 0.3 0">
|
|
145
160
|
<pc-entity name="body" scale="0.56 0.88 0.38"
|
|
146
161
|
><pc-render type="box" material="shirt-material"></pc-render
|
|
147
162
|
></pc-entity>
|