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.
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.
}
}
** 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