Phaser3结合Matterjs如何在函数外部访问Sprite属性
问题根源
MatterJS作为刚体物理引擎,和Arcade物理引擎的逻辑有本质区别:Matter默认会给所有刚体施加空气阻尼,同时会对长时间不受力的刚体触发睡眠机制来节省性能。你在create阶段或者非update时序里给刚体设置初始速度后,没有持续的速度输入,刚体会因为阻尼逐渐减速直到停止,甚至直接进入睡眠状态不再运动,这是引擎默认机制,不是代码逻辑错误。
你原有代码还存在两个容易触发报错的隐患:
- 定义
obstacle变量时未加let/const声明,变量会泄漏到全局作用域,很容易被其他逻辑覆盖,触发你遇到的Cannot read properties of undefined (reading 'setVelocityX')报错。 - 使用原生
setInterval做定时生成逻辑,不受Phaser游戏主时序控制,游戏切后台、暂停时定时器仍会运行,极易出现this指向错乱、对象生成时序不对的问题,应该替换为Phaser自带的时间事件API。
实现方案
根据需求二选一即可:
方案1:在update循环中统一设置组内障碍物速度(最稳定,推荐)
不需要在创建sprite时设置速度,直接在每帧update中遍历障碍物组统一赋值速度,完全规避刚体阻尼、睡眠带来的停止问题,也不需要单独维护每个sprite的引用。
首先修改create函数中的逻辑:
// create 函数内 this.obstacles = this.add.group(); const addObstacle = (x, y) => { // 用const声明局部变量,避免全局污染 const obstacle = this.matter.add.sprite(x, y, 'barrel').setScale(0.2); obstacle.setIgnoreGravity(true); // 标记障碍物类型,方便后续逻辑判断 obstacle.setData('type', 'obstacle'); this.obstacles.add(obstacle); // 创建时无需设置速度 } let space = 7; let vary = Phaser.Math.Between(800, 1000); // 替换原生setInterval为Phaser内置时间事件 this.time.addEvent({ delay: 5000, loop: true, callback: () => { for (let i = 0; i < 4; i++) { if (i != space && i != space + 1) { addObstacle(this.scale.width + 400, i * 60 + vary); } } // 每次生成后重新随机缺口位置,避免缺口固定 vary = Phaser.Math.Between(800, 1000); } });
然后在update函数中添加速度设置逻辑:
update() { // 遍历所有存活的障碍物 this.obstacles.getChildren().forEach(obstacle => { obstacle.setVelocityX(-30); // 可选:障碍物移出屏幕后自动销毁,避免内存占用过高 if (obstacle.x < -obstacle.displayWidth) { obstacle.destroy(); } }); }
这个方案完全遵循Phaser+Matter的运行时序,不会出现速度衰减、对象undefined的问题,稳定性最高。
方案2:修改刚体默认属性,单次设置速度即可持续运动
如果不想在update中写每帧逻辑,可以在创建刚体时关闭空气阻尼和自动睡眠机制,设置一次速度就可以让障碍物持续匀速运动:
const addObstacle = (x, y) => { const obstacle = this.matter.add.sprite(x, y, 'barrel', { friction: 0, frictionAir: 0, // 关闭空气阻尼,速度不会衰减 inertia: Infinity, // 禁止刚体碰撞后旋转 sleepThreshold: Infinity // 关闭自动睡眠,刚体不会停止运动 }).setScale(0.2); obstacle.setIgnoreGravity(true); this.obstacles.add(obstacle); obstacle.setVelocityX(-30); }
这个方案代码更简洁,但修改了刚体的物理参数,如果后续需要障碍物参与碰撞交互,可能会出现碰撞效果不符合预期的问题,适合纯装饰、无复杂交互的障碍场景。
内容的提问来源于stack exchange,提问作者Ace Enyioko
相关产品推荐
相关产品推荐

