dcl-npc-toolkit 1.0.10-20230523140244.commit-fbf44ee → 1.1.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.
- package/README.md +544 -813
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,74 +3,94 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
|
|
6
8
|
# NPC-library
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
A collection of tools for creating Non-Player-Characters (NPCs). These are capable of having conversations with the player, and play different animations.
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
|
|
16
20
|
|
|
17
21
|
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
Capabilities of the NPCs in this library:
|
|
19
25
|
|
|
20
26
|
|
|
21
27
|
|
|
22
28
|
|
|
23
29
|
|
|
30
|
+
|
|
31
|
+
|
|
24
32
|
- Start a conversation when clicked or when walking near
|
|
25
33
|
|
|
26
34
|
|
|
27
35
|
|
|
36
|
+
|
|
37
|
+
|
|
28
38
|
- Trigger any action when clicked or when walking near
|
|
29
39
|
|
|
30
40
|
|
|
31
41
|
|
|
42
|
+
|
|
43
|
+
|
|
32
44
|
- Trigger any action when the player walks away
|
|
33
45
|
|
|
34
46
|
|
|
35
47
|
|
|
48
|
+
|
|
49
|
+
|
|
36
50
|
- Turn around slowly to always face the player
|
|
37
51
|
|
|
38
52
|
|
|
39
53
|
|
|
54
|
+
|
|
55
|
+
|
|
40
56
|
- Play an animation in the NPC 3d model, optionally returning to loop the idle animation afterwards
|
|
41
57
|
|
|
42
58
|
|
|
43
59
|
|
|
44
60
|
|
|
45
61
|
|
|
62
|
+
|
|
63
|
+
|
|
46
64
|
The dialog messages can also require that the player chooses options, and any action can be triggered when the player picks an option or advances past a message.
|
|
47
65
|
|
|
48
66
|
|
|
49
67
|
|
|
50
68
|
|
|
51
69
|
|
|
70
|
+
|
|
71
|
+
|
|
52
72
|
To use NPCs in your scene:
|
|
53
73
|
|
|
54
74
|
|
|
55
75
|
|
|
56
76
|
|
|
57
77
|
|
|
78
|
+
|
|
79
|
+
|
|
58
80
|
1. Install the library as an npm bundle. Run this command in your scene's project folder:
|
|
59
81
|
|
|
60
82
|
|
|
61
83
|
|
|
62
84
|
|
|
63
85
|
|
|
64
|
-
```
|
|
65
|
-
|
|
66
86
|
|
|
67
87
|
|
|
88
|
+
```ts
|
|
68
89
|
npm i dcl-npc-toolkit -B
|
|
90
|
+
```
|
|
69
91
|
|
|
70
92
|
|
|
71
93
|
|
|
72
|
-
```
|
|
73
|
-
|
|
74
94
|
|
|
75
95
|
|
|
76
96
|
2. Install the dependent sdk utils library as an npm bundle. Run this command in your scene's project folder:
|
|
@@ -79,16 +99,14 @@ npm i dcl-npc-toolkit -B
|
|
|
79
99
|
|
|
80
100
|
|
|
81
101
|
|
|
82
|
-
```
|
|
83
|
-
|
|
84
102
|
|
|
85
103
|
|
|
104
|
+
```
|
|
86
105
|
npm i @dcl-sdk/utils -B
|
|
106
|
+
```
|
|
87
107
|
|
|
88
108
|
|
|
89
109
|
|
|
90
|
-
```
|
|
91
|
-
|
|
92
110
|
|
|
93
111
|
|
|
94
112
|
3. Run `dcl start` or `dcl build` so the dependencies are correctly installed.
|
|
@@ -97,22 +115,22 @@ npm i @dcl-sdk/utils -B
|
|
|
97
115
|
|
|
98
116
|
|
|
99
117
|
|
|
118
|
+
|
|
119
|
+
|
|
100
120
|
4. Import the library into the scene's script. Add this line at the start of your `game.ts` file, or any other TypeScript files that require it:
|
|
101
121
|
|
|
102
122
|
|
|
103
123
|
|
|
104
124
|
|
|
105
125
|
|
|
106
|
-
```ts
|
|
107
|
-
|
|
108
126
|
|
|
109
127
|
|
|
128
|
+
```ts
|
|
110
129
|
import * as npc from 'dcl-npc-toolkit'
|
|
130
|
+
```
|
|
111
131
|
|
|
112
132
|
|
|
113
133
|
|
|
114
|
-
```
|
|
115
|
-
|
|
116
134
|
|
|
117
135
|
|
|
118
136
|
|
|
@@ -123,44 +141,22 @@ import * as npc from 'dcl-npc-toolkit'
|
|
|
123
141
|
|
|
124
142
|
|
|
125
143
|
|
|
126
|
-
```ts
|
|
127
|
-
|
|
128
144
|
|
|
129
145
|
|
|
146
|
+
```ts
|
|
130
147
|
export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
134
149
|
//NPC Data Object
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
150
|
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
151
|
type: npc.NPCType.CUSTOM,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
152
|
model: 'models/npc.glb',
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
153
|
onActivate:()=>{console.log('npc activated');}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
155
|
)
|
|
156
|
+
```
|
|
159
157
|
|
|
160
158
|
|
|
161
159
|
|
|
162
|
-
```
|
|
163
|
-
|
|
164
160
|
|
|
165
161
|
|
|
166
162
|
|
|
@@ -171,80 +167,74 @@ onActivate:()=>{console.log('npc activated');}
|
|
|
171
167
|
|
|
172
168
|
|
|
173
169
|
|
|
174
|
-
```ts
|
|
175
|
-
|
|
176
170
|
|
|
177
171
|
|
|
172
|
+
```ts
|
|
178
173
|
import { Dialog } from 'dcl-npc-toolkit'
|
|
174
|
+
export let ILoveCats: Dialog[] = [
|
|
175
|
+
{
|
|
176
|
+
text: `I really lo-ove cats`,
|
|
177
|
+
isEndOfDialog: true
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
```
|
|
179
181
|
|
|
180
182
|
|
|
181
183
|
|
|
182
184
|
|
|
183
185
|
|
|
184
|
-
export let ILoveCats: Dialog[] = [
|
|
185
|
-
|
|
186
186
|
|
|
187
187
|
|
|
188
|
-
|
|
188
|
+
## NPC Default Behavior
|
|
189
189
|
|
|
190
190
|
|
|
191
191
|
|
|
192
|
-
text: `I really lo-ove cats`,
|
|
193
|
-
|
|
194
192
|
|
|
195
193
|
|
|
196
|
-
isEndOfDialog: true
|
|
197
|
-
|
|
198
194
|
|
|
199
195
|
|
|
200
|
-
|
|
196
|
+
NPCs at the very least must have:
|
|
201
197
|
|
|
202
198
|
|
|
203
199
|
|
|
204
|
-
|
|
200
|
+
|
|
205
201
|
|
|
206
202
|
|
|
207
203
|
|
|
208
|
-
|
|
204
|
+
- `position`: (_TransformType_) Must include position, rotation and scale.
|
|
209
205
|
|
|
210
206
|
|
|
211
207
|
|
|
212
208
|
|
|
213
209
|
|
|
214
|
-
|
|
210
|
+
- `NPCData`: (_Data Object_) with a minimum of two variables
|
|
215
211
|
|
|
216
212
|
|
|
217
213
|
|
|
218
214
|
|
|
219
215
|
|
|
220
|
-
|
|
216
|
+
- `type`: (_NPCType_) you have the choice to use a custom GLB object or an `AvatarShape` for your npc
|
|
221
217
|
|
|
222
218
|
|
|
223
219
|
|
|
224
220
|
|
|
225
221
|
|
|
226
|
-
- `
|
|
222
|
+
- `NPCType.CUSTOM`
|
|
227
223
|
|
|
228
224
|
|
|
229
225
|
|
|
230
|
-
- `NPCData`: (_Data Object_) with a minimum of two variables
|
|
231
|
-
|
|
232
226
|
|
|
233
227
|
|
|
234
|
-
- `
|
|
228
|
+
- `NPCType.AVATAR`
|
|
235
229
|
|
|
236
230
|
|
|
237
231
|
|
|
238
|
-
- `NPCType.CUSTOM`
|
|
239
|
-
|
|
240
232
|
|
|
241
233
|
|
|
242
|
-
- `
|
|
234
|
+
- `onActivate()`: (_()=> void_) A function to call when the NPC is activated.
|
|
243
235
|
|
|
244
236
|
|
|
245
237
|
|
|
246
|
-
- `onActivate()`: (_()=> void_) A function to call when the NPC is activated.
|
|
247
|
-
|
|
248
238
|
|
|
249
239
|
|
|
250
240
|
|
|
@@ -253,50 +243,30 @@ NPCs at the very least must have:
|
|
|
253
243
|
|
|
254
244
|
|
|
255
245
|
|
|
246
|
+
|
|
247
|
+
|
|
256
248
|
- `model`: (_string_) The path to a 3D model
|
|
257
249
|
|
|
258
250
|
|
|
259
251
|
|
|
260
252
|
|
|
261
253
|
|
|
262
|
-
```ts
|
|
263
|
-
|
|
264
254
|
|
|
265
255
|
|
|
256
|
+
```ts
|
|
266
257
|
export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
267
258
|
|
|
268
|
-
|
|
269
|
-
|
|
270
259
|
//NPC Data Object
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
260
|
{
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
261
|
type: npc.NPCType.CUSTOM,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
262
|
model: 'models/npc.glb',
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
263
|
onActivate:()=>{console.log('npc activated');}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
264
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
265
|
)
|
|
266
|
+
```
|
|
295
267
|
|
|
296
268
|
|
|
297
269
|
|
|
298
|
-
```
|
|
299
|
-
|
|
300
270
|
|
|
301
271
|
|
|
302
272
|
|
|
@@ -307,363 +277,412 @@ With this default configuration, the NPC behaves in the following way:
|
|
|
307
277
|
|
|
308
278
|
|
|
309
279
|
|
|
280
|
+
|
|
281
|
+
|
|
310
282
|
- The `onActivate()` function is called when pressing E on the NPC, and when the player walks near at a distance of 6 meters.
|
|
311
283
|
|
|
312
284
|
|
|
313
285
|
|
|
286
|
+
|
|
287
|
+
|
|
314
288
|
- Once activated, there's a cooldown period of 5 seconds, that prevents the NPC to be activated again.
|
|
315
289
|
|
|
316
290
|
|
|
317
291
|
|
|
292
|
+
|
|
293
|
+
|
|
318
294
|
- After walking away from the NPC, if its dialog window was open it will be closed, and if the NPC was rotating to follow the player it will stop.
|
|
319
295
|
|
|
320
296
|
|
|
321
297
|
|
|
298
|
+
|
|
299
|
+
|
|
322
300
|
- If the NPC already has an open dialog window, clicking on the NPC won't do anything, to prevent accidentally clicking on it while flipping through the conversation.
|
|
323
301
|
|
|
324
302
|
|
|
325
303
|
|
|
304
|
+
|
|
305
|
+
|
|
326
306
|
- If the NPC has an animation named 'Idle', it will play it in a loop. If other non-looping animations are played, it will return to looping the 'Idle' animation after the indicated duration.
|
|
327
307
|
|
|
328
308
|
|
|
329
309
|
|
|
330
310
|
|
|
331
311
|
|
|
312
|
+
|
|
313
|
+
|
|
332
314
|
Many of these behaviors can be overridden or tweaked with the exposed properties.
|
|
333
315
|
|
|
334
316
|
|
|
335
|
-
|
|
336
|
-
|
|
317
|
+
|
|
318
|
+
## SDK7 UI
|
|
319
|
+
|
|
320
|
+
With sdk7, there are new ways to implement similar features from sdk6, one of them being the way 2D UI objects get created. To add the NPC dialogs to your sdk7 2D UI:
|
|
321
|
+
|
|
322
|
+
- create a variable to hold *all* of your 2D UI objects
|
|
323
|
+
|
|
324
|
+
- import the NPC UI from the library and add the React object to your scene UI tree
|
|
325
|
+
|
|
326
|
+
- create a function to be called once to render all of your 2D UI objects
|
|
327
|
+
|
|
337
328
|
|
|
338
|
-
- create a variable to hold *all* of your 2D UI objects
|
|
339
|
-
- import the NPC UI from the library and add the React object to your scene UI tree
|
|
340
|
-
- create a function to be called once to render all of your 2D UI objects
|
|
341
329
|
|
|
342
330
|
```ts
|
|
343
331
|
import ReactEcs, { Label, ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
|
|
344
332
|
import { NpcUtilsUi } from 'dcl-npc-toolkit'
|
|
345
333
|
|
|
346
334
|
const SceneOwnedUi = () =>
|
|
335
|
+
|
|
347
336
|
<UiEntity>
|
|
348
|
-
<NpcUtilsUi
|
|
349
|
-
|
|
337
|
+
<NpcUtilsUi />
|
|
338
|
+
|
|
339
|
+
{ /* rest of user defined UI */ }
|
|
350
340
|
</UiEntity>
|
|
351
341
|
|
|
342
|
+
|
|
343
|
+
|
|
352
344
|
export function setupUi() {
|
|
353
345
|
ReactEcsRenderer.setUiRenderer(SceneOwnedUi)
|
|
354
346
|
}
|
|
347
|
+
|
|
355
348
|
```
|
|
356
349
|
|
|
357
350
|
|
|
358
351
|
|
|
352
|
+
|
|
353
|
+
|
|
359
354
|
## NPC Additional Properties
|
|
360
355
|
|
|
361
356
|
|
|
362
357
|
|
|
363
358
|
|
|
364
359
|
|
|
360
|
+
|
|
361
|
+
|
|
365
362
|
To configure other properties of an NPC, add a fourth argument as an `NPCData` object. This object can have the following optional properties:
|
|
366
363
|
|
|
367
364
|
|
|
368
365
|
|
|
369
366
|
|
|
370
367
|
|
|
368
|
+
|
|
369
|
+
|
|
371
370
|
- `idleAnim`: _(string)_ Name of the idle animation in the model. This animation is always looped. After playing a non-looping animation it returns to looping this one.
|
|
372
371
|
|
|
373
372
|
|
|
374
373
|
|
|
374
|
+
|
|
375
|
+
|
|
375
376
|
- `faceUser`: _(boolean)_ Set if the NPC rotates to face the user while active.
|
|
376
377
|
|
|
377
378
|
|
|
378
379
|
|
|
380
|
+
|
|
381
|
+
|
|
379
382
|
- `dialogSound`: _(string)_ Path to sound file to play once for every entry shown on the UI. If the dialog entry being shown has an `audio` field, the NPC will play the file referenced by the `audio` field instead.
|
|
380
383
|
|
|
381
384
|
|
|
382
385
|
|
|
386
|
+
|
|
387
|
+
|
|
383
388
|
- `coolDownDuration`: _(number)_ Change the cooldown period for activating the NPC again. The number is in seconds.
|
|
384
389
|
|
|
385
390
|
|
|
386
391
|
|
|
392
|
+
|
|
393
|
+
|
|
387
394
|
- `hoverText`: _(string)_ Set the UI hover feedback when pointing the cursor at the NPC. _TALK_ by default.
|
|
388
395
|
|
|
389
396
|
|
|
390
397
|
|
|
398
|
+
|
|
399
|
+
|
|
391
400
|
- `onlyClickTrigger`: _(boolean)_ If true, the NPC can't be activated by walking near. Just by clicking on it or calling its `activate()` function.
|
|
392
401
|
|
|
393
402
|
|
|
394
403
|
|
|
404
|
+
|
|
405
|
+
|
|
395
406
|
- `onlyETrigger`: _(boolean)_ If true, the NPC can't be activated by walking near. Just by pressing the E key on it or calling its `activate()` function.
|
|
396
407
|
|
|
397
408
|
|
|
398
409
|
|
|
410
|
+
|
|
411
|
+
|
|
399
412
|
- `onlyExternalTrigger`: _(boolean)_ If true, the NPC can't be activated by clicking, pressing E, or walking near. Just by calling its `activate()` function.
|
|
400
413
|
|
|
401
414
|
|
|
402
415
|
|
|
416
|
+
|
|
417
|
+
|
|
403
418
|
- `reactDistance`: _(number)_ Radius in meters for the player to activate the NPC or trigger the `onWalkAway()` function when leaving the radius.
|
|
404
419
|
|
|
405
420
|
|
|
406
421
|
|
|
422
|
+
|
|
423
|
+
|
|
407
424
|
- `continueOnWalkAway`: _(boolean)_ If true,when the player walks out of the `reactDistance` radius, the dialog window stays open and the NPC keeps turning to face the player (if applicable). It doesn't affect the triggering of the `onWalkAway()` function.
|
|
408
425
|
|
|
409
426
|
|
|
410
427
|
|
|
428
|
+
|
|
429
|
+
|
|
411
430
|
- `onWalkAway`: (_()=> void_) Function to call every time the player walks out of the `reactDistance` radius.
|
|
412
431
|
|
|
413
432
|
|
|
414
433
|
|
|
434
|
+
|
|
435
|
+
|
|
415
436
|
- `walkingAnim`: _(string)_ Name of the walking animation on the model. This animation is looped when calling the `followPath()` function.
|
|
416
437
|
|
|
417
438
|
|
|
418
439
|
|
|
440
|
+
|
|
441
|
+
|
|
419
442
|
- `walkingSpeed`: _(number)_ Speed of the NPC when walking. By default _2_.
|
|
420
443
|
|
|
421
444
|
|
|
422
445
|
|
|
446
|
+
|
|
447
|
+
|
|
423
448
|
- `path`: _(Vector3)_ Default path to walk. If a value is provided for this field on NPC initialization, the NPC will walk over this path in loop from the start.
|
|
424
449
|
|
|
450
|
+
|
|
451
|
+
|
|
425
452
|
- `bubbleHeight`: _(number)_ The height at which to display the speech bubble above the head of the NPC.
|
|
426
453
|
|
|
454
|
+
|
|
455
|
+
|
|
427
456
|
- `textBubble`: _(boolean)_ If true, NPC starts with a speech bubble object ready to be accessed from the start. Otherwise, they text bubble is only built on the first call to `talkBubble()` on the NPC.
|
|
428
457
|
|
|
429
458
|
|
|
430
459
|
|
|
460
|
+
|
|
461
|
+
|
|
431
462
|
- `noUI`: _(boolean)_ If true, no UI object is built for UI dialogs for this NPC. This may help optimize the scene if this feature is not used.
|
|
432
463
|
|
|
433
464
|
|
|
434
465
|
|
|
435
466
|
|
|
436
467
|
|
|
437
|
-
```ts
|
|
438
|
-
|
|
439
468
|
|
|
440
469
|
|
|
470
|
+
```ts
|
|
441
471
|
export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
472
|
+
//NPC Data Object
|
|
473
|
+
{
|
|
474
|
+
type: npc.NPCType.CUSTOM,
|
|
475
|
+
model: 'models/npc.glb',
|
|
476
|
+
onActivate: ()=>{console.log('npc activated');},
|
|
477
|
+
onWalkAway: ()=>{console.log('test on walk away function')},
|
|
478
|
+
faceUser: true,
|
|
479
|
+
reactDistance: 3,
|
|
480
|
+
idleAnim: 'idle1',
|
|
481
|
+
walkingAnim: 'walk1',
|
|
482
|
+
hoverText: 'Activate',
|
|
483
|
+
continueOnWalkAway: true,
|
|
484
|
+
onlyClickTrigger: false,
|
|
485
|
+
onlyExternalTrigger: false
|
|
486
|
+
}
|
|
487
|
+
)
|
|
488
|
+
```
|
|
442
489
|
|
|
443
490
|
|
|
444
491
|
|
|
445
|
-
|
|
492
|
+
|
|
446
493
|
|
|
447
494
|
|
|
448
495
|
|
|
449
|
-
|
|
496
|
+
## Get NPC Data
|
|
450
497
|
|
|
451
498
|
|
|
452
499
|
|
|
453
|
-
|
|
500
|
+
|
|
454
501
|
|
|
455
502
|
|
|
456
503
|
|
|
457
|
-
|
|
504
|
+
```ts
|
|
505
|
+
npc.getData(myNPC)
|
|
506
|
+
```
|
|
458
507
|
|
|
459
508
|
|
|
460
509
|
|
|
461
|
-
|
|
510
|
+
|
|
462
511
|
|
|
463
512
|
|
|
464
513
|
|
|
465
|
-
|
|
514
|
+
There are several properties you can check on an NPC to know what its current state is:
|
|
466
515
|
|
|
467
516
|
|
|
468
517
|
|
|
469
|
-
|
|
518
|
+
|
|
470
519
|
|
|
471
520
|
|
|
472
521
|
|
|
473
|
-
|
|
522
|
+
- `.state`: An enum value of type `NPCState`. Supported values are `NPCState.STANDING` (default), `NPCState.TALKING`, and `NPCState.FOLLOWPATH`. `TALKING` is applied when the dialog window is opened, and set back to `STANDING` when the window is closed. `FOLLOWPATH` is applied when the NPC starts walking, and set back to `STANDING` when the NPC finishes its path or is stopped.
|
|
474
523
|
|
|
475
524
|
|
|
476
525
|
|
|
477
|
-
idleAnim: 'idle1',
|
|
478
|
-
|
|
479
526
|
|
|
480
527
|
|
|
481
|
-
|
|
528
|
+
- `.introduced`: Boolean, false by default. Set to true if the NPC has spoken to the player at least once in this session.
|
|
482
529
|
|
|
483
530
|
|
|
484
531
|
|
|
485
|
-
hoverText: 'Activate',
|
|
486
|
-
|
|
487
532
|
|
|
488
533
|
|
|
489
|
-
|
|
534
|
+
- `.visible`: Returns a Boolean, false by default. True if the dialog window for this NPC is currently open.
|
|
490
535
|
|
|
491
536
|
|
|
492
537
|
|
|
493
|
-
onlyClickTrigger: false,
|
|
494
|
-
|
|
495
538
|
|
|
496
539
|
|
|
497
|
-
|
|
540
|
+
- `.inCooldown`: Boolean, false by default. True if the NPC was recently activated and it's now in cooldown. The NPC won't respond to being activated till `inCooldown` is false.
|
|
498
541
|
|
|
499
542
|
|
|
500
543
|
|
|
501
|
-
|
|
544
|
+
|
|
502
545
|
|
|
503
546
|
|
|
504
547
|
|
|
505
|
-
|
|
548
|
+
> TIP: If you want to force an activation of the NPC in spite of the `inCooldown` value, you can force this value to true before activating.
|
|
506
549
|
|
|
507
550
|
|
|
508
551
|
|
|
509
|
-
```
|
|
510
|
-
|
|
511
552
|
|
|
512
553
|
|
|
513
554
|
|
|
514
555
|
|
|
515
|
-
##
|
|
556
|
+
## NPC Callable Actions
|
|
516
557
|
|
|
517
558
|
|
|
518
559
|
|
|
519
560
|
|
|
520
561
|
|
|
521
|
-
```ts
|
|
522
|
-
|
|
523
562
|
|
|
524
563
|
|
|
525
|
-
|
|
564
|
+
An NPC object has several callable functions that come with the class:
|
|
526
565
|
|
|
527
566
|
|
|
528
567
|
|
|
529
|
-
```
|
|
530
|
-
|
|
531
568
|
|
|
532
569
|
|
|
533
570
|
|
|
534
571
|
|
|
535
|
-
|
|
572
|
+
### Talk
|
|
536
573
|
|
|
537
574
|
|
|
538
575
|
|
|
539
576
|
|
|
540
577
|
|
|
541
|
-
- `.state`: An enum value of type `NPCState`. Supported values are `NPCState.STANDING` (default), `NPCState.TALKING`, and `NPCState.FOLLOWPATH`. `TALKING` is applied when the dialog window is opened, and set back to `STANDING` when the window is closed. `FOLLOWPATH` is applied when the NPC starts walking, and set back to `STANDING` when the NPC finishes its path or is stopped.
|
|
542
|
-
|
|
543
578
|
|
|
544
579
|
|
|
545
|
-
|
|
580
|
+
To start a conversation with the NPC using the dialog UI, call the `talk()` function. The function takes the following **required** parameter:
|
|
546
581
|
|
|
547
582
|
|
|
548
583
|
|
|
549
|
-
|
|
584
|
+
|
|
550
585
|
|
|
551
586
|
|
|
552
587
|
|
|
553
|
-
-
|
|
588
|
+
- `script`: _(Dialog[])_ This array contains the information to manage the conversation, including events that may be triggered, options to choose, etc.
|
|
554
589
|
|
|
555
590
|
|
|
556
591
|
|
|
557
592
|
|
|
558
593
|
|
|
559
|
-
> TIP: If you want to force an activation of the NPC in spite of the `inCooldown` value, you can force this value to true before activating.
|
|
560
|
-
|
|
561
594
|
|
|
562
595
|
|
|
563
|
-
|
|
596
|
+
It can also take the following optional parameters:
|
|
564
597
|
|
|
565
|
-
|
|
598
|
+
|
|
566
599
|
|
|
567
600
|
|
|
568
601
|
|
|
569
602
|
|
|
570
603
|
|
|
571
|
-
|
|
604
|
+
- `startIndex`: _(number | string)_ The _Dialog_ object from the `script` array to open first. By default this is _0_, the first element of the array. Pass a number to open the entry on a given array position, or pass a string to open the entry with a `name` property matching that string.
|
|
572
605
|
|
|
573
606
|
|
|
574
607
|
|
|
575
608
|
|
|
576
609
|
|
|
577
|
-
|
|
610
|
+
- `duration`: _(number)_ Number of seconds to wait before closing the dialog window. If no value is set, the window is kept open till the player reaches the end of the conversation or something else closes it.
|
|
578
611
|
|
|
579
612
|
|
|
580
613
|
|
|
581
614
|
|
|
582
615
|
|
|
583
|
-
To start a conversation with the NPC using the dialog UI, call the `talk()` function. The function takes the following **required** parameter:
|
|
584
|
-
|
|
585
616
|
|
|
586
617
|
|
|
587
|
-
|
|
618
|
+
```ts
|
|
619
|
+
npc.talk(myNPC,myScript, 0)
|
|
620
|
+
```
|
|
588
621
|
|
|
589
|
-
|
|
622
|
+
|
|
590
623
|
|
|
591
624
|
|
|
592
625
|
|
|
593
626
|
|
|
594
627
|
|
|
595
|
-
|
|
628
|
+
Learn how to build a script object for NPCs in a section below.
|
|
596
629
|
|
|
597
630
|
|
|
598
631
|
|
|
599
632
|
|
|
600
633
|
|
|
601
|
-
- `startIndex`: _(number | string)_ The _Dialog_ object from the `script` array to open first. By default this is _0_, the first element of the array. Pass a number to open the entry on a given array position, or pass a string to open the entry with a `name` property matching that string.
|
|
602
|
-
|
|
603
634
|
|
|
604
635
|
|
|
605
|
-
|
|
636
|
+
### Play Animations
|
|
606
637
|
|
|
607
638
|
|
|
608
639
|
|
|
609
640
|
|
|
610
641
|
|
|
611
|
-
```ts
|
|
612
|
-
|
|
613
642
|
|
|
614
643
|
|
|
615
|
-
|
|
644
|
+
By default, the NPC will loop an animation named 'Idle', or with a name passed in the `idleAnim` parameter.
|
|
616
645
|
|
|
617
646
|
|
|
618
647
|
|
|
619
|
-
```
|
|
620
|
-
|
|
621
648
|
|
|
622
649
|
|
|
623
650
|
|
|
624
651
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
652
|
+
Make the NPC play another animation by calling the `playAnimation()` function. The function takes the following **required** parameter:
|
|
628
653
|
|
|
629
654
|
|
|
630
655
|
|
|
631
|
-
### Play Animations
|
|
632
|
-
|
|
633
656
|
|
|
634
657
|
|
|
635
658
|
|
|
636
659
|
|
|
637
|
-
|
|
660
|
+
- `animationName`: _(string)_ The name of the animation to play.
|
|
638
661
|
|
|
639
662
|
|
|
640
663
|
|
|
641
664
|
|
|
642
665
|
|
|
643
|
-
Make the NPC play another animation by calling the `playAnimation()` function. The function takes the following **required** parameter:
|
|
644
|
-
|
|
645
666
|
|
|
646
667
|
|
|
647
|
-
|
|
668
|
+
It can also take the following optional parameters:
|
|
648
669
|
|
|
649
|
-
|
|
670
|
+
|
|
650
671
|
|
|
651
672
|
|
|
652
673
|
|
|
653
674
|
|
|
654
675
|
|
|
655
|
-
|
|
676
|
+
- `noLoop`: _(boolean)_ If true, plays the animation just once. Otherwise, the animation is looped.
|
|
656
677
|
|
|
657
678
|
|
|
658
679
|
|
|
659
680
|
|
|
660
681
|
|
|
661
|
-
- `
|
|
682
|
+
- `duration`: _(number)_ Specifies the duration in seconds of the animation. When finished, it returns to playing the idle animation.
|
|
662
683
|
|
|
663
684
|
|
|
664
685
|
|
|
665
|
-
- `duration`: _(number)_ Specifies the duration in seconds of the animation. When finished, it returns to playing the idle animation.
|
|
666
|
-
|
|
667
686
|
|
|
668
687
|
|
|
669
688
|
|
|
@@ -674,16 +693,14 @@ It can also take the following optional parameters:
|
|
|
674
693
|
|
|
675
694
|
|
|
676
695
|
|
|
677
|
-
```ts
|
|
678
|
-
|
|
679
696
|
|
|
680
697
|
|
|
698
|
+
```ts
|
|
681
699
|
npc.playAnimation(myNPC, `Head_Yes`, true, 2.63)
|
|
700
|
+
```
|
|
682
701
|
|
|
683
702
|
|
|
684
703
|
|
|
685
|
-
```
|
|
686
|
-
|
|
687
704
|
|
|
688
705
|
|
|
689
706
|
|
|
@@ -694,44 +711,52 @@ npc.playAnimation(myNPC, `Head_Yes`, true, 2.63)
|
|
|
694
711
|
|
|
695
712
|
|
|
696
713
|
|
|
714
|
+
|
|
715
|
+
|
|
697
716
|
The NPC's idle animation is looped by default whenever the NPC is not playing any other animations. In some cases you may want to have different idle animations depending on the circumstances, like while in a conversation, or if the NPC changes its general attitude after some event.
|
|
698
717
|
|
|
699
718
|
|
|
700
719
|
|
|
701
720
|
|
|
702
721
|
|
|
722
|
+
|
|
723
|
+
|
|
703
724
|
You set the NPC's idle animation when creating the NPC, using the `idleAnim` field. To change this animation at some later time, use `changeIdleAnim()`.
|
|
704
725
|
|
|
705
726
|
|
|
706
727
|
|
|
707
728
|
|
|
708
729
|
|
|
730
|
+
|
|
731
|
+
|
|
709
732
|
The `changeIdleAnim()` function takes two arguments:
|
|
710
733
|
|
|
711
734
|
|
|
712
735
|
|
|
713
736
|
|
|
714
737
|
|
|
738
|
+
|
|
739
|
+
|
|
715
740
|
- `animation`: The name of the new animation to set as the idle animation
|
|
716
741
|
|
|
717
742
|
|
|
718
743
|
|
|
744
|
+
|
|
745
|
+
|
|
719
746
|
- `play`: Optionally pass this value as _true_ if you want this new animation to start playing right away.
|
|
720
747
|
|
|
721
748
|
|
|
722
749
|
|
|
723
750
|
|
|
724
751
|
|
|
725
|
-
```ts
|
|
726
|
-
|
|
727
752
|
|
|
728
753
|
|
|
754
|
+
```ts
|
|
729
755
|
npc.changeIdleAnim(myNPC,`AngryIdle`, true)
|
|
756
|
+
```
|
|
730
757
|
|
|
731
758
|
|
|
732
759
|
|
|
733
|
-
```
|
|
734
|
-
|
|
735
760
|
|
|
736
761
|
|
|
737
762
|
|
|
@@ -742,22 +767,22 @@ npc.changeIdleAnim(myNPC,`AngryIdle`, true)
|
|
|
742
767
|
|
|
743
768
|
|
|
744
769
|
|
|
770
|
+
|
|
771
|
+
|
|
745
772
|
The `activate()` function can be used to trigger the `onActivate()` function, as an alternative to pressing E or walking near.
|
|
746
773
|
|
|
747
774
|
|
|
748
775
|
|
|
749
776
|
|
|
750
777
|
|
|
751
|
-
```ts
|
|
752
|
-
|
|
753
778
|
|
|
754
779
|
|
|
780
|
+
```ts
|
|
755
781
|
npc.activate(myNPC)
|
|
782
|
+
```
|
|
756
783
|
|
|
757
784
|
|
|
758
785
|
|
|
759
|
-
```
|
|
760
|
-
|
|
761
786
|
|
|
762
787
|
|
|
763
788
|
|
|
@@ -768,28 +793,30 @@ The `activate()` function is callable even when in cool down period, and it does
|
|
|
768
793
|
|
|
769
794
|
|
|
770
795
|
|
|
796
|
+
|
|
797
|
+
|
|
771
798
|
### Stop Walking
|
|
772
799
|
|
|
773
800
|
|
|
774
801
|
|
|
775
802
|
|
|
776
803
|
|
|
804
|
+
|
|
805
|
+
|
|
777
806
|
If the NPC is currently walking, call `stopWalking()` to stop it moving and return to playing its idle animation.
|
|
778
807
|
|
|
779
808
|
|
|
780
809
|
|
|
781
810
|
|
|
782
811
|
|
|
783
|
-
```ts
|
|
784
|
-
|
|
785
812
|
|
|
786
813
|
|
|
814
|
+
```ts
|
|
787
815
|
npc.stopWalking(myNPC)
|
|
816
|
+
```
|
|
788
817
|
|
|
789
818
|
|
|
790
819
|
|
|
791
|
-
```
|
|
792
|
-
|
|
793
820
|
|
|
794
821
|
|
|
795
822
|
|
|
@@ -800,52 +827,62 @@ npc.stopWalking(myNPC)
|
|
|
800
827
|
|
|
801
828
|
|
|
802
829
|
|
|
830
|
+
|
|
831
|
+
|
|
803
832
|
- `duration`: Seconds to wait before starting to walk again. If not provided, the NPC will stop walking indefinitely.
|
|
804
833
|
|
|
805
834
|
|
|
806
835
|
|
|
807
836
|
|
|
808
837
|
|
|
838
|
+
|
|
839
|
+
|
|
809
840
|
> Note: If the NPC is has its dialog window open when the timer for the `duration` ends, the NPC will not return to walking.
|
|
810
841
|
|
|
811
842
|
|
|
812
843
|
|
|
813
844
|
|
|
814
845
|
|
|
846
|
+
|
|
847
|
+
|
|
815
848
|
To make the NPC play a different animation from idle when paused, call `playAnimation()` after `stopWalking()`.
|
|
816
849
|
|
|
817
850
|
|
|
818
851
|
|
|
819
852
|
|
|
820
853
|
|
|
854
|
+
|
|
855
|
+
|
|
821
856
|
### Follow Path
|
|
822
857
|
|
|
823
858
|
|
|
824
859
|
|
|
825
860
|
|
|
826
861
|
|
|
862
|
+
|
|
863
|
+
|
|
827
864
|
Make an NPC walk following a path of `Vector3` points by calling `followPath()`. While walking, the NPC will play the `walkingAnim` if one was set when defining the NPC. The path can be taken once or on a loop.
|
|
828
865
|
|
|
829
866
|
|
|
830
867
|
|
|
831
868
|
|
|
832
869
|
|
|
870
|
+
|
|
871
|
+
|
|
833
872
|
`followPath()` can be called with no parameters if a `path` was already provided in the NPC's initialization or in a previous calling of `followPath()`. If the NPC was previously in the middle of walking a path and was interrupted, calling `followPath()` again with no arguments will return the NPC to that path.
|
|
834
873
|
|
|
835
874
|
|
|
836
875
|
|
|
837
876
|
|
|
838
877
|
|
|
839
|
-
```ts
|
|
840
|
-
|
|
841
878
|
|
|
842
879
|
|
|
880
|
+
```ts
|
|
843
881
|
npc.followPath(myNPC)
|
|
882
|
+
```
|
|
844
883
|
|
|
845
884
|
|
|
846
885
|
|
|
847
|
-
```
|
|
848
|
-
|
|
849
886
|
|
|
850
887
|
|
|
851
888
|
|
|
@@ -856,188 +893,147 @@ npc.followPath(myNPC)
|
|
|
856
893
|
|
|
857
894
|
|
|
858
895
|
|
|
859
|
-
`followPath()` has a single optional parameter of type `FollowPathData`. This object may have the following optional fields:
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
896
|
|
|
864
897
|
|
|
865
|
-
|
|
898
|
+
`followPath()` has a single optional parameter of type `FollowPathData`. This object may have the following optional fields:
|
|
866
899
|
|
|
867
900
|
|
|
868
901
|
|
|
869
|
-
- speed: Speed to move at while walking this path. If no `speed` or `totalDuration` is provided, it uses the NPC's `walkingSpeed`, which is _2_ by default.
|
|
870
|
-
|
|
871
902
|
|
|
872
903
|
|
|
873
|
-
- totalDuration: The duration in _seconds_ that the whole path should take. The NPC will move at the constant speed required to finish in that time. This value overrides that of the _speed_.
|
|
874
|
-
|
|
875
904
|
|
|
876
905
|
|
|
877
|
-
-
|
|
906
|
+
- path: Array of `Vector3` positions to walk over.
|
|
878
907
|
|
|
879
908
|
|
|
880
909
|
|
|
881
|
-
- curve: _boolean_ If true, the path is traced a single smooth curve that passes over each of the indicated points. The curve is made out of straight-line segments, the path is stored with 4 times as many points as originally defined. _false_ by default.
|
|
882
|
-
|
|
883
910
|
|
|
884
911
|
|
|
885
|
-
-
|
|
912
|
+
- speed: Speed to move at while walking this path. If no `speed` or `totalDuration` is provided, it uses the NPC's `walkingSpeed`, which is _2_ by default.
|
|
886
913
|
|
|
887
914
|
|
|
888
915
|
|
|
889
|
-
- onFinishCallback: Function to call when the NPC finished walking over all the points on the path. This is only called when `loop` is _false_.
|
|
890
|
-
|
|
891
916
|
|
|
892
917
|
|
|
893
|
-
-
|
|
894
|
-
|
|
895
|
-
|
|
918
|
+
- totalDuration: The duration in _seconds_ that the whole path should take. The NPC will move at the constant speed required to finish in that time. This value overrides that of the _speed_.
|
|
896
919
|
|
|
897
920
|
|
|
898
921
|
|
|
899
|
-
```ts
|
|
900
|
-
|
|
901
922
|
|
|
902
923
|
|
|
903
|
-
|
|
924
|
+
- loop: _boolean_ If true, the NPC walks in circles over the provided set of points in the path. _false_ by default, unless the NPC is initiated with a `path`, in which case it starts as _true_.
|
|
904
925
|
|
|
905
926
|
|
|
906
927
|
|
|
907
|
-
//NPC Data Object
|
|
908
|
-
|
|
909
928
|
|
|
910
929
|
|
|
911
|
-
|
|
930
|
+
- curve: _boolean_ If true, the path is traced a single smooth curve that passes over each of the indicated points. The curve is made out of straight-line segments, the path is stored with 4 times as many points as originally defined. _false_ by default.
|
|
912
931
|
|
|
913
932
|
|
|
914
933
|
|
|
915
|
-
type: npc.NPCType.CUSTOM,
|
|
916
|
-
|
|
917
934
|
|
|
918
935
|
|
|
919
|
-
|
|
936
|
+
- startingPoint: Index position for what point to start from on the path. _0_ by default.
|
|
920
937
|
|
|
921
938
|
|
|
922
939
|
|
|
923
|
-
onActivate: ()=>{console.log('npc activated');},
|
|
924
|
-
|
|
925
940
|
|
|
926
941
|
|
|
927
|
-
|
|
942
|
+
- onFinishCallback: Function to call when the NPC finished walking over all the points on the path. This is only called when `loop` is _false_.
|
|
928
943
|
|
|
929
944
|
|
|
930
945
|
|
|
931
|
-
faceUser: true,
|
|
932
|
-
|
|
933
946
|
|
|
934
947
|
|
|
935
|
-
|
|
948
|
+
- onReachedPointCallback: Function to call once every time the NPC reaches a point in the path.
|
|
936
949
|
|
|
937
950
|
|
|
938
951
|
|
|
939
|
-
idleAnim: 'idle1',
|
|
940
|
-
|
|
941
952
|
|
|
942
953
|
|
|
943
|
-
walkingAnim: 'walk1',
|
|
944
|
-
|
|
945
954
|
|
|
946
955
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
956
|
+
```ts
|
|
957
|
+
export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
950
958
|
|
|
959
|
+
//NPC Data Object
|
|
960
|
+
{
|
|
961
|
+
type: npc.NPCType.CUSTOM,
|
|
962
|
+
model: 'models/npc.glb',
|
|
963
|
+
onActivate: ()=>{console.log('npc activated');},
|
|
964
|
+
onWalkAway: ()=>{console.log('test on walk away function')},
|
|
965
|
+
faceUser: true,
|
|
966
|
+
reactDistance: 3,
|
|
967
|
+
idleAnim: 'idle1',
|
|
968
|
+
walkingAnim: 'walk1',
|
|
969
|
+
hoverText: "Activate"
|
|
951
970
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
971
|
)
|
|
956
972
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
973
|
npc.followPath(myNPC,
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
974
|
{
|
|
975
|
+
path:path,
|
|
976
|
+
loop:true,
|
|
977
|
+
pathType: npc.NPCPathType.RIGID_PATH,
|
|
978
|
+
onFinishCallback:()=>{console.log('path is done')},
|
|
979
|
+
onReachedPointCallback:()=>{console.log('ending oint')},
|
|
980
|
+
totalDuration: 20
|
|
981
|
+
}
|
|
982
|
+
)
|
|
983
|
+
```
|
|
966
984
|
|
|
967
985
|
|
|
968
986
|
|
|
969
|
-
path:path,
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
loop:true,
|
|
974
|
-
|
|
975
987
|
|
|
976
988
|
|
|
977
|
-
pathType: npc.NPCPathType.RIGID_PATH,
|
|
978
|
-
|
|
979
989
|
|
|
980
990
|
|
|
981
|
-
|
|
991
|
+
#### NPC Walking Speed
|
|
982
992
|
|
|
983
993
|
|
|
984
994
|
|
|
985
|
-
onReachedPointCallback:()=>{console.log('ending oint')},
|
|
986
|
-
|
|
987
995
|
|
|
988
996
|
|
|
989
|
-
totalDuration: 20
|
|
990
|
-
|
|
991
997
|
|
|
992
998
|
|
|
993
|
-
|
|
999
|
+
The following list of factors are used to determine speed in hierarchical order:
|
|
994
1000
|
|
|
995
1001
|
|
|
996
1002
|
|
|
997
|
-
)
|
|
998
|
-
|
|
999
1003
|
|
|
1000
1004
|
|
|
1001
1005
|
|
|
1002
1006
|
|
|
1003
|
-
|
|
1007
|
+
- `totalDuration` parameter set when calling `followPath()` is used over the total distance travelled over the path.
|
|
1004
1008
|
|
|
1005
1009
|
|
|
1006
1010
|
|
|
1007
1011
|
|
|
1008
1012
|
|
|
1009
|
-
|
|
1013
|
+
- `speed` parameter set when calling `followPath()`
|
|
1010
1014
|
|
|
1011
1015
|
|
|
1012
1016
|
|
|
1013
1017
|
|
|
1014
1018
|
|
|
1015
|
-
|
|
1019
|
+
- `walkingSpeed` parameter set when initializing NPC
|
|
1016
1020
|
|
|
1017
1021
|
|
|
1018
1022
|
|
|
1019
1023
|
|
|
1020
1024
|
|
|
1021
|
-
-
|
|
1025
|
+
- Default value _2_.
|
|
1022
1026
|
|
|
1023
1027
|
|
|
1024
1028
|
|
|
1025
|
-
- `speed` parameter set when calling `followPath()`
|
|
1026
|
-
|
|
1027
1029
|
|
|
1028
1030
|
|
|
1029
|
-
- `walkingSpeed` parameter set when initializing NPC
|
|
1030
|
-
|
|
1031
1031
|
|
|
1032
1032
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1033
|
+
#### Joining the path
|
|
1036
1034
|
|
|
1037
1035
|
|
|
1038
1036
|
|
|
1039
|
-
#### Joining the path
|
|
1040
|
-
|
|
1041
1037
|
|
|
1042
1038
|
|
|
1043
1039
|
|
|
@@ -1048,898 +1044,588 @@ If the NPC's current position when calling `followPath()` doesn't match the firs
|
|
|
1048
1044
|
|
|
1049
1045
|
|
|
1050
1046
|
|
|
1047
|
+
|
|
1048
|
+
|
|
1051
1049
|
The `path` can be a single point, and the NPC will then walk a from its current position to that point.
|
|
1052
1050
|
|
|
1053
1051
|
|
|
1054
1052
|
|
|
1055
1053
|
|
|
1056
1054
|
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
1057
|
> Note: If the speed of the NPC is determined by a `totalDuration` value, the segment that the NPC walks to join into the path is counted as part of the full path. If this segment is long, it will increase the NPC walking speed so that the full path lasts as what's indicated by the `totalDuration`.
|
|
1058
1058
|
|
|
1059
1059
|
|
|
1060
1060
|
|
|
1061
1061
|
|
|
1062
1062
|
|
|
1063
|
+
|
|
1064
|
+
|
|
1063
1065
|
In this example the NPC is far away from the start of the path. It will first walk from _10, 0, 10_ to _2, 0, 2_ and then continue the path.
|
|
1064
1066
|
|
|
1065
1067
|
|
|
1066
1068
|
|
|
1067
1069
|
|
|
1068
1070
|
|
|
1069
|
-
```ts
|
|
1070
|
-
|
|
1071
1071
|
|
|
1072
1072
|
|
|
1073
|
+
```ts
|
|
1073
1074
|
export let myNPC = npc.create({position: Vector3.create(10,0,10),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
1074
1075
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
1076
|
//NPC Data Object
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
1077
|
{
|
|
1078
|
+
type: npc.NPCType.CUSTOM,
|
|
1079
|
+
model: 'models/npc.glb',
|
|
1080
|
+
onActivate: ()=>{console.log('npc activated');},
|
|
1081
|
+
}
|
|
1082
|
+
)
|
|
1083
|
+
npc.followPath(myNPC,
|
|
1084
|
+
{
|
|
1085
|
+
path: [new Vector3(2, 0, 2), new Vector3(4, 0, 4), new Vector3(6, 0, 6)]
|
|
1086
|
+
})
|
|
1087
|
+
```
|
|
1082
1088
|
|
|
1083
1089
|
|
|
1084
1090
|
|
|
1085
|
-
type: npc.NPCType.CUSTOM,
|
|
1086
|
-
|
|
1087
1091
|
|
|
1088
1092
|
|
|
1089
|
-
model: 'models/npc.glb',
|
|
1090
|
-
|
|
1091
1093
|
|
|
1092
1094
|
|
|
1093
|
-
|
|
1095
|
+
#### Example Interrupting the NPC
|
|
1094
1096
|
|
|
1095
1097
|
|
|
1096
1098
|
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
1099
|
|
|
1100
1100
|
|
|
1101
|
-
)
|
|
1102
|
-
|
|
1103
1101
|
|
|
1104
1102
|
|
|
1105
|
-
|
|
1103
|
+
In the following example, an NPC starts roaming walking over a path, pausing on every point to call out for its lost kitten. If the player activates the NPC (by pressing E on it or walking near it) the NPC stops, and turns to face the player and talk. When the conversation is over, the NPC returns to walking its path from where it left off.
|
|
1106
1104
|
|
|
1107
1105
|
|
|
1108
1106
|
|
|
1109
|
-
{
|
|
1110
|
-
|
|
1111
1107
|
|
|
1112
1108
|
|
|
1113
|
-
path: [new Vector3(2, 0, 2), new Vector3(4, 0, 4), new Vector3(6, 0, 6)]
|
|
1114
|
-
|
|
1115
1109
|
|
|
1116
1110
|
|
|
1117
|
-
|
|
1111
|
+
```ts
|
|
1112
|
+
export let myNPC = npc.create({position: Vector3.create(10,0,10),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
1118
1113
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
In the following example, an NPC starts roaming walking over a path, pausing on every point to call out for its lost kitten. If the player activates the NPC (by pressing E on it or walking near it) the NPC stops, and turns to face the player and talk. When the conversation is over, the NPC returns to walking its path from where it left off.
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
```ts
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
export let myNPC = npc.create({position: Vector3.create(10,0,10),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
//NPC Data Object
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
{
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
type: npc.NPCType.CUSTOM,
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
model: 'models/npc.glb',
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
onActivate: ()=>{
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
npc.stopWalking(myNPC);
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
npc.talk(myNPC, lostCat, 0)
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
console.log('npc activated');
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
},
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
walkingAnim: 'walk1',
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
faceUser:true
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
)
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1114
|
+
//NPC Data Object
|
|
1115
|
+
{
|
|
1116
|
+
type: npc.NPCType.CUSTOM,
|
|
1117
|
+
model: 'models/npc.glb',
|
|
1118
|
+
onActivate: ()=>{
|
|
1119
|
+
npc.stopWalking(myNPC);
|
|
1120
|
+
npc.talk(myNPC, lostCat, 0)
|
|
1121
|
+
console.log('npc activated');
|
|
1122
|
+
},
|
|
1123
|
+
walkingAnim: 'walk1',
|
|
1124
|
+
faceUser:true
|
|
1125
|
+
}
|
|
1126
|
+
)
|
|
1200
1127
|
|
|
1201
1128
|
npc.followPath(myNPC,
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
1129
|
{
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
loop: true,
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
onReachedPointCallback: () => {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
npc.stopWalking(myNPC, 3)
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
npc.playAnimation(myNPC, `Cocky`, true, 2.93)
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1130
|
+
path: [new Vector3(4, 0, 30), new Vector3(6, 0, 29), new Vector3(15, 0, 25)],
|
|
1131
|
+
loop: true,
|
|
1132
|
+
onReachedPointCallback: () => {
|
|
1133
|
+
npc.stopWalking(myNPC, 3)
|
|
1134
|
+
npc.playAnimation(myNPC, `Cocky`, true, 2.93)
|
|
1135
|
+
}
|
|
1229
1136
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
})
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1137
|
+
)
|
|
1238
1138
|
|
|
1239
1139
|
export let lostCat: Dialog[] = [
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
{
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
text: `Have you seen it anywhere?`
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
},
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
{
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
text: `Ok, I'm gonna go back to looking for it`,
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
triggeredByNext: () => {
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
npc.followPath(myNPC)
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
},
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
isEndOfDialog: true
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
]
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
```
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
### End interaction
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
The `endInteraction()` function can be used to abruptly end interactions with the NPC.
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
If applicable, it closes the dialog UI, hides speech bubbles, and makes the NPC stop rotating to face the player.
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
```ts
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
npc.endInteraction(myNPC)
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
```
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
As an alternative, you can call the `handleWalkAway()` function, which has the same effects (as long as `continueOnWalkAway` isn't set to true), but also triggers the `onWalkAway()` function.
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
## NPC Dialog Window
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
You can display an interactive dialog window to simulate a conversation with a non-player character (NPC).
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
The conversation is based on a script in JSON format. The script can include questions that can take you forward or backward, or end the conversation.
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
<img src="screenshots/NPC1.png" width="500">
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
### The NPC script
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
Each entry on the script must include at least a `text` field, but can include several more fields to further customize it.
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
Below is a minimal dialog.
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
```ts
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
export let NPCTalk: Dialog[] = [
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
{
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
text: 'Hi there'
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
},
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
{
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
text: 'It sure is nice talking to you'
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
},
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
{
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
text: 'I must go, my planet needs me',
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
isEndOfDialog: true
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1140
|
+
{
|
|
1141
|
+
text: `I lost my cat, I'm going crazy here`
|
|
1142
|
+
},
|
|
1143
|
+
|
|
1144
|
+
{
|
|
1145
|
+
text: `Have you seen it anywhere?`
|
|
1146
|
+
},
|
|
1147
|
+
|
|
1148
|
+
{
|
|
1149
|
+
text: `Ok, I'm gonna go back to looking for it`,
|
|
1150
|
+
triggeredByNext: () => {
|
|
1151
|
+
npc.followPath(myNPC)
|
|
1152
|
+
},
|
|
1153
|
+
isEndOfDialog: true
|
|
1429
1154
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
1155
|
]
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
1156
|
```
|
|
1438
1157
|
|
|
1439
1158
|
|
|
1440
1159
|
|
|
1441
1160
|
|
|
1442
1161
|
|
|
1443
|
-
The player advances through each entry by clicking the mouse button. Once the last is reached, clicking again closes the window, as it's marked as `isEndOfDialog`.
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
The script must adhere to the following schema:
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
```ts
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
class Dialog {
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
text: string
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
fontSize?: number
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
typeSpeed?: number
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
isEndOfDialog?: boolean
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
isQuestion?:boolean
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
buttons?: ButtonData[]
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
audio?: string
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
triggeredByNext?: () => void
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
```
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
> Note: A `Dialog` object can be used as an input both for the `talk()` function (that is displayed in the UI), and the `talkBubble()` function (that is displayed in a floating bubble over the NPC). Properties marked with `*` are only applicable to UI dialogs.
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
You can set the following fields to change the appearance of a dialog:
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
- `text`: The dialog text
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
- `fontSize`: Size of the text
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
1162
|
|
|
1526
1163
|
|
|
1527
|
-
|
|
1164
|
+
### End interaction
|
|
1528
1165
|
|
|
1529
1166
|
|
|
1530
1167
|
|
|
1531
|
-
|
|
1168
|
+
|
|
1532
1169
|
|
|
1533
1170
|
|
|
1534
1171
|
|
|
1535
|
-
|
|
1172
|
+
The `endInteraction()` function can be used to abruptly end interactions with the NPC.
|
|
1536
1173
|
|
|
1537
1174
|
|
|
1538
1175
|
|
|
1539
|
-
- `typeSpeed`: The text appears one character at a time, simulating typing. Players can click to skip the animation. Tune the speed of this typing (30 by default) to go slower or faster. Set to _-1_ to skip the animation.
|
|
1540
|
-
|
|
1541
1176
|
|
|
1542
1177
|
|
|
1543
1178
|
|
|
1544
1179
|
|
|
1545
|
-
|
|
1180
|
+
If applicable, it closes the dialog UI, hides speech bubbles, and makes the NPC stop rotating to face the player.
|
|
1546
1181
|
|
|
1547
1182
|
|
|
1548
1183
|
|
|
1549
1184
|
|
|
1550
1185
|
|
|
1551
|
-
The script can include questions that prompt the player to pick between two or up to four options. These questions can branch the conversation out and trigger other actions in the scene.
|
|
1552
|
-
|
|
1553
1186
|
|
|
1554
1187
|
|
|
1555
|
-
|
|
1188
|
+
```ts
|
|
1189
|
+
npc.endInteraction(myNPC)
|
|
1190
|
+
```
|
|
1556
1191
|
|
|
1557
|
-
|
|
1192
|
+
|
|
1558
1193
|
|
|
1559
1194
|
|
|
1560
1195
|
|
|
1561
1196
|
|
|
1562
1197
|
|
|
1563
|
-
|
|
1198
|
+
As an alternative, you can call the `handleWalkAway()` function, which has the same effects (as long as `continueOnWalkAway` isn't set to true), but also triggers the `onWalkAway()` function.
|
|
1564
1199
|
|
|
1565
1200
|
|
|
1566
1201
|
|
|
1567
1202
|
|
|
1568
1203
|
|
|
1569
|
-
To make an entry a question, set the `isQuestion` field to _true_. This displays a set of buttons rather than the click icon. It also disables the click to advance to the next entry.
|
|
1570
|
-
|
|
1571
1204
|
|
|
1572
1205
|
|
|
1573
|
-
|
|
1206
|
+
## NPC Dialog Window
|
|
1574
1207
|
|
|
1575
|
-
|
|
1208
|
+
|
|
1576
1209
|
|
|
1577
1210
|
|
|
1578
1211
|
|
|
1579
1212
|
|
|
1580
1213
|
|
|
1581
|
-
|
|
1214
|
+
You can display an interactive dialog window to simulate a conversation with a non-player character (NPC).
|
|
1582
1215
|
|
|
1583
1216
|
|
|
1584
1217
|
|
|
1585
1218
|
|
|
1586
1219
|
|
|
1587
|
-
- `label`: _(string)_ The label to show on the button.
|
|
1588
|
-
|
|
1589
1220
|
|
|
1590
1221
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1222
|
+
The conversation is based on a script in JSON format. The script can include questions that can take you forward or backward, or end the conversation.
|
|
1594
1223
|
|
|
1595
1224
|
|
|
1596
1225
|
|
|
1597
|
-
> TIP: It's always better to refer to an entry by name, since the array index might shift if you add more entries and it can get hard to keep track of these references.
|
|
1598
|
-
|
|
1599
1226
|
|
|
1600
1227
|
|
|
1601
1228
|
|
|
1602
1229
|
|
|
1603
|
-
|
|
1230
|
+
<img src="screenshots/NPC1.png" width="500">
|
|
1604
1231
|
|
|
1605
1232
|
|
|
1606
1233
|
|
|
1607
1234
|
|
|
1608
1235
|
|
|
1609
|
-
- `triggeredActions`: _( () => void )_ An additional function to run whenever the button is activated
|
|
1610
|
-
|
|
1611
1236
|
|
|
1612
1237
|
|
|
1613
|
-
|
|
1238
|
+
### The NPC script
|
|
1614
1239
|
|
|
1615
1240
|
|
|
1616
1241
|
|
|
1617
|
-
|
|
1242
|
+
|
|
1618
1243
|
|
|
1619
1244
|
|
|
1620
1245
|
|
|
1621
|
-
|
|
1246
|
+
Each entry on the script must include at least a `text` field, but can include several more fields to further customize it.
|
|
1622
1247
|
|
|
1623
1248
|
|
|
1624
1249
|
|
|
1625
1250
|
|
|
1626
1251
|
|
|
1627
|
-
All buttons can be clicked to activate them. Additionally, the first button in the array can be activated by pressing the _E_ key. The second button in the array can be activated by pressing the _F_ key,
|
|
1628
|
-
|
|
1629
1252
|
|
|
1630
1253
|
|
|
1631
|
-
|
|
1254
|
+
Below is a minimal dialog.
|
|
1632
1255
|
|
|
1633
|
-
|
|
1256
|
+
|
|
1634
1257
|
|
|
1635
1258
|
|
|
1636
1259
|
|
|
1637
1260
|
|
|
1638
1261
|
|
|
1639
1262
|
```ts
|
|
1263
|
+
export let NPCTalk: Dialog[] = [
|
|
1264
|
+
{
|
|
1265
|
+
text: 'Hi there'
|
|
1266
|
+
},
|
|
1267
|
+
|
|
1268
|
+
{
|
|
1269
|
+
text: 'It sure is nice talking to you'
|
|
1270
|
+
},
|
|
1271
|
+
|
|
1272
|
+
{
|
|
1273
|
+
text: 'I must go, my planet needs me',
|
|
1274
|
+
isEndOfDialog: true
|
|
1275
|
+
}
|
|
1276
|
+
]
|
|
1640
1277
|
|
|
1641
1278
|
|
|
1642
1279
|
|
|
1643
|
-
export let GemsMission: Dialog[] = [
|
|
1644
|
-
|
|
1645
1280
|
|
|
1646
1281
|
|
|
1647
|
-
|
|
1282
|
+
```
|
|
1648
1283
|
|
|
1649
1284
|
|
|
1650
1285
|
|
|
1651
|
-
text: `Hello stranger`
|
|
1652
|
-
|
|
1653
1286
|
|
|
1654
1287
|
|
|
1655
|
-
},
|
|
1656
|
-
|
|
1657
1288
|
|
|
1658
1289
|
|
|
1659
|
-
|
|
1290
|
+
The player advances through each entry by clicking the mouse button. Once the last is reached, clicking again closes the window, as it's marked as `isEndOfDialog`.
|
|
1660
1291
|
|
|
1661
1292
|
|
|
1662
1293
|
|
|
1663
|
-
text: `Can you help me finding my missing gems?`,
|
|
1664
|
-
|
|
1665
1294
|
|
|
1666
1295
|
|
|
1667
|
-
isQuestion: true,
|
|
1668
|
-
|
|
1669
1296
|
|
|
1670
1297
|
|
|
1671
|
-
|
|
1298
|
+
The script must adhere to the following schema:
|
|
1672
1299
|
|
|
1673
1300
|
|
|
1674
1301
|
|
|
1675
|
-
{ label: `Yes!`, goToDialog: 2 },
|
|
1676
|
-
|
|
1677
1302
|
|
|
1678
1303
|
|
|
1679
|
-
{ label: `I'm busy`, goToDialog: 4 }
|
|
1680
|
-
|
|
1681
1304
|
|
|
1682
1305
|
|
|
1683
|
-
|
|
1306
|
+
```ts
|
|
1307
|
+
class Dialog {
|
|
1308
|
+
text: string
|
|
1309
|
+
fontSize?: number
|
|
1310
|
+
typeSpeed?: number
|
|
1311
|
+
isEndOfDialog?: boolean
|
|
1312
|
+
isQuestion?:boolean
|
|
1313
|
+
buttons?: ButtonData[]
|
|
1314
|
+
audio?: string
|
|
1315
|
+
triggeredByNext?: () => void
|
|
1316
|
+
}
|
|
1317
|
+
```
|
|
1684
1318
|
|
|
1685
1319
|
|
|
1686
1320
|
|
|
1687
|
-
},
|
|
1688
|
-
|
|
1689
1321
|
|
|
1690
1322
|
|
|
1691
|
-
{
|
|
1692
|
-
|
|
1693
1323
|
|
|
1694
1324
|
|
|
1695
|
-
|
|
1325
|
+
> Note: A `Dialog` object can be used as an input both for the `talk()` function (that is displayed in the UI), and the `talkBubble()` function (that is displayed in a floating bubble over the NPC). Properties marked with `*` are only applicable to UI dialogs.
|
|
1696
1326
|
|
|
1697
1327
|
|
|
1698
1328
|
|
|
1699
|
-
},
|
|
1700
|
-
|
|
1701
1329
|
|
|
1702
1330
|
|
|
1703
|
-
{
|
|
1704
|
-
|
|
1705
1331
|
|
|
1706
1332
|
|
|
1707
|
-
|
|
1333
|
+
You can set the following fields to change the appearance of a dialog:
|
|
1708
1334
|
|
|
1709
1335
|
|
|
1710
1336
|
|
|
1711
|
-
|
|
1337
|
+
|
|
1712
1338
|
|
|
1713
1339
|
|
|
1714
1340
|
|
|
1715
|
-
|
|
1341
|
+
- `text`: The dialog text
|
|
1716
1342
|
|
|
1717
1343
|
|
|
1718
1344
|
|
|
1719
|
-
{
|
|
1720
|
-
|
|
1721
1345
|
|
|
1722
1346
|
|
|
1723
|
-
|
|
1347
|
+
- `fontSize`: Size of the text
|
|
1724
1348
|
|
|
1725
1349
|
|
|
1726
1350
|
|
|
1727
|
-
|
|
1351
|
+
|
|
1728
1352
|
|
|
1729
1353
|
|
|
1730
1354
|
|
|
1731
|
-
|
|
1355
|
+
Other fields:
|
|
1732
1356
|
|
|
1733
1357
|
|
|
1734
1358
|
|
|
1735
|
-
]
|
|
1736
|
-
|
|
1737
1359
|
|
|
1738
1360
|
|
|
1739
|
-
|
|
1361
|
+
- `buttons *`: An array of buttons to use in a question entry, covered in the next section.
|
|
1740
1362
|
|
|
1741
1363
|
|
|
1742
1364
|
|
|
1743
1365
|
|
|
1744
1366
|
|
|
1745
|
-
|
|
1367
|
+
- `audio`: String with the path to an audio file to play once when this dialog is shown on the UI.
|
|
1746
1368
|
|
|
1747
1369
|
|
|
1748
1370
|
|
|
1749
1371
|
|
|
1750
1372
|
|
|
1751
|
-
|
|
1373
|
+
- `typeSpeed`: The text appears one character at a time, simulating typing. Players can click to skip the animation. Tune the speed of this typing (30 by default) to go slower or faster. Set to _-1_ to skip the animation.
|
|
1752
1374
|
|
|
1753
1375
|
|
|
1754
1376
|
|
|
1755
1377
|
|
|
1756
1378
|
|
|
1757
|
-
- `triggeredByNext`: Is executed when the player advances to the next dialog on a non-question dialog. The function also gets called if the dialog is the end of the conversation. It also gets called when a speech bubble advances to the next entry.
|
|
1758
|
-
|
|
1759
1379
|
|
|
1760
1380
|
|
|
1761
|
-
|
|
1381
|
+
#### Questions and conversation trees
|
|
1762
1382
|
|
|
1763
|
-
|
|
1383
|
+
|
|
1764
1384
|
|
|
1765
1385
|
|
|
1766
1386
|
|
|
1767
1387
|
|
|
1768
1388
|
|
|
1769
|
-
|
|
1389
|
+
The script can include questions that prompt the player to pick between two or up to four options. These questions can branch the conversation out and trigger other actions in the scene.
|
|
1770
1390
|
|
|
1771
1391
|
|
|
1772
1392
|
|
|
1773
|
-
|
|
1393
|
+
|
|
1774
1394
|
|
|
1775
1395
|
|
|
1776
1396
|
|
|
1777
|
-
|
|
1397
|
+
<img src="screenshots/NPC2.png" width="500">
|
|
1778
1398
|
|
|
1779
1399
|
|
|
1780
1400
|
|
|
1781
|
-
|
|
1401
|
+
|
|
1782
1402
|
|
|
1783
1403
|
|
|
1784
1404
|
|
|
1785
|
-
|
|
1405
|
+
> Note: Questions are only used by UI dialogs. If used in a speech bubble, questions will be displayed as regular entries with no buttons or options.
|
|
1786
1406
|
|
|
1787
1407
|
|
|
1788
1408
|
|
|
1789
|
-
|
|
1409
|
+
|
|
1790
1410
|
|
|
1791
1411
|
|
|
1792
1412
|
|
|
1793
|
-
|
|
1413
|
+
To make an entry a question, set the `isQuestion` field to _true_. This displays a set of buttons rather than the click icon. It also disables the click to advance to the next entry.
|
|
1794
1414
|
|
|
1795
1415
|
|
|
1796
1416
|
|
|
1797
|
-
|
|
1417
|
+
|
|
1798
1418
|
|
|
1799
1419
|
|
|
1800
1420
|
|
|
1801
|
-
|
|
1421
|
+
The `buttons` property of an entry contains an array of `ButtonData` objects, each one of these defines one button.
|
|
1802
1422
|
|
|
1803
1423
|
|
|
1804
1424
|
|
|
1805
|
-
|
|
1425
|
+
|
|
1806
1426
|
|
|
1807
1427
|
|
|
1808
1428
|
|
|
1809
|
-
|
|
1429
|
+
When on a question entry, you must provide at least the following for each button:
|
|
1810
1430
|
|
|
1811
1431
|
|
|
1812
1432
|
|
|
1813
|
-
|
|
1433
|
+
|
|
1814
1434
|
|
|
1815
1435
|
|
|
1816
1436
|
|
|
1817
|
-
|
|
1437
|
+
- `label`: _(string)_ The label to show on the button.
|
|
1818
1438
|
|
|
1819
1439
|
|
|
1820
1440
|
|
|
1821
|
-
label: `Yes!`,
|
|
1822
|
-
|
|
1823
1441
|
|
|
1824
1442
|
|
|
1825
|
-
goToDialog
|
|
1443
|
+
- `goToDialog`: _(number | string)_ The index or name of the next dialog entry to display when activated.
|
|
1826
1444
|
|
|
1827
1445
|
|
|
1828
1446
|
|
|
1829
|
-
|
|
1447
|
+
|
|
1830
1448
|
|
|
1831
1449
|
|
|
1832
1450
|
|
|
1833
|
-
|
|
1451
|
+
> TIP: It's always better to refer to an entry by name, since the array index might shift if you add more entries and it can get hard to keep track of these references.
|
|
1834
1452
|
|
|
1835
1453
|
|
|
1836
1454
|
|
|
1837
|
-
|
|
1455
|
+
|
|
1838
1456
|
|
|
1839
1457
|
|
|
1840
1458
|
|
|
1841
|
-
|
|
1459
|
+
You can also set the following:
|
|
1842
1460
|
|
|
1843
1461
|
|
|
1844
1462
|
|
|
1845
|
-
|
|
1463
|
+
|
|
1846
1464
|
|
|
1847
1465
|
|
|
1848
1466
|
|
|
1849
|
-
|
|
1467
|
+
- `triggeredActions`: _( () => void )_ An additional function to run whenever the button is activated
|
|
1850
1468
|
|
|
1851
1469
|
|
|
1852
1470
|
|
|
1853
|
-
goToDialog: 4
|
|
1854
|
-
|
|
1855
1471
|
|
|
1856
1472
|
|
|
1857
|
-
|
|
1473
|
+
- `fontSize`: _(number)_ Font size of the text
|
|
1858
1474
|
|
|
1859
1475
|
|
|
1860
1476
|
|
|
1861
|
-
// NPC waves goodbye
|
|
1862
|
-
|
|
1863
1477
|
|
|
1864
1478
|
|
|
1865
|
-
|
|
1479
|
+
- `offsetX`: _(number)_ Offset of the label on the X axis, relative to its normal position.
|
|
1866
1480
|
|
|
1867
1481
|
|
|
1868
1482
|
|
|
1869
|
-
},
|
|
1870
|
-
|
|
1871
1483
|
|
|
1872
1484
|
|
|
1873
|
-
|
|
1485
|
+
- `offsetY`: _(number)_ Offset of the label on the Y axis, relative to its normal position.
|
|
1874
1486
|
|
|
1875
1487
|
|
|
1876
1488
|
|
|
1877
|
-
|
|
1489
|
+
|
|
1878
1490
|
|
|
1879
1491
|
|
|
1880
1492
|
|
|
1881
|
-
|
|
1493
|
+
All buttons can be clicked to activate them. Additionally, the first button in the array can be activated by pressing the _E_ key. The second button in the array can be activated by pressing the _F_ key,
|
|
1882
1494
|
|
|
1883
1495
|
|
|
1884
1496
|
|
|
1885
|
-
|
|
1497
|
+
|
|
1886
1498
|
|
|
1887
1499
|
|
|
1888
1500
|
|
|
1889
|
-
|
|
1501
|
+
<img src="screenshots/NPC3.png" width="500">
|
|
1890
1502
|
|
|
1891
1503
|
|
|
1892
1504
|
|
|
1893
|
-
|
|
1505
|
+
|
|
1894
1506
|
|
|
1895
1507
|
|
|
1896
1508
|
|
|
1897
|
-
|
|
1509
|
+
```ts
|
|
1510
|
+
export let GemsMission: Dialog[] = [
|
|
1511
|
+
{
|
|
1512
|
+
text: `Hello stranger`
|
|
1513
|
+
},
|
|
1514
|
+
|
|
1515
|
+
{
|
|
1516
|
+
text: `Can you help me finding my missing gems?`,
|
|
1517
|
+
isQuestion: true,
|
|
1518
|
+
buttons: [
|
|
1519
|
+
{ label: `Yes!`, goToDialog: 2 },
|
|
1520
|
+
{ label: `I'm busy`, goToDialog: 4 }
|
|
1521
|
+
]
|
|
1522
|
+
},
|
|
1523
|
+
|
|
1524
|
+
{
|
|
1525
|
+
text: `Ok, awesome, thanks!`
|
|
1526
|
+
},
|
|
1527
|
+
|
|
1528
|
+
{
|
|
1529
|
+
text: `I need you to find 10 gems scattered around this scene, go find them!`,
|
|
1530
|
+
isEndOfDialog: true
|
|
1531
|
+
},
|
|
1532
|
+
|
|
1533
|
+
{
|
|
1534
|
+
text: `Ok, come back soon`,
|
|
1535
|
+
isEndOfDialog: true
|
|
1536
|
+
}
|
|
1537
|
+
]
|
|
1538
|
+
```
|
|
1898
1539
|
|
|
1899
1540
|
|
|
1900
1541
|
|
|
1901
|
-
|
|
1542
|
+
|
|
1902
1543
|
|
|
1903
1544
|
|
|
1904
1545
|
|
|
1905
|
-
|
|
1546
|
+
#### Triggering functions from the dialog
|
|
1906
1547
|
|
|
1907
1548
|
|
|
1908
1549
|
|
|
1909
|
-
|
|
1550
|
+
|
|
1910
1551
|
|
|
1911
1552
|
|
|
1912
1553
|
|
|
1913
|
-
|
|
1554
|
+
You can run functions that may affect any other part of your scene. These functions get triggered when the player interacts with the dialog window, or when the NPC displays speech bubbles.
|
|
1914
1555
|
|
|
1915
1556
|
|
|
1916
1557
|
|
|
1917
|
-
|
|
1558
|
+
|
|
1918
1559
|
|
|
1919
1560
|
|
|
1920
1561
|
|
|
1921
|
-
|
|
1562
|
+
- `triggeredByNext`: Is executed when the player advances to the next dialog on a non-question dialog. The function also gets called if the dialog is the end of the conversation. It also gets called when a speech bubble advances to the next entry.
|
|
1922
1563
|
|
|
1923
1564
|
|
|
1924
1565
|
|
|
1925
|
-
|
|
1566
|
+
|
|
1926
1567
|
|
|
1927
1568
|
|
|
1928
1569
|
|
|
1929
|
-
|
|
1570
|
+
- `triggeredActions`: This property is associated to a button and is executed on a question dialog if the player activates the corresponding button. You can have up to 4 different buttons per entry, each with its own actions.
|
|
1930
1571
|
|
|
1931
1572
|
|
|
1932
1573
|
|
|
1933
|
-
|
|
1574
|
+
|
|
1934
1575
|
|
|
1935
1576
|
|
|
1936
1577
|
|
|
1578
|
+
```ts
|
|
1579
|
+
export let GemsMission: Dialog[] = [
|
|
1580
|
+
{
|
|
1581
|
+
text: `Hello stranger`,
|
|
1582
|
+
triggeredByNext: () => {
|
|
1583
|
+
// NPC plays animation to show a gem
|
|
1584
|
+
}
|
|
1585
|
+
},
|
|
1586
|
+
|
|
1587
|
+
{
|
|
1588
|
+
text: `Can you help me finding my missing gems?`,
|
|
1589
|
+
isQuestion: true,
|
|
1590
|
+
buttons: [
|
|
1591
|
+
{
|
|
1592
|
+
label: `Yes!`,
|
|
1593
|
+
goToDialog: 2,
|
|
1594
|
+
triggeredActions: () => {
|
|
1595
|
+
// NPC plays an animation to celebrate
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
|
|
1599
|
+
{
|
|
1600
|
+
label: `I'm busy`,
|
|
1601
|
+
goToDialog: 4
|
|
1602
|
+
triggeredActions: () => {
|
|
1603
|
+
// NPC waves goodbye
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
]
|
|
1607
|
+
},
|
|
1608
|
+
|
|
1609
|
+
{
|
|
1610
|
+
text: `Ok, awesome, thanks!`,
|
|
1611
|
+
},
|
|
1612
|
+
|
|
1613
|
+
{
|
|
1614
|
+
text: `I need you to find 10 gems scattered around this scene, go find them!`,
|
|
1615
|
+
isEndOfDialog: true
|
|
1616
|
+
triggeredByNext: () => {
|
|
1617
|
+
// Gems are rendered all around the scene
|
|
1618
|
+
},
|
|
1619
|
+
|
|
1620
|
+
{
|
|
1621
|
+
text: `Ok, come back soon`,
|
|
1622
|
+
isEndOfDialog: true
|
|
1623
|
+
}
|
|
1937
1624
|
]
|
|
1625
|
+
```
|
|
1938
1626
|
|
|
1939
1627
|
|
|
1940
1628
|
|
|
1941
|
-
```
|
|
1942
|
-
|
|
1943
1629
|
|
|
1944
1630
|
|
|
1945
1631
|
## No-NPC Dialogs
|
|
@@ -1948,73 +1634,84 @@ isEndOfDialog: true
|
|
|
1948
1634
|
|
|
1949
1635
|
|
|
1950
1636
|
|
|
1637
|
+
|
|
1638
|
+
|
|
1951
1639
|
You can open a Dialog window that isn't associated with any `NPC` object in the scene. The `openDialogWindow()` function has all the same functionality as calling the `talk()` function on an NPC, but may be more practical in scenarios where a character isn't physically there, or where the conversation isn't with a particular character.
|
|
1952
1640
|
|
|
1953
1641
|
|
|
1954
1642
|
|
|
1955
1643
|
|
|
1956
1644
|
|
|
1645
|
+
|
|
1646
|
+
|
|
1957
1647
|
### The Dialog window
|
|
1958
1648
|
|
|
1959
1649
|
|
|
1960
1650
|
|
|
1961
1651
|
|
|
1962
1652
|
|
|
1653
|
+
|
|
1654
|
+
|
|
1963
1655
|
To create a new dialog window, call `createDialogWindow()` and store as a variable. This will instantiate the window but keep it hidden until you open it.
|
|
1964
1656
|
|
|
1965
1657
|
|
|
1966
1658
|
|
|
1967
|
-
```ts
|
|
1968
|
-
|
|
1969
1659
|
|
|
1970
1660
|
|
|
1661
|
+
```ts
|
|
1971
1662
|
let dialogWindow = npc.createDialogWindow()
|
|
1663
|
+
```
|
|
1972
1664
|
|
|
1973
1665
|
|
|
1974
1666
|
|
|
1975
|
-
```
|
|
1976
|
-
|
|
1977
1667
|
|
|
1978
1668
|
|
|
1979
1669
|
<img src="screenshots/NPC1.png" width="500">
|
|
1980
1670
|
|
|
1981
1671
|
|
|
1982
1672
|
|
|
1673
|
+
|
|
1674
|
+
|
|
1983
1675
|
When instantiating a new blank dialog, you can pass the following optional parameters:
|
|
1984
1676
|
|
|
1985
1677
|
|
|
1678
|
+
|
|
1986
1679
|
|
|
1987
1680
|
|
|
1988
1681
|
- `defaultPortrait`: Sets a default portrait image to use on the left of all dialogs that don't specify an image. If a dialog has no portrait and no default is provided, no image is shown on the left. This field expects a `Portrait` object, that may include the following fields: - `path`: Path to the image file - `xOffset`: Offset on X, relative to the normal position of the portrait. - `yOffset`: Offset on Y, relative to the normal position of the portrait. - `section`: Use only a section of the image file, useful when arranging multiple icons into an image atlas. This field takes an `ImageSection` object, specifying `sourceWidth` and `sourceHeight`, and optionally also `sourceLeft` and `sourceTop`.
|
|
1989
1682
|
|
|
1990
1683
|
|
|
1991
1684
|
|
|
1685
|
+
|
|
1686
|
+
|
|
1992
1687
|
- `useDarkTheme`: Switch the style of the window to the dark theme.
|
|
1993
1688
|
|
|
1994
1689
|
|
|
1995
1690
|
|
|
1691
|
+
|
|
1692
|
+
|
|
1996
1693
|
- `sound`: Path to a sound file that will be played once for every dialog entry shown, as long as the dialog entry doesn't have its own `audio` property.
|
|
1997
1694
|
|
|
1998
1695
|
|
|
1999
1696
|
|
|
2000
1697
|
|
|
2001
1698
|
|
|
1699
|
+
|
|
1700
|
+
|
|
2002
1701
|
Once you have created a dialog window, you can open a dialog window with the `openDialogWindow()` function.
|
|
2003
1702
|
|
|
2004
1703
|
|
|
2005
1704
|
|
|
2006
1705
|
|
|
2007
1706
|
|
|
2008
|
-
```ts
|
|
2009
|
-
|
|
2010
1707
|
|
|
2011
1708
|
|
|
1709
|
+
```ts
|
|
2012
1710
|
npc.openDialogWindow(dialogWindow, NPCTalk, 0)
|
|
1711
|
+
```
|
|
2013
1712
|
|
|
2014
1713
|
|
|
2015
1714
|
|
|
2016
|
-
```
|
|
2017
|
-
|
|
2018
1715
|
|
|
2019
1716
|
|
|
2020
1717
|
|
|
@@ -2025,46 +1722,54 @@ When calling this function, you must specify:
|
|
|
2025
1722
|
|
|
2026
1723
|
|
|
2027
1724
|
|
|
1725
|
+
|
|
1726
|
+
|
|
2028
1727
|
- `NPCScript`: A JSON object composed of an array of `Dialog` objects, that includes all the dialog tree.
|
|
2029
1728
|
|
|
2030
1729
|
|
|
2031
1730
|
|
|
2032
1731
|
|
|
2033
1732
|
|
|
1733
|
+
|
|
1734
|
+
|
|
2034
1735
|
A second optional parameter is also available:
|
|
2035
1736
|
|
|
2036
1737
|
|
|
2037
1738
|
|
|
2038
1739
|
|
|
2039
1740
|
|
|
1741
|
+
|
|
1742
|
+
|
|
2040
1743
|
- `textId`: The index or `name` property of the entry to show first from the script. The first entry is 0.
|
|
2041
1744
|
|
|
2042
1745
|
|
|
2043
1746
|
|
|
2044
1747
|
|
|
2045
1748
|
|
|
1749
|
+
|
|
1750
|
+
|
|
2046
1751
|
> TIP: It's always better to refer to an entry by name, since the array index might shift if you add more entries and it can get hard to keep track of these references.
|
|
2047
1752
|
|
|
2048
1753
|
|
|
2049
1754
|
|
|
2050
1755
|
|
|
2051
1756
|
|
|
1757
|
+
|
|
1758
|
+
|
|
2052
1759
|
Close a dialog window at any time by calling the `closeDialogWindow()` function.
|
|
2053
1760
|
|
|
2054
1761
|
|
|
2055
1762
|
|
|
2056
1763
|
|
|
2057
1764
|
|
|
2058
|
-
```ts
|
|
2059
|
-
|
|
2060
1765
|
|
|
2061
1766
|
|
|
1767
|
+
```ts
|
|
2062
1768
|
npc.closeDialogWindow(dialogWindow)
|
|
1769
|
+
```
|
|
2063
1770
|
|
|
2064
1771
|
|
|
2065
1772
|
|
|
2066
|
-
```
|
|
2067
|
-
|
|
2068
1773
|
|
|
2069
1774
|
|
|
2070
1775
|
|
|
@@ -2075,94 +1780,120 @@ For details on how to construct the dialog tree, see the sections above. The req
|
|
|
2075
1780
|
|
|
2076
1781
|
|
|
2077
1782
|
|
|
1783
|
+
|
|
1784
|
+
|
|
2078
1785
|
---
|
|
2079
1786
|
|
|
2080
1787
|
|
|
2081
1788
|
|
|
1789
|
+
|
|
1790
|
+
|
|
2082
1791
|
## Contribute
|
|
2083
1792
|
|
|
2084
1793
|
|
|
2085
1794
|
|
|
2086
1795
|
|
|
2087
1796
|
|
|
1797
|
+
|
|
1798
|
+
|
|
2088
1799
|
In order to test changes made to this repository in active scenes, do the following:
|
|
2089
1800
|
|
|
2090
1801
|
|
|
2091
1802
|
|
|
2092
1803
|
|
|
2093
1804
|
|
|
1805
|
+
|
|
1806
|
+
|
|
2094
1807
|
1. Run `npm run build` for the internal files of the library to be generated
|
|
2095
1808
|
|
|
2096
1809
|
|
|
2097
1810
|
|
|
1811
|
+
|
|
1812
|
+
|
|
2098
1813
|
2. Run `npm run link` on this repository
|
|
2099
1814
|
|
|
2100
1815
|
|
|
2101
1816
|
|
|
1817
|
+
|
|
1818
|
+
|
|
2102
1819
|
3. On a new Decentraland scene, import this library as you normally would and include the tests you need
|
|
2103
1820
|
|
|
2104
1821
|
|
|
2105
1822
|
|
|
1823
|
+
|
|
1824
|
+
|
|
2106
1825
|
4. On the scene directory, run `npm link dcl-npc-toolkit`
|
|
2107
1826
|
|
|
2108
1827
|
|
|
2109
1828
|
|
|
2110
1829
|
|
|
2111
1830
|
|
|
1831
|
+
|
|
1832
|
+
|
|
2112
1833
|
> Note: When done testing, run `npm unlink` on both folders, so that the scene stops using the local version of the library.
|
|
2113
1834
|
|
|
2114
1835
|
|
|
2115
1836
|
|
|
2116
1837
|
|
|
2117
1838
|
|
|
1839
|
+
|
|
1840
|
+
|
|
2118
1841
|
## CI/CD
|
|
2119
1842
|
|
|
2120
1843
|
|
|
2121
1844
|
|
|
2122
1845
|
|
|
2123
1846
|
|
|
1847
|
+
|
|
1848
|
+
|
|
2124
1849
|
This repository uses `semantic-release` to automatically release new versions of the package to NPM.
|
|
2125
1850
|
|
|
2126
1851
|
|
|
2127
1852
|
|
|
2128
1853
|
|
|
2129
1854
|
|
|
1855
|
+
|
|
1856
|
+
|
|
2130
1857
|
Use the following convention for commit names:
|
|
2131
1858
|
|
|
2132
1859
|
|
|
2133
1860
|
|
|
2134
1861
|
|
|
2135
1862
|
|
|
1863
|
+
|
|
1864
|
+
|
|
2136
1865
|
`feat: something`: Minor release, every time you add a feature or enhancement that doesn’t break the api.
|
|
2137
1866
|
|
|
2138
1867
|
|
|
2139
1868
|
|
|
2140
1869
|
|
|
2141
1870
|
|
|
1871
|
+
|
|
1872
|
+
|
|
2142
1873
|
`fix: something`: Bug fixing / patch
|
|
2143
1874
|
|
|
2144
1875
|
|
|
2145
1876
|
|
|
2146
1877
|
|
|
2147
1878
|
|
|
1879
|
+
|
|
1880
|
+
|
|
2148
1881
|
`chore: something`: Anything that doesn't require a release to npm, like changing the readme. Updating a dependency is **not** a chore if it fixes a bug or a vulnerability, that's a `fix`.
|
|
2149
1882
|
|
|
2150
1883
|
|
|
2151
1884
|
|
|
2152
1885
|
|
|
2153
1886
|
|
|
1887
|
+
|
|
1888
|
+
|
|
2154
1889
|
If you break the API of the library, you need to do a major release, and that's done a different way. You need to add a second comment that starts with `BREAKING CHANGE`, like:
|
|
2155
1890
|
|
|
2156
1891
|
|
|
2157
1892
|
|
|
2158
1893
|
|
|
2159
1894
|
|
|
2160
|
-
```
|
|
2161
|
-
|
|
2162
1895
|
|
|
2163
1896
|
|
|
1897
|
+
```
|
|
2164
1898
|
commit -m "feat: changed the signature of a method" -m "BREAKING CHANGE: this commit breaks the API, changing foo(arg1) to foo(arg1, arg2)"
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
1899
|
```
|