kinematic与static刚体不会触发任何接触回调

本文介绍使用Box2D物理引擎创建不同类型的物体并设置碰撞回调的方法。通过实例演示了如何创建静态、动态和运动体,并实现碰撞开始、结束等事件的监听。

Main.as

package{
    import Box2D.Common.Math.b2Vec2;
    import Box2D.Dynamics.b2Body;
    import Box2D.Dynamics.Contacts.b2Contact;
    import Box2D.Collision.b2Manifold;
    import Box2D.Dynamics.b2ContactImpulse;
    
    public class Main extends BaseMain{
        
        
        public function Main(){
            super(new b2Vec2(0,0));
        }
        
        
        override protected function init():void{
            UIManager.getInstance().init(this);
            
            var boxA:b2Body=createBox(30,30,50,300);
            var circle:b2Body=createCircle(15,50,400);
            var boxB:b2Body=createBox(50,200,700,300);
            boxA.SetUserData({type:"boxA"});
            circle.SetUserData({type:"circle"});
            boxB.SetUserData({type:"boxB"});
            
            boxB.SetType(b2Body.b2_staticBody);
            
            boxA.SetType(b2Body.b2_kinematicBody);
            boxA.SetLinearVelocity(new b2Vec2(10,0));
            boxA.SetPreSolveCallback(preSolve);
            boxA.SetContactBeginCallback(contactBegin);
            boxA.SetContactEndCallback(contactEnd);
            boxA.SetPostSolveCallback(postSolve);
            
            circle.SetType(b2Body.b2_dynamicBody);
            circle.SetLinearVelocity(new b2Vec2(5,0));
            circle.SetPreSolveCallback(preSolve);
            circle.SetContactBeginCallback(contactBegin);
            circle.SetContactEndCallback(contactEnd);
            circle.SetPostSolveCallback(postSolve);
        }
        
        private function contactBegin(contact:b2Contact,other:b2Body):void{
            UIManager.getInstance().print("contactBegin:"+other.GetUserData().type);
        }
        
        private function contactEnd(contact:b2Contact,other:b2Body):void{
            UIManager.getInstance().print("contactEnd:"+other.GetUserData().type);
        }
        
        private function postSolve(contact:b2Contact,impulse:b2ContactImpulse,other:b2Body):void{
            UIManager.getInstance().print("postSolve:"+other.GetUserData().type);
        }
        
        private function preSolve(contact:b2Contact,oldManifold:b2Manifold,other:b2Body):void{
            UIManager.getInstance().print("preSolve:"+other.GetUserData().type);
            
        }
        
        override protected function stepBefore():void{ 
            
        }
        
        
    };
}

示例:

源码下载:链接:http://pan.baidu.com/s/1bpL8chh 密码:qui7

转载于:https://www.cnblogs.com/kingBook/p/6834574.html

在 Cocos Creator 3.x 中使用 **Kinematic 刚体**实现拖动物体时,物体可能会出现穿透其他物理对象的问题。这是由于 Kinematic 刚体不会自动参物理引擎的碰撞响应计算,仅通过代码直接设置其位置可能导致其他刚体发生穿透[^1]。 为了解决这一问题,可以采用以下几种方法: ### 1. 使用 Mouse Joint 实现自然拖动 相比直接修改 Kinematic 刚体的位置,使用 **Mouse Joint** 是一种更符合物理引擎设计逻辑的方式。它允许物理引擎根据力约束条件自动处理物体的移动,从而避免穿透现象。 ```typescript // 创建并配置 Mouse Joint const mouseJoint = new MouseJoint(); mouseJoint.bodyA = groundBody; // 场景中的静态刚体 mouseJoint.bodyB = draggedBody; mouseJoint.target = new Vec2(mouseWorldPosition.x, mouseWorldPosition.y); mouseJoint.maxForce = 1000.0 * draggedBody.mass; // 添加到物理系统中 PhysicsSystem.instance.addJoint(mouseJoint); // 拖动结束后移除 Mouse Joint PhysicsSystem.instance.removeJoint(mouseJoint); ``` 这种方式能够有效防止物体穿透,并保持自然的物理交互效果[^2]。 --- ### 2. 启用接触事件并手动修正穿透 如果仍希望使用 Kinematic 刚体进行拖动,可以通过监听 **接触事件(Contact Events)** 并在每一帧中检测是否发生了穿透,随后施加冲量来修正位置。 ```typescript PhysicsSystem.instance.enableContactEvent = true; cc.director.getPhysicsManager().on(ContactEventType.BeginContact, (contact) => { const colliderA = contact.colliderA; const colliderB = contact.colliderB; if (colliderA === draggedCollider || colliderB === draggedCollider) { const manifold = contact.getWorldManifold(); const normal = manifold.normal; const penetration = manifold.separations.reduce((sum, sep) => sum + sep, 0) / manifold.points.length; draggedBody.applyLinearImpulse(new Vec2(normal.x * penetration * 10, normal.y * penetration * 10), draggedBody.worldCenter); } }); ``` 此方式可以在拖动过程中动态调整物体之间的相对位置,从而减少穿透的发生[^4]。 --- ### 3. 调整物理模拟参数提升精度 为了进一步提升物理系统的稳定性,可以适当调整物理引擎的固定步长迭代次数: ```typescript PhysicsSystem.fixedTimeStep = 1 / 60; // 提高更新频率 PhysicsSystem.velocityIterations = 8; // 增加速度求解次数 PhysicsSystem.positionIterations = 5; // 增加位置求解次数 ``` 更高的迭代次数有助于提高物理计算的准确性,但也会增加 CPU 开销,需根据项目性能需求合理设置[^2]。 --- ### 4. 结合触发碰撞器控制交互 可以将某些碰撞器设置为触发器(Trigger),用于检测物体进入或离开区域的事件,同时保留正常的碰撞器用于物理响应。这样可以在不影响物理行为的前提下实现复杂的交互逻辑。 ```typescript boxCollider.isTrigger = true; ``` 该方法可用于辅助检测拖动物体是否接近其他物体,提前做出响应[^3]。 --- ### 总结 使用 Kinematic 刚体进行拖动虽然便于控制物体的位置,但容易引发穿透问题。通过引入 Mouse Joint、启用接触事件并手动修正、调整物理模拟参数等手段,可以有效解决穿透问题,同时保持物理碰撞的正确性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值