【问题标题】:Sprite Kit failing assertion: (typeA == b2_dynamicBody || typeB == b2_dynamicBody)Sprite Kit 断言失败:(typeA == b2_dynamicBody || typeB == b2_dynamicBody)
【发布时间】:2014-02-25 07:35:34
【问题描述】:

这是被问到earlier,但原来的提问者不需要更改动态属性,所以他通过取消提问来回答自己的问题。

我在 iOS7 中使用 Sprite Kit,我希望能够在运行时更改 SKPhysicsBody 的动态属性。最初我在 touchesBegan: 方法中改变了它。 Apple Dev 论坛中有人建议将更改移至 didSimulatePhysics: 方法,但这也无济于事。

此代码导致错误:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
  if (!heyWereSwappingDynamismHere) 
  {
    heyWereSwappingDynamismHere = YES;
    SKNode * rope = [self childNodeWithName:@"rope"];
    SKNode * anchor = [rope childNodeWithName:@"anchor"];
    [listOfObjectsToSwapDynamic addObject:anchor];
  }
}

-(void) didSimulatePhysics 
{
  if (heyWereSwappingDynamismHere) 
  {
    for (SKNode * node in listOfObjectsToSwapDynamic) 
    {
        bool isItDynamic = node.physicsBody.isDynamic;
        node.physicsBody.dynamic = !isItDynamic;
    }
    [listOfObjectsToSwapDynamic removeAllObjects];
    heyWereSwappingDynamismHere = NO;
}

}

调试器中出现的错误是:

断言失败:(typeA == b2_dynamicBody || typeB == b2_dynamicBody),函数 SolveTOI,文件 /SourceCache/PhysicsKit/PhysicsKit-4.6/PhysicsKit/Box2D/Dynamics/b2World.cpp,第 670 行。

我在其他地方四处张望,但这似乎是 Sprite Kit 的 Box2D 实现(和覆盖)的问题。

也许?

【问题讨论】:

  • 尝试创建一个新的主体来替换之前的主体,或者您可能不需要它是静态的,但您不希望它与任何东西发生碰撞。在这种情况下,使用接触类别并将重力比例设置为 0,这将具有与静态物体相同的效果。在 bix2d 中,您不能将身体从静态更改为动态,反之亦然,我想 sprite kit 也是如此。

标签: dynamic ios7 box2d sprite-kit skphysicsbody


【解决方案1】:

您可以来回更改dynamic 属性,但是,如果您使用碰撞/接触检测,则应该非常小心。

在两个物体之间的碰撞/接触期间,断言其中至少一个必须是动态物体。如果在运行时将该属性更改为 NO,并且另一个接触的物体也是静态的(非动态的),并且正在发生碰撞/接触回调,它将抛出这个特定的断言错误 - 将在 2 个静态物体中间检测到接触-执行,Box2d 不喜欢。

一个可能的解决方法 - 对我有用,甚至直接在 didBeginContact: 方法中:

SKPhysicsBody *temp = node.physicsBody;
temp.dynamic = NO;
node.physicsBody = temp;

【讨论】:

  • +1 我还注意到 iOS 8 不会抱怨,但 iOS 7 会。
【解决方案2】:

如果原发帖者的意图是在直接操作 SKNode 时禁用碰撞,可以按如下方式进行:

@property (nonatomic, strong) SKNode *node;
@property (nonatomic, assign) uint32_t previousCollisionBitMask;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  // Disable collisions & gravity
  self.previousCollisionBitMask = self.node.physicsBody.collisionBitMask;
  self.node.physicsBody.collisionBitMask = 0;
  self.node.physicsBody.affectedByGravity = NO;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  // Enable collisions & gravity
  self.node.physicsBody.collisionBitMask = self.previousCollisionBitMask;
  self.node.physicsBody.affectedByGravity = YES;
}

这会将对象排除在碰撞计算之外。禁用重力可防止物体在您移动时下落。

如果您还关心contactTextBitMask,您可以在使用触摸操作场景时使用类似的逻辑来禁用它。

【讨论】:

    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2014-08-08
    • 2021-03-16
    • 2010-09-26
    相关资源
    最近更新 更多