2016-03-22 7 views
1

Ich habe versucht, eine einfache Scenekit-Szene mit etwas Physik einzurichten, so dass ich lernen konnte, wie SCNPhysicsContactDelegate, categoryBitMask, collisionBitMask und die physicsWorld-Funktion funktionieren. Nicht sicher, ob ich auch eine contactTestBitMask einrichten muss.Wie gehe ich mit Swift mit der Kollisionserkennung in Scenekit um?

Das Erlernen der Kontakterkennung hat mir einen langen Weg von bitweisen Operatoren und das Konzept der Bitmaskierung vermittelt. Das Hinzufügen von Binärdateien macht Spaß! Allerdings ist das alles immer noch sehr neblig und ich versuche, mehrere Tutorials, die ich sowohl in SpriteKit als auch in SceneKit gefunden habe, zusammenzufügen. This is the most comprehensive aber es ist in Obj-C und ich verstehe es nicht, wie man zu Swift übersetzt.

Hier ist was ich erstellt habe. Alle Einsichten würden sehr geschätzt werden. Kannst du sehen, was ich falsch eingerichtet habe? Ich hätte gerne eine einfache Print-Anweisung, wenn der rote rollende Ball das blaue Ziel trifft. Der Boden, die Rampe und das Ziel sind statisch, während der rollende Ball dynamisch ist.

Animated Gif of Scene

import UIKit 
import SceneKit 


