diff --git a/cocos/physics-2d/box2d-jsb/joints/distance-joint.ts b/cocos/physics-2d/box2d-jsb/joints/distance-joint.ts index 593c1b5267..89025d2b33 100644 --- a/cocos/physics-2d/box2d-jsb/joints/distance-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/distance-joint.ts @@ -36,8 +36,10 @@ export class b2DistanceJoint extends b2Joint implements IDistanceJoint { _createJointDef (): any { const comp = this._jointComp as DistanceJoint2D; const def = new b2jsb.RopeJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.maxLength = comp.maxLength / PHYSICS_2D_PTM_RATIO; return def; } diff --git a/cocos/physics-2d/box2d-jsb/joints/fixed-joint.ts b/cocos/physics-2d/box2d-jsb/joints/fixed-joint.ts index 27dfc6d413..4d658f2208 100644 --- a/cocos/physics-2d/box2d-jsb/joints/fixed-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/fixed-joint.ts @@ -24,7 +24,6 @@ import { IFixedJoint } from '../../spec/i-physics-joint'; import { b2Joint } from './joint-2d'; import { FixedJoint2D } from '../../framework'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; export class b2FixedJoint extends b2Joint implements IFixedJoint { setFrequency (v: number): void { @@ -41,8 +40,10 @@ export class b2FixedJoint extends b2Joint implements IFixedJoint { _createJointDef (): any { const comp = this._jointComp as FixedJoint2D; const def = new b2jsb.WeldJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.referenceAngle = 0; def.frequencyHz = comp.frequency; def.dampingRatio = comp.dampingRatio; diff --git a/cocos/physics-2d/box2d-jsb/joints/hinge-joint.ts b/cocos/physics-2d/box2d-jsb/joints/hinge-joint.ts index 54a98e705c..210c1ca9ce 100644 --- a/cocos/physics-2d/box2d-jsb/joints/hinge-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/hinge-joint.ts @@ -25,7 +25,6 @@ import { IHingeJoint } from '../../spec/i-physics-joint'; import { HingeJoint2D } from '../../framework'; import { b2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; export class b2HingeJoint extends b2Joint implements IHingeJoint { @@ -67,8 +66,10 @@ export class b2HingeJoint extends b2Joint implements IHingeJoint { _createJointDef (): any { const comp = this._jointComp as HingeJoint2D; const def = new b2jsb.RevoluteJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.enableMotor = comp.enableMotor; def.maxMotorTorque = comp.maxMotorTorque; diff --git a/cocos/physics-2d/box2d-jsb/joints/joint-2d.ts b/cocos/physics-2d/box2d-jsb/joints/joint-2d.ts index 662196e78e..9d025518eb 100644 --- a/cocos/physics-2d/box2d-jsb/joints/joint-2d.ts +++ b/cocos/physics-2d/box2d-jsb/joints/joint-2d.ts @@ -24,6 +24,10 @@ import { IJoint2D } from '../../spec/i-physics-joint'; import { Joint2D, PhysicsSystem2D, RigidBody2D } from '../../framework'; import { b2PhysicsWorld } from '../physics-world'; +import { Vec2 } from '../../../core'; + +const tempAnchorA = new Vec2(); +const tempAnchorB = new Vec2(); export class b2Joint implements IJoint2D { get impl (): b2jsb.Joint | null { @@ -117,6 +121,14 @@ export class b2Joint implements IJoint2D { return null; } + protected _getAnchorA (): Vec2 { + return this._jointComp!._getAnchorA(tempAnchorA); + } + + protected _getAnchorB (): Vec2 { + return this._jointComp!._getAnchorB(tempAnchorB); + } + isValid (): Joint2D | null { return this._b2joint && this._body && this._body.impl && this._jointComp; } diff --git a/cocos/physics-2d/box2d-jsb/joints/slider-joint.ts b/cocos/physics-2d/box2d-jsb/joints/slider-joint.ts index 1341e3831a..e802f537b0 100644 --- a/cocos/physics-2d/box2d-jsb/joints/slider-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/slider-joint.ts @@ -67,8 +67,10 @@ export class b2SliderJoint extends b2Joint implements ISliderJoint { _createJointDef (): any { const comp = this._jointComp as SliderJoint2D; const def = new b2jsb.PrismaticJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; const angle = toRadian(comp.angle); def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; def.referenceAngle = 0; diff --git a/cocos/physics-2d/box2d-jsb/joints/spring-joint.ts b/cocos/physics-2d/box2d-jsb/joints/spring-joint.ts index 8246a7e2fd..3a2d4506f3 100644 --- a/cocos/physics-2d/box2d-jsb/joints/spring-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/spring-joint.ts @@ -46,8 +46,10 @@ export class b2SpringJoint extends b2Joint implements ISpringJoint { _createJointDef (): any { const comp = this._jointComp as SpringJoint2D; const def = new b2jsb.DistanceJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.length = comp.distance / PHYSICS_2D_PTM_RATIO; def.dampingRatio = comp.dampingRatio; def.frequencyHz = comp.frequency; diff --git a/cocos/physics-2d/box2d-jsb/joints/wheel-joint.ts b/cocos/physics-2d/box2d-jsb/joints/wheel-joint.ts index 6746c4639a..30baa6ce09 100644 --- a/cocos/physics-2d/box2d-jsb/joints/wheel-joint.ts +++ b/cocos/physics-2d/box2d-jsb/joints/wheel-joint.ts @@ -24,7 +24,6 @@ import { IWheelJoint } from '../../spec/i-physics-joint'; import { WheelJoint2D } from '../../framework'; import { b2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; export class b2WheelJoint extends b2Joint implements IWheelJoint { @@ -59,8 +58,10 @@ export class b2WheelJoint extends b2Joint implements IWheelJoint { _createJointDef (): any { const comp = this._jointComp as WheelJoint2D; const def = new b2jsb.WheelJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; const angle = toRadian(comp.angle); def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; def.maxMotorTorque = comp.maxMotorTorque; diff --git a/cocos/physics-2d/box2d-jsb/rigid-body.ts b/cocos/physics-2d/box2d-jsb/rigid-body.ts index b5139d3b01..49336f9581 100644 --- a/cocos/physics-2d/box2d-jsb/rigid-body.ts +++ b/cocos/physics-2d/box2d-jsb/rigid-body.ts @@ -30,7 +30,7 @@ import { Vec2, toRadian, Vec3, Quat, IVec2Like, TWO_PI, HALF_PI } from '../../co import { PHYSICS_2D_PTM_RATIO, ERigidBody2DType } from '../framework/physics-types'; import { Node } from '../../scene-graph/node'; -import { Collider2D } from '../framework'; +import { Collider2D, Joint2D } from '../framework'; const tempVec3 = new Vec3(); @@ -90,6 +90,7 @@ export class b2RigidBody2D implements IRigidBody2D { for (let i = 0; i < colliders.length; i++) { colliders[i].apply(); } + Joint2D._applyScale(this.rigidBody); } const bodyType = this._rigidBody.type; diff --git a/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts b/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts index ed078ad583..9ec72b1a5e 100644 --- a/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts @@ -39,8 +39,10 @@ export class B2DistanceJoint extends B2Joint implements IDistanceJoint { _createJointDef (): any { const comp = this._jointComp as DistanceJoint2D; const def = new B2.RopeJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.maxLength = comp.maxLength / PHYSICS_2D_PTM_RATIO; return def; } diff --git a/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts b/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts index 2a0425ba18..6bde077d21 100644 --- a/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts @@ -26,7 +26,6 @@ import { B2 } from '../instantiated'; import { IFixedJoint } from '../../spec/i-physics-joint'; import { B2Joint } from './joint-2d'; import { FixedJoint2D } from '../../framework'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; /** @mangle */ export class B2FixedJoint extends B2Joint implements IFixedJoint { @@ -44,8 +43,10 @@ export class B2FixedJoint extends B2Joint implements IFixedJoint { _createJointDef (): any { const comp = this._jointComp as FixedJoint2D; const def = new B2.WeldJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.referenceAngle = 0; def.dampingRatio = comp.dampingRatio; def.frequencyHz = comp.frequency; diff --git a/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts b/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts index 7f157f1c7e..7b19c0467a 100644 --- a/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts @@ -26,7 +26,6 @@ import { B2 } from '../instantiated'; import { IHingeJoint } from '../../spec/i-physics-joint'; import { HingeJoint2D } from '../../framework'; import { B2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; /** @mangle */ @@ -69,8 +68,10 @@ export class B2HingeJoint extends B2Joint implements IHingeJoint { _createJointDef (): any { const comp = this._jointComp as HingeJoint2D; const def = new B2.RevoluteJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.enableMotor = comp.enableMotor; def.maxMotorTorque = comp.maxMotorTorque; diff --git a/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts index 62ac98f28d..b733a63953 100644 --- a/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts +++ b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts @@ -26,7 +26,10 @@ import { B2, B2ObjectType, addImplPtrReference, addImplPtrReferenceWASM, getImpl import { IJoint2D } from '../../spec/i-physics-joint'; import { Joint2D, PhysicsSystem2D, RigidBody2D } from '../../framework'; import { B2PhysicsWorld } from '../physics-world'; -import { warn } from '../../../core'; +import { Vec2, warn } from '../../../core'; + +const tempAnchorA = new Vec2(); +const tempAnchorB = new Vec2(); /** @mangle */ export class B2Joint implements IJoint2D { @@ -127,6 +130,14 @@ export class B2Joint implements IJoint2D { return null; } + protected _getAnchorA (): Vec2 { + return this._jointComp!._getAnchorA(tempAnchorA); + } + + protected _getAnchorB (): Vec2 { + return this._jointComp!._getAnchorB(tempAnchorB); + } + isValid (): Joint2D | null { return this._b2joint && this._body && this._body.impl && this._jointComp; } diff --git a/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts b/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts index e37a2b31ae..3e769a88ba 100644 --- a/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts @@ -70,8 +70,10 @@ export class B2SliderJoint extends B2Joint implements ISliderJoint { _createJointDef (): any { const comp = this._jointComp as SliderJoint2D; const def = new B2.PrismaticJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; const angle = toRadian(comp.angle); def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; def.referenceAngle = 0; diff --git a/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts b/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts index 830599c068..537b44ae8e 100644 --- a/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts @@ -51,8 +51,10 @@ export class B2SpringJoint extends B2Joint implements ISpringJoint { _createJointDef (): any { const comp = this._jointComp as SpringJoint2D; const def = new B2.DistanceJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; def.length = comp.distance / PHYSICS_2D_PTM_RATIO; def.dampingRatio = comp.dampingRatio; def.frequencyHz = comp.frequency; diff --git a/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts b/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts index 0ff5bfb2d8..0a9e5556ce 100644 --- a/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts +++ b/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts @@ -26,7 +26,6 @@ import { B2 } from '../instantiated'; import { IWheelJoint } from '../../spec/i-physics-joint'; import { WheelJoint2D } from '../../framework'; import { B2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; /** @mangle */ @@ -62,8 +61,10 @@ export class B2WheelJoint extends B2Joint implements IWheelJoint { _createJointDef (): any { const comp = this._jointComp as WheelJoint2D; const def = new B2.WheelJointDef(); - def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; - def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA = { x: anchorA.x, y: anchorA.y }; + def.localAnchorB = { x: anchorB.x, y: anchorB.y }; const angle = toRadian(comp.angle); def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; def.maxMotorTorque = comp.maxMotorTorque; diff --git a/cocos/physics-2d/box2d-wasm/rigid-body.ts b/cocos/physics-2d/box2d-wasm/rigid-body.ts index 505ef2abd7..487eaff82d 100644 --- a/cocos/physics-2d/box2d-wasm/rigid-body.ts +++ b/cocos/physics-2d/box2d-wasm/rigid-body.ts @@ -32,7 +32,7 @@ import { Vec2, toRadian, Vec3, Quat, IVec2Like, TWO_PI, HALF_PI, warn } from '.. import { PHYSICS_2D_PTM_RATIO, ERigidBody2DType } from '../framework/physics-types'; import { Node } from '../../scene-graph/node'; -import { Collider2D } from '../framework'; +import { Collider2D, Joint2D } from '../framework'; import { B2Shape2D } from './shapes/shape-2d'; import { B2Joint } from './joints/joint-2d'; @@ -95,6 +95,7 @@ export class B2RigidBody2D implements IRigidBody2D { for (let i = 0; i < colliders.length; i++) { colliders[i].apply(); } + Joint2D._applyScale(this.rigidBody); } if (type & Node.TransformBit.POSITION) { this.syncPositionToPhysics(true); diff --git a/cocos/physics-2d/box2d/joints/distance-joint.ts b/cocos/physics-2d/box2d/joints/distance-joint.ts index 41f7fc78c5..f937d87684 100644 --- a/cocos/physics-2d/box2d/joints/distance-joint.ts +++ b/cocos/physics-2d/box2d/joints/distance-joint.ts @@ -39,8 +39,10 @@ export class b2DistanceJoint extends b2Joint implements IDistanceJoint { _createJointDef (): any { const comp = this._jointComp as DistanceJoint2D; const def = new b2.RopeJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); def.maxLength = comp.maxLength / PHYSICS_2D_PTM_RATIO; return def; } diff --git a/cocos/physics-2d/box2d/joints/fixed-joint.ts b/cocos/physics-2d/box2d/joints/fixed-joint.ts index 3d4d9c7f59..bc57974d40 100644 --- a/cocos/physics-2d/box2d/joints/fixed-joint.ts +++ b/cocos/physics-2d/box2d/joints/fixed-joint.ts @@ -26,7 +26,6 @@ import b2 from '@cocos/box2d'; import { IFixedJoint } from '../../spec/i-physics-joint'; import { b2Joint } from './joint-2d'; import { FixedJoint2D } from '../../framework'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; /** @mangle */ export class b2FixedJoint extends b2Joint implements IFixedJoint { @@ -44,8 +43,10 @@ export class b2FixedJoint extends b2Joint implements IFixedJoint { _createJointDef (): any { const comp = this._jointComp as FixedJoint2D; const def = new b2.WeldJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); def.referenceAngle = 0; def.frequencyHz = comp.frequency; def.dampingRatio = comp.dampingRatio; diff --git a/cocos/physics-2d/box2d/joints/hinge-joint.ts b/cocos/physics-2d/box2d/joints/hinge-joint.ts index b834b07579..2958ba9c2b 100644 --- a/cocos/physics-2d/box2d/joints/hinge-joint.ts +++ b/cocos/physics-2d/box2d/joints/hinge-joint.ts @@ -26,7 +26,6 @@ import b2 from '@cocos/box2d'; import { IHingeJoint } from '../../spec/i-physics-joint'; import { HingeJoint2D } from '../../framework'; import { b2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; /** @mangle */ @@ -69,8 +68,10 @@ export class b2HingeJoint extends b2Joint implements IHingeJoint { _createJointDef (): any { const comp = this._jointComp as HingeJoint2D; const def = new b2.RevoluteJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); def.enableMotor = comp.enableMotor; def.maxMotorTorque = comp.maxMotorTorque; diff --git a/cocos/physics-2d/box2d/joints/joint-2d.ts b/cocos/physics-2d/box2d/joints/joint-2d.ts index 987bfd87d2..fac1b26c20 100644 --- a/cocos/physics-2d/box2d/joints/joint-2d.ts +++ b/cocos/physics-2d/box2d/joints/joint-2d.ts @@ -26,6 +26,10 @@ import b2 from '@cocos/box2d'; import { IJoint2D } from '../../spec/i-physics-joint'; import { Joint2D, PhysicsSystem2D, RigidBody2D } from '../../framework'; import { b2PhysicsWorld } from '../physics-world'; +import { Vec2 } from '../../../core'; + +const tempAnchorA = new Vec2(); +const tempAnchorB = new Vec2(); /** @mangle */ export class b2Joint implements IJoint2D { @@ -118,6 +122,14 @@ export class b2Joint implements IJoint2D { return null; } + protected _getAnchorA (): Vec2 { + return this._jointComp!._getAnchorA(tempAnchorA); + } + + protected _getAnchorB (): Vec2 { + return this._jointComp!._getAnchorB(tempAnchorB); + } + isValid (): Joint2D | null { return this._b2joint && this._body && this._body.impl && this._jointComp; } diff --git a/cocos/physics-2d/box2d/joints/slider-joint.ts b/cocos/physics-2d/box2d/joints/slider-joint.ts index 45f59d747a..1578d31a9f 100644 --- a/cocos/physics-2d/box2d/joints/slider-joint.ts +++ b/cocos/physics-2d/box2d/joints/slider-joint.ts @@ -70,8 +70,10 @@ export class b2SliderJoint extends b2Joint implements ISliderJoint { _createJointDef (): any { const comp = this._jointComp as SliderJoint2D; const def = new b2.PrismaticJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); const angle = toRadian(comp.angle); def.localAxisA.Set(Math.cos(angle), Math.sin(angle)); def.referenceAngle = 0; diff --git a/cocos/physics-2d/box2d/joints/spring-joint.ts b/cocos/physics-2d/box2d/joints/spring-joint.ts index c5b55d4510..a2d9da58d7 100644 --- a/cocos/physics-2d/box2d/joints/spring-joint.ts +++ b/cocos/physics-2d/box2d/joints/spring-joint.ts @@ -49,8 +49,10 @@ export class b2SpringJoint extends b2Joint implements ISpringJoint { _createJointDef (): any { const comp = this._jointComp as SpringJoint2D; const def = new b2.DistanceJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); def.length = comp.distance / PHYSICS_2D_PTM_RATIO; def.dampingRatio = comp.dampingRatio; def.frequencyHz = comp.frequency; diff --git a/cocos/physics-2d/box2d/joints/wheel-joint.ts b/cocos/physics-2d/box2d/joints/wheel-joint.ts index d4608449c7..316526ff40 100644 --- a/cocos/physics-2d/box2d/joints/wheel-joint.ts +++ b/cocos/physics-2d/box2d/joints/wheel-joint.ts @@ -26,7 +26,6 @@ import b2 from '@cocos/box2d'; import { IWheelJoint } from '../../spec/i-physics-joint'; import { WheelJoint2D } from '../../framework'; import { b2Joint } from './joint-2d'; -import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; import { toRadian } from '../../../core'; /** @mangle */ @@ -62,8 +61,10 @@ export class b2WheelJoint extends b2Joint implements IWheelJoint { _createJointDef (): any { const comp = this._jointComp as WheelJoint2D; const def = new b2.WheelJointDef(); - def.localAnchorA.Set(comp.anchor.x / PHYSICS_2D_PTM_RATIO, comp.anchor.y / PHYSICS_2D_PTM_RATIO); - def.localAnchorB.Set(comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO); + const anchorA = this._getAnchorA(); + const anchorB = this._getAnchorB(); + def.localAnchorA.Set(anchorA.x, anchorA.y); + def.localAnchorB.Set(anchorB.x, anchorB.y); const angle = toRadian(comp.angle); def.localAxisA.Set(Math.cos(angle), Math.sin(angle)); // def.localAxisA.Set(0, 1); diff --git a/cocos/physics-2d/box2d/rigid-body.ts b/cocos/physics-2d/box2d/rigid-body.ts index f64cdd6c6d..7f7755bd16 100644 --- a/cocos/physics-2d/box2d/rigid-body.ts +++ b/cocos/physics-2d/box2d/rigid-body.ts @@ -32,7 +32,7 @@ import { Vec2, toRadian, Vec3, Quat, IVec2Like, TWO_PI, HALF_PI, warn } from '.. import { PHYSICS_2D_PTM_RATIO, ERigidBody2DType } from '../framework/physics-types'; import { Node } from '../../scene-graph/node'; -import { Collider2D } from '../framework'; +import { Collider2D, Joint2D } from '../framework'; import { TransformBit } from '../../scene-graph/node-enum'; const tempVec3 = new Vec3(); @@ -94,6 +94,7 @@ export class b2RigidBody2D implements IRigidBody2D { for (let i = 0; i < colliders.length; i++) { colliders[i].apply(); } + Joint2D._applyScale(this.rigidBody); } if (type & Node.TransformBit.POSITION) { this.syncPositionToPhysics(true); diff --git a/cocos/physics-2d/framework/components/joints/joint-2d.ts b/cocos/physics-2d/framework/components/joints/joint-2d.ts index f4a7211874..daf87469e3 100644 --- a/cocos/physics-2d/framework/components/joints/joint-2d.ts +++ b/cocos/physics-2d/framework/components/joints/joint-2d.ts @@ -26,7 +26,7 @@ import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { Vec2, _decorator, tooltip, serializable } from '../../../../core'; import { RigidBody2D } from '../rigid-body-2d'; import { IJoint2D } from '../../../spec/i-physics-joint'; -import { EJoint2DType } from '../../physics-types'; +import { EJoint2DType, PHYSICS_2D_PTM_RATIO } from '../../physics-types'; import { createJoint } from '../../physics-selector'; import { Component } from '../../../../scene-graph'; @@ -34,6 +34,14 @@ const { ccclass, type } = _decorator; @ccclass('cc.Joint2D') export class Joint2D extends Component { + /** + * @en + * All registered 2D joints. + * @zh + * 所有已注册的 2D 关节。 + */ + static readonly joints: Joint2D[] = []; + /** * @en * The position of Joint2D in the attached rigid body's local space. @@ -75,6 +83,42 @@ export class Joint2D extends Component { @tooltip('i18n:physics2d.joint.connectedBody') connectedBody: RigidBody2D | null = null; + /** + * @en + * Gets the attached body's anchor after node scale is applied, in Box2D local units. + * @zh + * 获取自身刚体锚点。返回值已经按节点世界缩放换算,并转换为 Box2D 使用的物理单位。 + * @param out @en Optional output vector. A new Vec2 is created when it is not provided. @zh 可选,输出向量。未传入时会创建新的 Vec2。 + * @returns @en The scaled local anchor in Box2D units. @zh 已缩放并转换为物理单位的本地锚点。 + * @engineInternal + * @mangle + */ + _getAnchorA (out: Vec2 = new Vec2()): Vec2 { + const scale = this.node.worldScale; + out.x = this.anchor.x * scale.x / PHYSICS_2D_PTM_RATIO; + out.y = this.anchor.y * scale.y / PHYSICS_2D_PTM_RATIO; + return out; + } + + /** + * @en + * Gets the connected body's anchor after node scale is applied, in Box2D local units. + * @zh + * 获取连接刚体锚点。连接刚体为空时保持世界原点静态刚体语义,不应用节点缩放;返回值会转换为 Box2D 物理单位。 + * @param out @en Optional output vector. A new Vec2 is created when it is not provided. @zh 可选,输出向量。未传入时会创建新的 Vec2。 + * @returns @en The scaled connected local anchor in Box2D units. @zh 已缩放并转换为物理单位的连接锚点。 + * @engineInternal + * @mangle + */ + _getAnchorB (out: Vec2 = new Vec2()): Vec2 { + const body = this.connectedBody; + const node = body && body.isValid ? body.node : null; + const scale = node ? node.worldScale : null; + out.x = this.connectedAnchor.x * (scale ? scale.x : 1) / PHYSICS_2D_PTM_RATIO; + out.y = this.connectedAnchor.y * (scale ? scale.y : 1) / PHYSICS_2D_PTM_RATIO; + return out; + } + /** * @en * the Joint2D attached rigid-body. @@ -100,12 +144,36 @@ export class Joint2D extends Component { */ TYPE = EJoint2DType.None; + /** + * @en + * Rebuilds all joints whose anchors may be affected by the rigid body's scale. + * @zh + * 重建所有会受指定刚体缩放影响的关节。 + * @param body @en The scaled rigid body. @zh 发生缩放变化的刚体。 + * @engineInternal + * @mangle + */ + static _applyScale (body: RigidBody2D): void { + const joints = Joint2D.joints; + for (let i = 0; i < joints.length; i++) { + const joint = joints[i]; + if (!joint.isValid || (joint.connectedBody && !joint.connectedBody.isValid)) { + continue; + } + const selfBody = joint._body || joint.getComponent(RigidBody2D); + if (selfBody === body || joint.connectedBody === body) { + joint.apply(); + } + } + } + protected override onLoad (): void { if (!EDITOR_NOT_IN_PREVIEW) { this._joint = createJoint(this.TYPE); this._joint.initialize(this); this._body = this.getComponent(RigidBody2D); + Joint2D.joints.push(this); } } @@ -128,6 +196,10 @@ export class Joint2D extends Component { } protected override onDestroy (): void { + const i = Joint2D.joints.indexOf(this); + if (i >= 0) { + Joint2D.joints.splice(i, 1); + } if (this._joint && this._joint.onDestroy) { this._joint.onDestroy(); } diff --git a/tests/physics2d/joint.ts b/tests/physics2d/joint.ts new file mode 100644 index 0000000000..869c8f5d7f --- /dev/null +++ b/tests/physics2d/joint.ts @@ -0,0 +1,117 @@ +import { Vec2, Vec3 } from "../../cocos/core"; +import { director } from "../../cocos/game"; +import { Node } from "../../cocos/scene-graph"; +import * as physics2d from "../../exports/physics-2d-framework"; + +const ANCHOR_A = new Vec2(3, 4); +const ANCHOR_B = new Vec2(-2, 5); +const SCALE_A = new Vec3(2, 3, 1); +const SCALE_B = new Vec3(4, 5, 1); +const POSITION_A = new Vec3(10, 20, 0); +const POSITION_B = new Vec3(50, -30, 0); +const ANCHOR_EPSILON = 1e-3; + +const JOINT_TYPES = [ + physics2d.DistanceJoint2D, + physics2d.SpringJoint2D, + physics2d.FixedJoint2D, + physics2d.SliderJoint2D, + physics2d.WheelJoint2D, + physics2d.HingeJoint2D, +]; + +function expectVec2Close (actual: Vec2, expected: Vec2): void { + expect(Math.abs(actual.x - expected.x)).toBeLessThan(ANCHOR_EPSILON); + expect(Math.abs(actual.y - expected.y)).toBeLessThan(ANCHOR_EPSILON); +} + +function readJointAnchor (joint: physics2d.Joint2D, method: 'GetAnchorA' | 'GetAnchorB'): Vec2 { + const impl = joint.impl!.impl; + const out = { x: 0, y: 0 }; + const methodFunc = impl[method]; + const result = methodFunc.length === 0 ? methodFunc.call(impl) : methodFunc.call(impl, out) || out; + return new Vec2( + result.x * physics2d.PHYSICS_2D_PTM_RATIO, + result.y * physics2d.PHYSICS_2D_PTM_RATIO, + ); +} + +function createJoint ( + parent: Node, + jointCtor: new () => Joint, + scaleA = SCALE_A, + scaleB = SCALE_B, +): { nodeA: Node, nodeB: Node, joint: Joint } { + const nodeA = new Node('JointBodyA'); + const nodeB = new Node('JointBodyB'); + parent.addChild(nodeA); + parent.addChild(nodeB); + + nodeA.worldPosition = POSITION_A; + nodeB.worldPosition = POSITION_B; + nodeA.setScale(scaleA); + nodeB.setScale(scaleB); + + const bodyA = nodeA.addComponent(physics2d.RigidBody2D); + const bodyB = nodeB.addComponent(physics2d.RigidBody2D); + bodyA.type = physics2d.ERigidBody2DType.Kinematic; + bodyB.type = physics2d.ERigidBody2DType.Kinematic; + + const joint = nodeA.addComponent(jointCtor); + joint.connectedBody = bodyB; + joint.anchor.set(ANCHOR_A); + joint.connectedAnchor.set(ANCHOR_B); + joint.apply(); + + return { nodeA, nodeB, joint }; +} + +function getExpectedAnchorA (node: Node): Vec2 { + const scale = node.worldScale; + const position = node.worldPosition; + return new Vec2(position.x + ANCHOR_A.x * scale.x, position.y + ANCHOR_A.y * scale.y); +} + +function getExpectedAnchorB (node: Node): Vec2 { + const scale = node.worldScale; + const position = node.worldPosition; + return new Vec2(position.x + ANCHOR_B.x * scale.x, position.y + ANCHOR_B.y * scale.y); +} + +/** + * This function is used to test the api of the Joint2D. + */ +export default function (parent: Node, _steps = 0): void { + //skip builtin for now + if (physics2d.selector.id === 'builtin') { + return; + } + + // 各类关节创建时应使用缩放后的本地锚点。 + for (let i = 0; i < JOINT_TYPES.length; i++) { + const { nodeA, nodeB, joint } = createJoint(parent, JOINT_TYPES[i]); + expectVec2Close(readJointAnchor(joint, 'GetAnchorA'), getExpectedAnchorA(nodeA)); + expectVec2Close(readJointAnchor(joint, 'GetAnchorB'), getExpectedAnchorB(nodeB)); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + + // 运行时缩放自身或连接刚体后,应重建关节并刷新锚点。 + { + const { nodeA, nodeB, joint } = createJoint(parent, physics2d.HingeJoint2D, Vec3.ONE, Vec3.ONE); + expectVec2Close(readJointAnchor(joint, 'GetAnchorA'), getExpectedAnchorA(nodeA)); + expectVec2Close(readJointAnchor(joint, 'GetAnchorB'), getExpectedAnchorB(nodeB)); + + nodeA.setScale(SCALE_A); + director.tick(physics2d.PhysicsSystem2D.instance.fixedTimeStep); + expectVec2Close(readJointAnchor(joint, 'GetAnchorA'), getExpectedAnchorA(nodeA)); + + nodeB.setScale(SCALE_B); + director.tick(physics2d.PhysicsSystem2D.instance.fixedTimeStep); + expectVec2Close(readJointAnchor(joint, 'GetAnchorB'), getExpectedAnchorB(nodeB)); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } +} diff --git a/tests/physics2d/physics2d.test.ts b/tests/physics2d/physics2d.test.ts index 90d6414f6a..86ad0ef248 100644 --- a/tests/physics2d/physics2d.test.ts +++ b/tests/physics2d/physics2d.test.ts @@ -10,6 +10,7 @@ import { waitForBox2dWasmInstantiation } from "../../cocos/physics-2d/box2d-wasm import RigidBodyTest from "./rigid-body"; import ColliderTest from "./collider"; +import JointTest from "./joint"; import SceneQueryTest from "./scene-query"; import EventTest from "./events"; @@ -44,6 +45,9 @@ for (const id in physics2d.selector.backend) { //test collider ColliderTest(temp0); + //test joint + JointTest(temp0); + //test scene query SceneQueryTest(temp0); @@ -56,4 +60,4 @@ for (const id in physics2d.selector.backend) { // all works done done(); }) -} \ No newline at end of file +}