@galacean/engine-core 0.0.0-experimental-2.0-game.11 → 0.0.0-experimental-2.0-game.12

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/dist/main.js CHANGED
@@ -5759,8 +5759,13 @@ function dependentComponents(componentOrComponents, dependentMode) {
5759
5759
  rotation._onValueChanged = target._onRotationChanged;
5760
5760
  // @ts-ignore
5761
5761
  scale._onValueChanged = target._onScaleChanged;
5762
- // When cloning, other components may obtain properties such as `rotationQuaternion` in the constructor, local related dirty flags need to be corrected
5762
+ // When cloning, other components may obtain properties such as `rotationQuaternion` in the constructor, local related dirty flags need to be corrected.
5763
+ // Earlier in this Entity's construction other components (e.g. DynamicCollider) may have queried
5764
+ // `worldPosition`, which clears the WorldPosition / WorldMatrix dirty flags as a side effect of caching
5765
+ // the computed value. After this _cloneTo writes new local values, those world-derived caches are stale,
5766
+ // so re-dirty them and notify listeners (Collider._updateFlag etc.) so subsequent reads recompute correctly.
5763
5767
  target._setDirtyFlagTrue(2 | 64);
5768
+ target._worldAssociatedChange(444);
5764
5769
  };
5765
5770
  _proto._onLocalMatrixChanging = function _onLocalMatrixChanging() {
5766
5771
  this._setDirtyFlagFalse(64);
@@ -20591,17 +20596,23 @@ exports.Collider = /*#__PURE__*/ function(Component) {
20591
20596
  /**
20592
20597
  * @internal
20593
20598
  */ _proto._onUpdate = function _onUpdate() {
20599
+ var shapes = this._shapes;
20594
20600
  if (this._updateFlag.flag) {
20595
20601
  var transform = this.entity.transform;
20596
- this._nativeCollider.setWorldTransform(transform.worldPosition, transform.worldRotationQuaternion);
20602
+ this._syncEntityTransformToNative(transform.worldPosition, transform.worldRotationQuaternion);
20597
20603
  var worldScale = transform.lossyWorldScale;
20598
- var shapes = this._shapes;
20599
20604
  for(var i = 0, n = shapes.length; i < n; i++){
20600
20605
  var _shapes_i__nativeShape;
20601
20606
  (_shapes_i__nativeShape = shapes[i]._nativeShape) == null ? void 0 : _shapes_i__nativeShape.setWorldScale(worldScale);
20602
20607
  }
20603
20608
  this._updateFlag.flag = false;
20604
20609
  }
20610
+ // Drive per-shape physics update (e.g. MeshColliderShape retries pending
20611
+ // native shape creation when mesh data becomes accessible asynchronously).
20612
+ // No-op for shape types that don't override `_onPhysicsUpdate`.
20613
+ for(var i1 = 0, n1 = shapes.length; i1 < n1; i1++){
20614
+ shapes[i1]._onPhysicsUpdate();
20615
+ }
20605
20616
  };
20606
20617
  /**
20607
20618
  * @internal
@@ -20633,6 +20644,28 @@ exports.Collider = /*#__PURE__*/ function(Component) {
20633
20644
  this._addNativeShape(this.shapes[i]);
20634
20645
  }
20635
20646
  this._setCollisionLayer();
20647
+ // Teleport native actor to entity's current world pose.
20648
+ // The native actor was created in constructor() with the entity's then-current
20649
+ // worldPosition/Rotation. On clone, the entity's transform fields are deep-cloned
20650
+ // AFTER the Component (and its native actor) are constructed, so the native actor's
20651
+ // pose lags behind the cloned entity transform until this sync.
20652
+ var transform = this.entity.transform;
20653
+ this._teleportToEntityTransform(transform.worldPosition, transform.worldRotationQuaternion);
20654
+ };
20655
+ /**
20656
+ * Teleport native actor to a world pose (instant, no implied velocity).
20657
+ * Used during initialization paths (clone) where the native actor must be re-aligned
20658
+ * with the entity transform after construction-time pose was based on stale defaults.
20659
+ */ _proto._teleportToEntityTransform = function _teleportToEntityTransform(worldPosition, worldRotation) {
20660
+ this._nativeCollider.setWorldTransform(worldPosition, worldRotation);
20661
+ };
20662
+ /**
20663
+ * Sync entity world transform to native actor for per-frame updates.
20664
+ * Default semantics: teleport (setGlobalPose). Subclasses override to express
20665
+ * physics-aware movement (e.g. DynamicCollider routes kinematic actors through
20666
+ * setKinematicTarget to generate contact events on swept motion).
20667
+ */ _proto._syncEntityTransformToNative = function _syncEntityTransformToNative(worldPosition, worldRotation) {
20668
+ this._nativeCollider.setWorldTransform(worldPosition, worldRotation);
20636
20669
  };
20637
20670
  /**
20638
20671
  * @internal
@@ -20792,6 +20825,9 @@ exports.Collider = __decorate([
20792
20825
  this._nativeCollider.setUpDirection(this._upDirection);
20793
20826
  this._nativeCollider.setSlopeLimit(this._slopeLimit);
20794
20827
  };
20828
+ _proto._teleportToEntityTransform = function _teleportToEntityTransform(worldPosition, _worldRotation) {
20829
+ this._nativeCollider.setWorldPosition(worldPosition);
20830
+ };
20795
20831
  _proto._syncWorldPositionFromPhysicalSpace = function _syncWorldPositionFromPhysicalSpace() {
20796
20832
  this._nativeCollider.getWorldPosition(this.entity.transform.worldPosition);
20797
20833
  };
@@ -20894,7 +20930,7 @@ __decorate([
20894
20930
  this._staticFriction = 0.6;
20895
20931
  this._bounceCombine = PhysicsMaterialCombineMode.Average;
20896
20932
  this._frictionCombine = PhysicsMaterialCombineMode.Average;
20897
- this._nativeMaterial = Engine._nativePhysics.createPhysicsMaterial(this._staticFriction, this._dynamicFriction, this._bounciness, this._bounceCombine, this._frictionCombine);
20933
+ this._nativeMaterial = Engine._nativePhysics.createPhysicsMaterial(this._staticFriction, this._dynamicFriction, this._bounciness, this._frictionCombine, this._bounceCombine);
20898
20934
  }
20899
20935
  var _proto = PhysicsMaterial.prototype;
20900
20936
  /**
@@ -20903,6 +20939,21 @@ __decorate([
20903
20939
  !this._destroyed && this._nativeMaterial.destroy();
20904
20940
  this._destroyed = true;
20905
20941
  };
20942
+ /**
20943
+ * @internal
20944
+ */ _proto._cloneTo = function _cloneTo(target) {
20945
+ target._syncNative();
20946
+ };
20947
+ /**
20948
+ * @internal
20949
+ */ _proto._syncNative = function _syncNative() {
20950
+ var nativeMaterial = this._nativeMaterial;
20951
+ nativeMaterial.setStaticFriction(this._staticFriction);
20952
+ nativeMaterial.setDynamicFriction(this._dynamicFriction);
20953
+ nativeMaterial.setBounciness(this._bounciness);
20954
+ nativeMaterial.setFrictionCombine(this._frictionCombine);
20955
+ nativeMaterial.setBounceCombine(this._bounceCombine);
20956
+ };
20906
20957
  _create_class(PhysicsMaterial, [
20907
20958
  {
20908
20959
  key: "bounciness",
@@ -20977,6 +21028,9 @@ __decorate([
20977
21028
  ]);
20978
21029
  return PhysicsMaterial;
20979
21030
  }();
21031
+ __decorate([
21032
+ ignoreClone
21033
+ ], PhysicsMaterial.prototype, "_nativeMaterial", void 0);
20980
21034
 
20981
21035
  /**
20982
21036
  * Abstract class for collider shapes.
@@ -21029,6 +21083,16 @@ __decorate([
21029
21083
  };
21030
21084
  /**
21031
21085
  * @internal
21086
+ *
21087
+ * Called once per physics update tick by `Collider._onUpdate`. Base no-op.
21088
+ *
21089
+ * Subclasses can override for frame-driven maintenance. Currently used by
21090
+ * `MeshColliderShape` to retry native shape creation when mesh data becomes
21091
+ * accessible later or PhysX cooking previously failed due to transient state
21092
+ * (async resource loading, cook pipeline warmup, etc.).
21093
+ */ _proto._onPhysicsUpdate = function _onPhysicsUpdate() {};
21094
+ /**
21095
+ * @internal
21032
21096
  */ _proto._destroy = function _destroy() {
21033
21097
  if (this._nativeShape) {
21034
21098
  this._nativeShape.destroy();
@@ -21178,7 +21242,11 @@ __decorate([
21178
21242
  _inherits(MeshColliderShape, ColliderShape);
21179
21243
  function MeshColliderShape() {
21180
21244
  var _this;
21181
- _this = ColliderShape.apply(this, arguments) || this, _this._mesh = null, _this._isConvex = false, _this._positions = null, _this._indices = null, _this._cookingFlags = MeshColliderShapeCookingFlag.Cleaning | MeshColliderShapeCookingFlag.VertexWelding, _this._isShapeAttached = false;
21245
+ _this = ColliderShape.apply(this, arguments) || this, _this._mesh = null, _this._isConvex = false, _this._positions = null, _this._indices = null, _this._cookingFlags = MeshColliderShapeCookingFlag.Cleaning | MeshColliderShapeCookingFlag.VertexWelding, _this._isShapeAttached = false, /**
21246
+ * `true` if a native shape creation was attempted but failed (mesh data not yet
21247
+ * accessible, PhysX cooking transient failure, etc.). The `_onPhysicsUpdate` hook
21248
+ * will keep retrying every frame until creation succeeds.
21249
+ */ _this._pendingNativeShapeCreation = false;
21182
21250
  return _this;
21183
21251
  }
21184
21252
  var _proto = MeshColliderShape.prototype;
@@ -21262,9 +21330,12 @@ __decorate([
21262
21330
  }
21263
21331
  var nativeShape = Engine._nativePhysics.createMeshColliderShape(this._id, this._positions, this._indices, this._isConvex, this._material._nativeMaterial, this._cookingFlags);
21264
21332
  if (!nativeShape) {
21333
+ // Cook failed — `_onPhysicsUpdate` will retry next frame
21334
+ this._pendingNativeShapeCreation = true;
21265
21335
  return;
21266
21336
  }
21267
21337
  this._nativeShape = nativeShape;
21338
+ this._pendingNativeShapeCreation = false;
21268
21339
  // Sync base class properties (position, rotation, contactOffset, isTrigger, material)
21269
21340
  ColliderShape.prototype._syncNative.call(this);
21270
21341
  // If already attached to a collider, add the newly created native shape to it
@@ -21273,6 +21344,36 @@ __decorate([
21273
21344
  this._attachToCollider();
21274
21345
  }
21275
21346
  };
21347
+ /**
21348
+ * @internal
21349
+ * Retry hook: keep attempting `_createNativeShape` until it succeeds.
21350
+ *
21351
+ * Triggered every physics update tick by `Collider._onUpdate`. Handles the case
21352
+ * where `_cookMesh` fails on first attempt due to PhysX cooking pipeline timing
21353
+ * (the mesh data was extracted successfully at `set mesh` time, but the native
21354
+ * cook call returned null). No-op once a valid native shape exists.
21355
+ *
21356
+ * We DO NOT re-call `_extractMeshData` here — once `set mesh` finished, either:
21357
+ * - extraction succeeded → `_positions` is populated and we reuse it
21358
+ * - extraction failed → `_clearMeshData` cleared `_positions`, and `mesh.accessible`
21359
+ * won't recover (GPU upload is one-way), so re-extracting would fail again
21360
+ */ _proto._onPhysicsUpdate = function _onPhysicsUpdate() {
21361
+ if (!this._pendingNativeShapeCreation || !this._mesh || !this._positions) return;
21362
+ this._createNativeShape();
21363
+ };
21364
+ /**
21365
+ * @internal
21366
+ * After CloneManager deep-copies `_positions` / `_indices` / `_mesh` and remaps `_collider`,
21367
+ * the cloned shape still has no native PhysX shape because `_nativeShape` is `@ignoreClone`.
21368
+ * Cook a fresh native shape now using the already-cloned vertex/index buffers; on transient
21369
+ * cook failure `_createNativeShape` sets `_pendingNativeShapeCreation = true` and
21370
+ * `_onPhysicsUpdate` will retry next tick.
21371
+ */ _proto._cloneTo = function _cloneTo(target) {
21372
+ ColliderShape.prototype._cloneTo.call(this, target);
21373
+ if (target._positions) {
21374
+ target._createNativeShape();
21375
+ }
21376
+ };
21276
21377
  _create_class(MeshColliderShape, [
21277
21378
  {
21278
21379
  key: "cookingFlags",
@@ -21332,15 +21433,25 @@ __decorate([
21332
21433
  (_this__mesh = this._mesh) == null ? void 0 : _this__mesh._addReferCount(-1);
21333
21434
  value == null ? void 0 : value._addReferCount(1);
21334
21435
  this._mesh = value;
21335
- if (value && this._extractMeshData(value)) {
21336
- if (this._nativeShape) {
21337
- this._updateNativeShapeData();
21436
+ if (value) {
21437
+ if (this._extractMeshData(value)) {
21438
+ if (this._nativeShape) {
21439
+ this._updateNativeShapeData();
21440
+ } else {
21441
+ this._createNativeShape();
21442
+ }
21443
+ // _createNativeShape can fail silently (cookMesh transient failure); mark pending if so
21444
+ this._pendingNativeShapeCreation = !this._nativeShape;
21338
21445
  } else {
21339
- this._createNativeShape();
21446
+ // Mesh not yet accessible — keep pending so `_onPhysicsUpdate` retries later
21447
+ this._destroyNativeShape();
21448
+ this._clearMeshData();
21449
+ this._pendingNativeShapeCreation = true;
21340
21450
  }
21341
21451
  } else {
21342
21452
  this._destroyNativeShape();
21343
21453
  this._clearMeshData();
21454
+ this._pendingNativeShapeCreation = false;
21344
21455
  }
21345
21456
  }
21346
21457
  }
@@ -21385,6 +21496,27 @@ __decorate([
21385
21496
  */ _proto.applyTorque = function applyTorque(torque) {
21386
21497
  this._phasedActiveInScene && this._nativeCollider.addTorque(torque);
21387
21498
  };
21499
+ /**
21500
+ * Apply a force to the DynamicCollider at a given position in world space.
21501
+ * The force generates both linear acceleration through the center of mass and angular
21502
+ * acceleration about it (torque = (position - centerOfMass) × force).
21503
+ * @param force - The force to apply, in world space
21504
+ * @param position - The position where the force is applied, in world space
21505
+ */ _proto.applyForceAtPosition = function applyForceAtPosition(force, position) {
21506
+ if (!this._phasedActiveInScene) return;
21507
+ var nativeCollider = this._nativeCollider;
21508
+ var localCoM = DynamicCollider._tempVector3;
21509
+ nativeCollider.getCenterOfMass(localCoM);
21510
+ var transform = this.entity.transform;
21511
+ var worldCoM = DynamicCollider._tempVector3_1;
21512
+ engineMath.Vector3.transformByQuat(localCoM, transform.worldRotationQuaternion, worldCoM);
21513
+ worldCoM.add(transform.worldPosition);
21514
+ var torque = DynamicCollider._tempVector3_2;
21515
+ engineMath.Vector3.subtract(position, worldCoM, torque);
21516
+ engineMath.Vector3.cross(torque, force, torque);
21517
+ nativeCollider.addForce(force);
21518
+ nativeCollider.addTorque(torque);
21519
+ };
21388
21520
  _proto.move = function move(positionOrRotation, rotation) {
21389
21521
  if (!this._isKinematic) {
21390
21522
  console.warn("DynamicCollider: move() is only supported when isKinematic is true.");
@@ -21418,6 +21550,31 @@ __decorate([
21418
21550
  Collider.prototype.addShape.call(this, shape);
21419
21551
  };
21420
21552
  /**
21553
+ * Route per-frame entity → native transform sync to the correct physics API based
21554
+ * on kinematic state.
21555
+ *
21556
+ * PhysX 4.x docs (PxRigidDynamic):
21557
+ * "If you intend to move a kinematic actor with [setGlobalPose] and want
21558
+ * collision detection, use setKinematicTarget() instead."
21559
+ *
21560
+ * setGlobalPose is a teleport: PhysX skips contact detection between the old
21561
+ * and new pose, so two kinematic actors moved onto each other via entity.transform
21562
+ * mutation would NOT produce onCollisionEnter / onCollisionStay events even when
21563
+ * scene.kineKineFilteringMode = eKEEP. Routing the per-frame sync through
21564
+ * IDynamicCollider.move() (which the PhysX backend implements as
21565
+ * setKinematicTarget) tells PhysX the actor is animating to the target during the
21566
+ * next simulate(), enabling sweep contact detection for kine-kine and kine-dynamic
21567
+ * pairs alike.
21568
+ *
21569
+ * @internal
21570
+ */ _proto._syncEntityTransformToNative = function _syncEntityTransformToNative(worldPosition, worldRotation) {
21571
+ if (this._isKinematic) {
21572
+ this._nativeCollider.move(worldPosition, worldRotation);
21573
+ } else {
21574
+ Collider.prototype._syncEntityTransformToNative.call(this, worldPosition, worldRotation);
21575
+ }
21576
+ };
21577
+ /**
21421
21578
  * @internal
21422
21579
  */ _proto._onLateUpdate = function _onLateUpdate() {
21423
21580
  var transform = this.entity.transform;
@@ -21791,6 +21948,8 @@ __decorate([
21791
21948
  return DynamicCollider;
21792
21949
  }(exports.Collider);
21793
21950
  DynamicCollider._tempVector3 = new engineMath.Vector3();
21951
+ DynamicCollider._tempVector3_1 = new engineMath.Vector3();
21952
+ DynamicCollider._tempVector3_2 = new engineMath.Vector3();
21794
21953
  DynamicCollider._tempQuat = new engineMath.Quaternion();
21795
21954
  __decorate([
21796
21955
  ignoreClone