class ViewController: UIViewController, SCNPhysicsContactDelegate { 
    //category bit masks for ball node and target node 
    // ball = 0001 -> 1 and target = 0010 ->2 
    let collisionRollingBall: Int = 1 << 0 
    let collsionTarget: Int = 1 << 1 

//declare variables 
var sceneView: SCNView! 
var cameraNode: SCNNode! 
var groundNode: SCNNode! 
var lightNode: SCNNode! 
var rampNode: SCNNode! 
var rollingBallNode: SCNNode! 
var targetNode: SCNNode! 

override func viewDidLoad() { 
    super.viewDidLoad() 
    //set up sceneview and scene. Define the physicsworld contact delegate as self 
    sceneView = SCNView(frame: self.view.frame) 
    sceneView.scene = SCNScene() 
    sceneView.scene!.physicsWorld.contactDelegate = self 
    self.view.addSubview(sceneView) 

    //add floor 
    let groundGeometry = SCNFloor() 
    groundGeometry.reflectivity = 0 
    let groundMaterial = SCNMaterial() 
    groundMaterial.diffuse.contents = UIColor.greenColor() 
    groundGeometry.materials = [groundMaterial] 
    groundNode = SCNNode(geometry: groundGeometry) 

    //add ramp 
    let rampGeometry = SCNBox(width: 4, height: 1, length: 18, chamferRadius: 0) 
    rampNode = SCNNode(geometry: rampGeometry) 
    rampNode.position = SCNVector3(x: 0, y: 2.0, z: 1.0) 
    rampNode.rotation = SCNVector4(1, 0, 0, 0.26) 

    //add rolling ball 
    let rollingBallGeometry = SCNSphere(radius: 0.5) 
    let sphereMaterial = SCNMaterial() 
    sphereMaterial.diffuse.contents = UIColor.redColor() 
    rollingBallGeometry.materials = [sphereMaterial] 
    rollingBallNode = SCNNode(geometry: rollingBallGeometry) 
    rollingBallNode.position = SCNVector3(0, 6, -6) 

    //add target box 
    let targetBoxGeometry = SCNBox(width: 4, height: 1, length: 4, chamferRadius: 0) 
    let targetMaterial = SCNMaterial() 
    targetMaterial.diffuse.contents = UIColor.blueColor() 
    targetBoxGeometry.materials = [targetMaterial] 
    targetNode = SCNNode(geometry: targetBoxGeometry) 
    targetNode.position = SCNVector3(x: 0, y: 0.5, z: 11.5) 
    targetNode.rotation = SCNVector4(-1,0,0,0.592) 

    //add a camera 
    let camera = SCNCamera() 
    self.cameraNode = SCNNode() 
    self.cameraNode.camera = camera 
    self.cameraNode.position = SCNVector3(x: 13, y: 5, z: 12) 
    let constraint = SCNLookAtConstraint(target: rampNode) 
    self.cameraNode.constraints = [constraint] 
    constraint.gimbalLockEnabled = true 

    //add a light 
    let spotLight = SCNLight() 
    spotLight.type = SCNLightTypeSpot 
    spotLight.castsShadow = true 
    spotLight.spotInnerAngle = 70.0 
    spotLight.spotOuterAngle = 90.0 
    spotLight.zFar = 500 
    lightNode = SCNNode() 
    lightNode.light = spotLight 
    lightNode.position = SCNVector3(x: 0, y: 25, z: 25) 
    lightNode.constraints = [constraint] 

    //define physcis bodies 
    let groundShape = SCNPhysicsShape(geometry: groundGeometry, options: nil) 
    let groundBody = SCNPhysicsBody(type: .Static, shape: groundShape) 
    groundNode.physicsBody = groundBody 

    let rampShape = SCNPhysicsShape(geometry: rampGeometry, options: nil) 
    let rampBody = SCNPhysicsBody(type: .Static, shape: rampShape) 
    rampNode.physicsBody = rampBody 

    let sphereShape = SCNPhysicsShape(geometry: rollingBallGeometry, options: nil) 
    let sphereBody = SCNPhysicsBody(type: .Dynamic, shape: sphereShape) 
    rollingBallNode.physicsBody?.categoryBitMask = collisionRollingBall 
    rollingBallNode.physicsBody?.collisionBitMask = collsionTarget 
    rollingBallNode.physicsBody = sphereBody 

    let targetShape = SCNPhysicsShape(geometry: targetBoxGeometry, options: nil) 
    let targetBody = SCNPhysicsBody(type: .Static, shape: targetShape) 
    targetNode.physicsBody?.categoryBitMask = collsionTarget 
    targetNode.physicsBody?.collisionBitMask = collisionRollingBall 
    targetNode.physicsBody = targetBody 

    //add nodes to view 
    sceneView.scene?.rootNode.addChildNode(groundNode) 
    sceneView.scene?.rootNode.addChildNode(rampNode) 
    sceneView.scene?.rootNode.addChildNode(rollingBallNode) 
    sceneView.scene?.rootNode.addChildNode(targetNode) 
    sceneView.scene?.rootNode.addChildNode(self.cameraNode) 
    sceneView.scene?.rootNode.addChildNode(lightNode) 

} 

func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) { 
print("contact") 

// let contactMask = contact.nodeA.categoryBitMask | 
//contact.nodeB.categoryBitMask 

    //if contactMask == collsionTarget | collisionRollingBall { 
     // print("The ball hit the target") 
    // } 

} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 


} 
+1

** UPDATE: ** Ich habe es geschafft, das Problem zu lösen. Ich erkannte, dass die collisionBitMasks, die ich für die verschiedenen Knoten in den Szenen eingerichtet hatte, unvollständig waren. Ich habe eine vollständigere Liste von Kollisionsinteraktionen für die verschiedenen Knoten in der Szene definiert. Außerdem habe ich 'contact.nodeA.categoryBitMask' in' contact.nodeA.physicsBody! .categoryBitMask' geändert und alles funktioniert. Nicht sicher, warum das einen Unterschied machte, aber es war der Fall. Weißt du, warum? – brickm

Antwort

0

Ich glaube, Sie haben die „catagoryBitMask“ -Wert in der Delegatfunktion zurückgesetzt werden, da Sie versuchen, die „catagoryBitMask“ und „collisionBitMask“ Werte zu setzen, wenn der physicsBody noch ist Null.

rollingBallNode.physicsBody?.categoryBitMask = collisionRollingBall 
rollingBallNode.physicsBody?.collisionBitMask = collsionTarget 
rollingBallNode.physicsBody = sphereBody 

Versuchen Sie, die dritte Zeile 1. setzen.