[0]官方box2d封装,没有PostSolve方法问题的解决方案。

我这边游戏需要在对象碰撞的时候,判断碰撞的冲量,根据冲量来判断是否摧毁物品。但官方封装的方法,直接把PostSolve给忽略了。。
无奈只能自己加一份,为了尽量不修改引擎源码,导致不兼容的问题,我使用了prototype覆盖的方法。额外增加了一个类。对于原来的laya.physics.js类,只需要添加把ContactListener这个类导出的方法即可。
具体参见我这个类。
使用的时候,只需要在外部调用初始化方法就行了。


const BoxExtraFunctions = {}

// 在laya.physics.js里添加这些方法,将ContactListener这个类导出来。
// Laya.ClassUtils.regClass("laya.physics.ContactListener", ContactListener);
// Laya.ClassUtils.regClass("Laya.ContactListener", ContactListener);
// exports.ContactListener = ContactListener;


BoxExtraFunctions.addExtra = function(){
//注册预碰撞功能。
Laya.ContactListener.prototype.PostSolve = function(contact, impulse) {
Laya.Physics.I._eventList.push(impulse, contact);
}

Laya.Event.TRIGGER_POST_SOLVE = "trigger_post_solve"

Laya.Physics.prototype._sendEvent = function(type, contact) {
var colliderA = contact.GetFixtureA().collider;
var colliderB = contact.GetFixtureB().collider;
var ownerA = colliderA.owner;
var ownerB = colliderB.owner;
contact.getHitInfo = function () {
var manifold = new this.box2d.b2WorldManifold();
this.GetWorldManifold(manifold);
var p = manifold.points[0];
p.x *= Physics.PIXEL_RATIO;
p.y *= Physics.PIXEL_RATIO;
return manifold;
};
if (ownerA) {
var args = [colliderB, colliderA, contact];
if (type === 0) {
ownerA.event(Laya.Event.TRIGGER_ENTER, args);
if (!ownerA["_triggered"]) {
ownerA["_triggered"] = true;
}
else {
ownerA.event(Laya.Event.TRIGGER_STAY, args);
}
}
else if(type === 1){
ownerA["_triggered"] = false;
ownerA.event(Laya.Event.TRIGGER_EXIT, args);
}
else{
ownerA.event(Laya.Event.TRIGGER_POST_SOLVE, args.concat(type));
}
}
if (ownerB) {
args = [colliderA, colliderB, contact];
if (type === 0) {
ownerB.event(Laya.Event.TRIGGER_ENTER, args);
if (!ownerB["_triggered"]) {
ownerB["_triggered"] = true;
}
else {
ownerB.event(Laya.Event.TRIGGER_STAY, args);
}
}
else if(type === 1){
ownerB["_triggered"] = false;
ownerB.event(Laya.Event.TRIGGER_EXIT, args);
}
else{
ownerB.event(Laya.Event.TRIGGER_POST_SOLVE, args.concat(type));
}
}
}

Laya.Script.prototype.onTriggerPostSolve = function(other, self, contact, impulse) {

}

Laya.Script.prototype._onEnable = function(){
let proto = Laya.Script.prototype
if (this.onTriggerEnter !== proto.onTriggerEnter) {
this.owner.on(Laya.Event.TRIGGER_ENTER, this, this.onTriggerEnter);
}
if (this.onTriggerStay !== proto.onTriggerStay) {
this.owner.on(Laya.Event.TRIGGER_STAY, this, this.onTriggerStay);
}
if (this.onTriggerExit !== proto.onTriggerExit) {
this.owner.on(Laya.Event.TRIGGER_EXIT, this, this.onTriggerExit);
}
if (this.onTriggerPostSolve !== proto.onTriggerPostSolve) {
this.owner.on(Laya.Event.TRIGGER_POST_SOLVE, this, this.onTriggerPostSolve);
}
if (this.onMouseDown !== proto.onMouseDown) {
this.owner.on(Laya.Event.MOUSE_DOWN, this, this.onMouseDown);
}
if (this.onMouseUp !== proto.onMouseUp) {
this.owner.on(Laya.Event.MOUSE_UP, this, this.onMouseUp);
}
if (this.onClick !== proto.onClick) {
this.owner.on(Laya.Event.CLICK, this, this.onClick);
}
if (this.onStageMouseDown !== proto.onStageMouseDown) {
ILaya.stage.on(Laya.Event.MOUSE_DOWN, this, this.onStageMouseDown);
}
if (this.onStageMouseUp !== proto.onStageMouseUp) {
ILaya.stage.on(Laya.Event.MOUSE_UP, this, this.onStageMouseUp);
}
if (this.onStageClick !== proto.onStageClick) {
ILaya.stage.on(Laya.Event.CLICK, this, this.onStageClick);
}
if (this.onStageMouseMove !== proto.onStageMouseMove) {
ILaya.stage.on(Laya.Event.MOUSE_MOVE, this, this.onStageMouseMove);
}
if (this.onDoubleClick !== proto.onDoubleClick) {
this.owner.on(Laya.Event.DOUBLE_CLICK, this, this.onDoubleClick);
}
if (this.onRightClick !== proto.onRightClick) {
this.owner.on(Laya.Event.RIGHT_CLICK, this, this.onRightClick);
}
if (this.onMouseMove !== proto.onMouseMove) {
this.owner.on(Laya.Event.MOUSE_MOVE, this, this.onMouseMove);
}
if (this.onMouseOver !== proto.onMouseOver) {
this.owner.on(Laya.Event.MOUSE_OVER, this, this.onMouseOver);
}
if (this.onMouseOut !== proto.onMouseOut) {
this.owner.on(Laya.Event.MOUSE_OUT, this, this.onMouseOut);
}
if (this.onKeyDown !== proto.onKeyDown) {
ILaya.stage.on(Laya.Event.KEY_DOWN, this, this.onKeyDown);
}
if (this.onKeyPress !== proto.onKeyPress) {
ILaya.stage.on(Laya.Event.KEY_PRESS, this, this.onKeyPress);
}
if (this.onKeyUp !== proto.onKeyUp) {
ILaya.stage.on(Laya.Event.KEY_UP, this, this.onKeyUp);
}
if (this.onUpdate !== proto.onUpdate) {
ILaya.updateTimer.frameLoop(1, this, this.onUpdate);
}
if (this.onLateUpdate !== proto.onLateUpdate) {
ILaya.lateTimer.frameLoop(1, this, this.onLateUpdate);
}
if (this.onPreRender !== proto.onPreRender) {
ILaya.lateTimer.frameLoop(1, this, this.onPreRender);
}
this.onEnable();
}
}

export default BoxExtraFunctions
已邀请:

Yan

赞同来自:

这个我们稍后和技术确认一下是否漏加。如果是的话,后续会加上的。感谢您的反馈。

阿闲

赞同来自:

如果按照上面的改法,会有问题,PostSolve方法在接触的对象之间,每帧都会调用,而且有个地方的对象发生碰撞后的冲量,会影响到所有的接触中的对象。找了半天,原因在于。
laya.physics.js里面b2Island类里的Solve方法里有调用
this.Report(contactSolver.m_velocityConstraints);
在SolveTOI这个方法里也调用了。
通关日志可以知道,Solve里的方法,是每帧都调用,SolveTOI里只是在接触的一瞬间调用。
这不很明显了吗,我把Solve方法里的调用注释掉,就正常了。
希望官方不是说说而已,早点修复这个BUG。

要回复问题请先

商务合作
商务合作