用途:在 Decentraland 场景中用 @dcl/sdk/ecs 的 Physics API 对玩家角色施加物理力,所有操作仅影响本地玩家。
背景:玩家 Transform(engine.PlayerEntity)由引擎控制、场景代码只读。用 Transform.getMutable、Transform.createOrReplace 或直接改 position/rotation 都不会生效且不报错。要抬升、漂浮、推动、击退等请用 Physics API;瞬移或平滑滑向指定位置请用 ~system/RestrictedActions 的 movePlayerTo。
主要能力:
- 瞬时冲量:Physics.applyImpulseToPlayer(direction, magnitude?),同帧多次调用会累加,适合弹跳板、跳跃、爆炸。
- 击退:Physics.applyKnockbackToPlayer(sourcePos, magnitude, radius?, falloff?),方向由源点指向玩家自动计算;负 magnitude 为吸引。falloff 可选 CONSTANT(默认)、LINEAR、INVERSE_SQUARE,多数区域效果推荐 LINEAR。玩家正好站在源点时会被垂直向上推。
- 持续力:Physics.applyForceToPlayer(entity, direction, magnitude?) 施加,Physics.removeForceFromPlayer(entity) 移除;不同实体的力可叠加,适合风道、传送带、重力场。
- 定时力:Physics.applyForceToPlayerForDuration(entity, seconds, direction, magnitude?),到期自动失效。
- 斥力:Physics.applyRepulsionForceToPlayer(entity, position, magnitude, radius),每帧按距离重算,位置需显式传入,移除同上。
- 坐标转换:Transform.localToWorldDirection(entity, localDir) 将本地方向转为世界方向。
触发区碰撞层:Physics.* 只作用于本地玩家。用 TriggerArea 时,掩码决定哪些角色触发回调:CL_MAIN_PLAYER 只触发本地玩家;CL_PLAYER 只触发远端角色(不含本地);两者按位或则都触发;CL_PHYSICS 对任何角色都不触发。玩家物理触发区建议用 CL_MAIN_PLAYER,则无需再判断远端/本地。若用 CL_PLAYER | CL_MAIN_PLAYER,需以 result.trigger?.entity === engine.PlayerEntity 判断进入者(result.triggeredEntity 是触发区自身实体,无法用于区分)。
滑翔状态:滑翔伞打开时,持续力(applyForceToPlayer、applyForceToPlayerForDuration、applyRepulsionForceToPlayer)强度为 1.5 倍;持续力的向上分量可抬升滑翔中的玩家,glidingFallingSpeed 只限制下降速度;瞬时冲量与击退不受滑翔影响。
限制:移动端(Godot)客户端与 Unity 在玩家胶囊体、台阶偏移和地面接触上存在已知不一致,台阶高度和落点可能与桌面端不同,遍历几何体应留余量,精确平台跳跃需真机验证。更完整示例见 {baseDir}/references/physics-patterns.md。