【问题标题】:Optional collision with SKPhysicsContactDelegate与 SKPhysicsContactDelegate 的可选碰撞
【发布时间】:2020-04-02 13:52:58
【问题描述】:

是否有可能在空间发生碰撞之前取消它?

示例:A 和 B 即将发生碰撞,但 A 具有一个属性,因此对于特定的 SKPhysicsContact,不应发生与 B 的碰撞。空间中的所有其他碰撞都应不受影响。

在阅读 Apple 的课程文档时,它说:

物理接触委托方法在物理过程中被调用 模拟步骤。期间物理世界不可修改 以及物理实体的任何变化的行为 模拟未定义。如果您需要进行此类更改,请设置一个标志 在 didBegin(:) 或 didEnd(:) 中并做出相应的更改 SKSceneDelegate 中 update(_:for:) 方法中的标志。

这是否意味着我可以检测到 didBegin() 中的状态,并在实际发生碰撞之前更改 update() 中的碰撞掩码?

有一个类似主题的旧线程:SpriteKit SKPhysicsBody collision in one direction like a door you can only go through but not back

【问题讨论】:

  • 接触和碰撞是两个不同的东西,请更好地解释你想要做什么。
  • 更新了问题。

标签: swift sprite-kit skphysicscontact


【解决方案1】:

当然

你可以设置contactBitMask在检测到联系人时调用didBegin方法。一旦调用了 didBegin 并且您从 (_contact: SKPhysicsContact) 参数中的信息中识别出您想要的节点。

设置一个标志,表明联系已经发生。从那里运行 override func didFinishUpdate() 中的流控制 (if) 语句来检查标志的值。如果为 true,则更改对象的碰撞掩码。

然后在下一个游戏循环迭代中,物理不会检测到碰撞。尽管在检测到接触的游戏循环中,您仍然会遇到初始碰撞。不过有办法解决这个问题。就像在碰撞发生之前制造第二个更大的物理体来检测接触。

【讨论】:

  • 最好将被忽略对象的类别掩码更改为 0,而不是乱用碰撞掩码。碰撞遮罩需要改变两个物体,类别遮罩只需要改变被接触的物体(不是接触器)
  • 你也有问题,碰撞和接触会发生在同一个更新周期,所以可能会出现卡顿甚至反射。
【解决方案2】:

根据我的理解,您希望一个对象有时会穿过一个对象。

以下代码应该可以工作:

enum CategoryBitMasks{
  case player1Collidable = 1 << 0
  case player2Collidable = 1 << 1
  case player1 = 1 << 2
  case player2 = 1 << 3
  case oneTimePass = 1 << 4
  case unstoppable = 1 << 5
  case player = CategoryBitMasks.player1 | CategoryBitMasks.player2
  case playerCollidable = CategoryBitMasks.player1Collidable | CategoryBitMasks.player2Collidable
}


//Create an obstacle with category (.player1Collidable | .player2Collidable)
//                   with contact 0
//                   with collision 0
//Create a player with category (.player1 | .unstoppable)
//                with contact .player1Collidable
//                with collision .player1Collidable 

func didBeginContact(contact: SKPhysicsContact) {
    var obstacle = contact.bodyA.categoryBitMask >= contact.bodyB.categoryBitMask ?contact.bodyA, contact.bodyB
    var player = contact.bodyB == obstacle ? contact.bodyA, contact.bodyB

    //Only allows the player to pass through 1 object
    if player.categoryBitMask || CategoryBitMasks.oneTimePass && obstacle.categoryBitMask || CategoryBitMasks.playerCollidable  {
       obstacle.categoryBitMask &= ~(player.collisionBitMask & CategoryBitMasks.playerCollidable) //turns player1Collidable off
       player.categoryBitMask &= ~(player.categoryBitMask & CategoryBitMasks.oneTimePass) //turns oneTimePass off

    }

    //Allows player to pass through all objects
    if player.categoryBitMask || CategoryBitMasks.unstoppable && obstacle.categoryBitMask || CategoryBitMasks.playerCollidable  {

       //This will bypass all objects providing their collision is not set to the player
       player.collisionBitMask &= ~(player.collisionBitMask & CategoryBitMasks.playerCollidable) //turns player1Collidable off

       //This will bypass all objects, but is dangerous because the category is now changed, meaning if a contact does happen, .player can't be used
       //player.categoryBitMask &= ~(player.categoryBitMask & CategoryBitMasks.player ) //turns player1Collidable off

    }
}

记得在需要时重置掩码

这将允许玩家 1 根据您指定的类别穿过对象,同时强制玩家 2 仍然被同一个对象阻挡。

希望这些示例能帮助您调整游戏需求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    相关资源
    最近更新 更多