以前做的笔记:仅供参考
onContactBegin 中添加刚体导致节点信息被覆盖的问题
- 节点信息丢失,被物理世界同步回来的数据覆盖
原因分析
beforeSimulation #1 同步节点信息到刚体
cpSpaceStep
- 触发碰撞事件
- 执行回调onContactBegin
//
- 如果在此处添加新的刚体
- 会导致刚体原始信息没有同步到物理世界. 没有执行beforeSimulation
- afterSimulation会同步刚体信息到节点,而新刚体的刚体信息是默认的。还没有经过任何同步。
- 会被覆盖掉,丢失了原始节点信息
- 覆盖为空
afterSimulation #2 同步刚体位置/旋转信息到节点
解决方案
// 在下一帧再执行新增刚体的操作
ScheduleUtil::onNextFrame(this,[this](float dt){
auto& endPos=_attackMonster->convertToWorldSpace(Vec2::ZERO);
_gun->fire(endPos);//发射子弹
});
cpSpaceStep
// 物理世界步进
// - 刚体发生碰撞时会触发事件,调用回调等collisionBeginCallbackFunc
// - listener->onContactBegin=[](PhysicsContact& contact){
// P:\@git\game_test\__cocos2dx\physics\cocos\CCPhysicsWorld\Event事件\setPreUpdateCallback 更新事件.cpp
void PhysicsWorld::update(float delta, bool userCall)
cpSpaceStep(_cpSpace, delta);
// 事件回调
cpCollisionHandler *handler = cpSpaceAddDefaultCollisionHandler(_cpSpace);
handler->userData = this;
handler->beginFunc = (cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc;
handler->preSolveFunc = (cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc;
handler->postSolveFunc = (cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc;
handler->separateFunc = (cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc;
void PhysicsWorld::update(float delta, bool userCall)
{
if(_preUpdateCallback) _preUpdateCallback(); //fix #11154
/// #1 同步节点信息到刚体
auto sceneToWorldTransform = _scene->getNodeToParentTransform();
beforeSimulation(_scene, sceneToWorldTransform, 1.f, 1.f, 0.f);
...
// 物理世界步进
// - 刚体发生碰撞时会触发事件,调用回调等collisionBeginCallbackFunc
// - listener->onContactBegin=[](PhysicsContact& contact){
if (userCall)
{
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
cpSpaceStep(_cpSpace, delta);
#else
cpHastySpaceStep(_cpSpace, delta);
#endif
}
...
// Update physics position, should loop as the same sequence as node tree.
// PhysicsWorld::afterSimulation() will depend on the sequence.
// 更新物理位置,应该按照与节点树相同的顺序循环。
// PhysicsWorld::afterSimulation() 将取决于序列。
/// #2 同步刚体位置/旋转信息到节点
afterSimulation(_scene, sceneToWorldTransform, 0.f);
if(_postUpdateCallback) _postUpdateCallback(); //fix #11154
}