Needle Engine

Changes between version 3.22.2 and 3.22.3
Files changed (4) hide show
  1. src/engine-components/CharacterController.ts +14 -8
  2. src/engine/engine_context.ts +9 -0
  3. src/engine/engine_coroutine.ts +9 -0
  4. src/engine-components/ShadowCatcher.ts +1 -1
src/engine-components/CharacterController.ts CHANGED
@@ -8,7 +8,10 @@
8
8
  import { Animator } from "./Animator.js"
9
9
  import { RaycastOptions } from "../engine/engine_physics.js";
10
10
  import { getWorldPosition } from "../engine/engine_three_utils.js";
11
+ import { getParam } from "../engine/engine_utils.js";
11
12
 
13
+ const debug = getParam("debugcharactercontroller");
14
+
12
15
  export class CharacterController extends Behaviour {
13
16
 
14
17
  @serializable(Vector3)
@@ -30,7 +33,7 @@
30
33
  private _activeGroundCollisions!: Set<Collision>;
31
34
 
32
35
  awake(): void {
33
- this._activeGroundCollisions = new Set<Collision>();
36
+ this._activeGroundCollisions = new Set<Collision>();
34
37
  }
35
38
 
36
39
  onEnable() {
@@ -38,7 +41,7 @@
38
41
  let collider = this.gameObject.getComponent(CapsuleCollider);
39
42
  if (!collider)
40
43
  collider = this.gameObject.addNewComponent(CapsuleCollider) as CapsuleCollider;
41
-
44
+
42
45
  collider.center.copy(this.center);
43
46
  collider.radius = this.radius;
44
47
  collider.height = this.height;
@@ -63,19 +66,22 @@
63
66
  this.gameObject.position.add(vec);
64
67
  }
65
68
 
66
-
67
69
  onCollisionEnter(col: Collision) {
68
- for (const contact of col.contacts) {
69
- // console.log(contact.normal);
70
- if (contact.normal.y > .1) {
71
- this._activeGroundCollisions.add(col);
72
- break;
70
+ // contacts can be empty, ignoring such collision results in a stuck grounded state
71
+ // namely caused by mesh colliders
72
+ if (col.contacts.length == 0 || col.contacts.some(contact => contact.normal.y > 0.2)) {
73
+ this._activeGroundCollisions.add(col);
74
+ if (debug) {
75
+ console.log(`Collision(${this._activeGroundCollisions.size}): ${col.contacts.map(c => c.normal.y.toFixed(2)).join(", ")} - ${this.isGrounded}`);
73
76
  }
74
77
  }
75
78
  }
76
79
 
77
80
  onCollisionExit(col: Collision) {
78
81
  this._activeGroundCollisions.delete(col);
82
+ if (debug) {
83
+ console.log(`Collision(${this._activeGroundCollisions.size}) - ${this.isGrounded}`);
84
+ }
79
85
  }
80
86
 
81
87
  get isGrounded(): boolean { return this._activeGroundCollisions.size > 0; }
src/engine/engine_context.ts CHANGED
@@ -33,6 +33,7 @@
33
33
  import { isDevEnvironment, LogType, showBalloonMessage, showBalloonWarning } from './debug/index.js';
34
34
  import { getLoader } from './engine_gltf.js';
35
35
  import { isLocalNetwork } from './engine_networking_utils.js';
36
+ import { WaitForPromise } from './engine_coroutine.js';
36
37
 
37
38
 
38
39
  const debug = utils.getParam("debugcontext");
@@ -1247,6 +1248,14 @@
1247
1248
  if (!evt.chained) evt.chained = [];
1248
1249
  evt.chained.push(val as Generator);
1249
1250
  }
1251
+ else if (val instanceof Promise) {
1252
+ // If its a promise we want to wait for it to resolve
1253
+ const prom = val as Promise<any>;
1254
+ if (!evt.chained) evt.chained = [];
1255
+ const nested = WaitForPromise(prom);
1256
+ evt.chained?.push(nested);
1257
+ continue;
1258
+ }
1250
1259
  }
1251
1260
  catch (e) {
1252
1261
  console.error(e);
src/engine/engine_coroutine.ts CHANGED
@@ -14,3 +14,12 @@
14
14
  yield;
15
15
  }
16
16
  }
17
+
18
+ export function* WaitForPromise(promise: Promise<any>) {
19
+ let isRunning = true;
20
+ promise.then(() => isRunning = false);
21
+ promise.catch(() => isRunning = false);
22
+ while (isRunning) {
23
+ yield;
24
+ }
25
+ }
src/engine-components/ShadowCatcher.ts CHANGED
@@ -58,7 +58,7 @@
58
58
  `vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;
59
59
  // diffuse-only lighting with overdrive to somewhat compensate
60
60
  // for the loss of indirect lighting and to make it more visible.
61
- vec3 direct = reflectedLight.directDiffuse * 3.;
61
+ vec3 direct = reflectedLight.directSpecular * 6.6;
62
62
  float max = max(direct.r, max(direct.g, direct.b));
63
63
 
64
64
  // early out - we're simply returning direct lighting and some alpha based on it so it can