首页 文章

使用 multi-geometry 形状未正确检测到碰撞

提问于
浏览
2

我有一个具有复杂几何形状的宇宙飞船物体,由于 SceneKit 的物理不适用于复杂的物体,我采用了一种解决方法:我使用了一些基本的形状,如圆柱体和立方体,因此模拟整个宇宙飞船的身体。在 Blender 中,我创建了一组近似于宇宙飞船形状的物体:

在此输入图像描述

然后当我加载场景时,我删除了这些对象,但是使用它们的几何构造一个 SCNPhysicsShape 来用作宇宙飞船的物理主体:

// First I retrieve all of these bodies, which I named "Body1" up to 9: 
let bodies = _scene.rootNode.childNodes(passingTest: { (node:SCNNode, stop:UnsafeMutablePointer<ObjCBool>) -> Bool in
    if let name = node.name
    {
        return name.contains("Body")
    }
    return false
})

// Then I create an array of SCNPhysicsShape objects, and an array
// containing the transformation associated to each shape
var shapes = [SCNPhysicsShape]()
var transforms = [NSValue]()
for body in bodies
{
    shapes.append(SCNPhysicsShape(geometry: body.geometry!, options: nil))
    transforms.append(NSValue(scnMatrix4:body.transform))
    // I remove it from the scene because it shouldn't be visible, as it has 
    // the sole goal is simulating the spaceship's physics
    body.removeFromParentNode()  
}

// Finally I create a SCNPhysicsShape that contains all of the shapes
let shape = SCNPhysicsShape(shapes: shapes, transforms: transforms)
let body = SCNPhysicsBody(type: .dynamic, shape: shape)
body.isAffectedByGravity = false
body.categoryBitMask = SpaceshipCategory
body.collisionBitMask = 0
body.contactTestBitMask = RockCategory
self.spaceship.physicsBody = body

SCNPhysicsShape 对象应包含我在 Blender 文件中创建的所有形状。但是当我测试程序时,宇宙飞船的行为就像一个空体,并且没有检测到碰撞。

PS:我的目标只是检测碰撞。我不希望物理引擎模拟物理。

1 回答

  • 2

    你想为你的船使用凹形。以下示例。为了使用凹面,你的身体必须是静态的或运动的。运动学是动画对象的理想选择。

    不需要:

    body.collisionBitMask = 0
    

    只需要联系人就可以获得接触位掩码。

    以下代码适用于您所寻找的内容.这是快速的 3 代码 fyi.

    let body = SCNPhysicsBodyType.kinematic
    let shape = SCNPhysicsShape(node: spaceship, options: [SCNPhysicsShape.Option.type: SCNPhysicsShape.ShapeType.concavePolyhedron])
    spaceship.physicsBody = SCNPhysicsBody(type: body, shape: shape)
    

    没有看到你的位掩码,我无法判断你是否正确处理它们。你应该有类似的东西:

    spaceship.physicsBody.categoryBitMask = 1 << 1
    

    您想要联系您的太空船的任何东西都应该:

    otherObject.physicsBody.contactTestBitMask = 1 << 1
    

    这只会将“otherObject”的联系人注册到“太空飞船”而不是“太空船”到“otherObject”。因此,请确保您的物理世界联系代表以这种方式处理,反之亦然。不需要两个对象互相寻找。这样效率会降低。

    下面的代表示例:

    func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
    
        var tempOtherObject: SCNNode!
        var tempSpaceship: SCNNode!
    
        // This will assign the tempOtherObject and tempSpaceship to the proper contact nodes
        if contact.nodeA.node == otherObject {
            tempOtherObject = contact.nodeA
            tempSpaceship = contact.nodeB
        }else{
            tempOtherObject = contact.nodeB
            tempSpaceship = contact.nodeA
        }
    
        print("tempOtherObject = ", tempOtherObject)
        print("tempSpaceship = ", tempSpaceship)
    
    }
    

相关问题