You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AS3如何解决碰撞物体数秒后穿透碰撞体继续下落的问题

问题原因
  • 实例属性访问错误:yVel是Enemy类的实例成员,原代码中Class(Enemy).yVel = 0是对类的静态属性赋值,完全不会修改当前enemy实例的yVel值。重力会持续累加yVel,当数值大到单帧位移超过碰撞修正的阈值时,enemy就会直接穿透ground,这就是2-6秒后才出现异常的核心原因。
  • 事件执行顺序冲突:Enemy类内部和主时间轴都绑定了enterFrame事件,两者执行顺序没有固定优先级,如果先执行碰撞修正再执行Enemy的位移逻辑,碰撞修正后的坐标会被直接覆盖。
  • 位移逻辑错误:Enemy类的onEnterFrame中直接写this.x = xVel、this.y = yVel,错误将速度值当做坐标值使用,你在主时间轴设置的初始x=400也会被直接覆盖为0。
  • 碰撞修正逻辑冗余:每次碰撞仅将y减少0.1的处理效率极低,yVel过大时根本抵消不了单帧的位移量。
修正代码

主时间轴代码

stop();
// 请将下方赋值替换为你舞台上ground元件的实例名
var ground: MovieClip = stage.getChildByName("ground") as MovieClip;

var enemy:Enemy = new Enemy();
stage.addChild(enemy);
enemy.x = 400;
enemy.y = 150;
enemy.rotation = 0;

enemy.addEventListener("enterFrame", collisions);
function collisions(e: Event): void {
    var collision: Boolean = ground.hitTestObject(enemy);
    if (collision) {
        // 此处默认两个元件的注册点为中心,若注册点在左上角请改为 enemy.y = ground.y - enemy.height
        enemy.y = ground.y - enemy.height/2;
        // 直接修改实例的yVel属性
        enemy.yVel = 0;
    }
}

Enemy类代码

package  {
    import flash.display.MovieClip;
    import flash.events.Event;
    public class Enemy extends MovieClip {
        // 设为public允许外部访问属性
        public var xVel: int = 0;
        public var yVel: int = 0;
        
        public function Enemy() {
            addEventListener("enterFrame", onEnterFrame);
        }
        
        private function onEnterFrame(e: Event): void {
            yVel += 2;
            // 速度叠加到当前坐标,而非直接赋值坐标
            this.x += xVel;
            this.y += yVel;
        }
    }
}
额外优化建议

如果要彻底避免enterFrame执行顺序的问题,可以直接将碰撞检测逻辑写到Enemy类的onEnterFrame方法中,执行位移后马上做碰撞修正,逻辑会更稳定。

内容的提问来源于stack exchange,提问作者Alex Smart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 19:06:03