3

这是之前问过的,但最初的提问者不需要更改动态属性,所以他通过取消提问来回答自己的问题。

我在 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 实现(和覆盖)的问题。

也许?

4

2 回答 2

8

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

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

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

SKPhysicsBody *temp = node.physicsBody;
temp.dynamic = NO;
node.physicsBody = temp;
于 2014-01-19T18:23:58.840 回答
0

如果原始发布者的意图是在直接操作 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,您可以在使用触摸操作场景时使用类似的逻辑来禁用它。

于 2014-02-24T23:35:34.740 回答