如何设置SceneKit碰撞检测

T N*_*ate 13 scenekit swift

您好我已经仔细阅读了文档,无法弄清楚如何在场景工具包中设置碰撞检测.有人可以举个例子.请帮助我非常绝望地想出这个.谢谢!

编辑:您好,非常感谢,对不起,我忘了提到我的项目很快.没什么大不了的,我可以在很大程度上翻译自己.

我有BitMasks正常工作,因为对象相互碰撞和反弹.但是我似乎无法使功能发挥作用

func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact){
    let contactMask = contact.nodeA.physicsBody!.categoryBitMask | contact.nodeB.physicsBody!.categoryBitMask
    if (contactMask == (CollisionBallCategory | CollisionTerminatorCategory)) {
        println("Collided")
    }
}
Run Code Online (Sandbox Code Playgroud)

看看文档,我需要以某种方式将场景物理世界委托分配给此方法.我不知道该怎么做.

ric*_*ter 34

在SceneKit中获得碰撞检测的主要内容:

  • 它基于位掩码,它们共同组成一个表.
  • 联系代表是您如何应对冲突.

使物体碰撞

例如,您可以用简单的英语说明一些游戏设计,如下所示:

小行星相互撞击(并制造较小的小行星).导弹应该相互穿过,但是要毁掉火箭和小行星.火箭队不应该对导弹做任何事情(只是反过来),但如果一个人太靠近另一个或小行星,你就会遇到一个不好的问题,今天你不会去太空.

实现碰撞检测的第一步是根据哪些对进行交互来编写该设计.您可以使用表格执行此操作:

         | Missile | Rocket | Asteroid
--------------------------------------
Missile  | No      | Yes    | Yes
Rocket   | No      | Yes    | Yes
Asteroid | No      | No     | Yes
Run Code Online (Sandbox Code Playgroud)

然后,您可以将表的标题转换为一组类别常量,以便在代码中使用.

typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
    CollisionCategoryMissile    = 1 << 0,
    CollisionCategoryRocket     = 1 << 1,
    CollisionCategoryAsteroid   = 1 << 2,
};

missile.physicsBody.categoryBitMask = CollisionCategoryMissile;
rocket.physicsBody.categoryBitMask = CollisionCategoryRocket;
asteroid.physicsBody.categoryBitMask = CollisionCategoryAsteroid;
Run Code Online (Sandbox Code Playgroud)

在这些常量上使用按位OR来创建collisionBitMask填充表的值.

missile.physicsBody.collisionBitMask =
    CollisionCategoryRocket | CollisionCategoryAsteroid;
rocket.physicsBody.collisionBitMask =
    CollisionCategoryRocket | CollisionCategoryAsteroid;
asteroid.physicsBody.collisionBitMask = CollisionCategoryAsteroid;
Run Code Online (Sandbox Code Playgroud)

这就是让SceneKit为你解决碰撞所需要的一切(也就是说,互相反弹物体).

应对碰撞

如果您还希望收到碰撞通知(这样您可以使导弹炸毁,并将您的船运到小行星结束游戏),您需要在场景的物理世界中设置一个联系委托并实施一个或多个发生联系时调用的联系委托方法

在您的联系委托方法(例如physicsWorld:didBeginContact:)中,您需要找出联系中涉及哪些类别的主体,哪些是哪个,因此您可以访问您的代码,该代码执行您的游戏对碰撞所做的任何事情:

- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact
{
    CollisionCategory contactMask =
        contact.nodeA.physicsBody.categoryBitMask | contact.nodeB.physicsBody.categoryBitMask;

    // first, sort out what kind of collision
    if (contactMask == (CollisionCategoryMissile | CollisionCategoryRocket)) {
        // next, sort out which body is the missile and which is the rocket
        // and do something about it
        if (contact.nodeA.physicsBody.categoryBitMask == CollisionCategoryMissile) {
            [self hitRocket:contact.nodeB withMissile:contact.nodeA];
        } else {
            [self hitRocket:contact.nodeA withMissile:contact.nodeB];
        }
    } else if (contactMask == (CollisionCategoryMissile | CollisionCategoryAsteroid)) {
        // ... and so on ...
    }
}
Run Code Online (Sandbox Code Playgroud)

将此代码放在您的一个类中(可能是视图控制器 - 无论您将游戏逻辑保持在哪里),并使该类声明符合SCNPhysicsContactDelegate协议.

@interface ViewController: UIViewController <SCNPhysicsContactDelegate>
Run Code Online (Sandbox Code Playgroud)

然后将该对象指定给场景的物理世界作为联系人委托:

// in initial setup, where presumably you already have a reference to your scene
scene.physicsWorld.contactDelegate = self
Run Code Online (Sandbox Code Playgroud)

了解更多

SCNPhysicsBody参考文档中有一些关于冲突解决的内容.Apple提供了一些使用碰撞检测的示例代码 - 它是WWDC 幻灯片演示示例应用程序中演示的大杂烩的一部分,也是车辆物理演示中的一部分.

除此之外,SceneKit的碰撞处理模型几乎与SpriteKit完全相同,因此几乎SpriteKit编程指南中的所有内容对于理解SceneKit中的相同内容也很有用.