私はSCNPhysicsContactDelegate、categoryBitMask、collisionBitMask、およびphysicsWorld funcがどのように動作するかを知ることができるように、いくつかの物理を持つ簡単なScenekitシーンを設定しようとしています。私もcontactTestBitMaskを設定する必要があるかどうかはわかりません。SwiftでScenekitの衝突検出を処理するにはどうすればよいですか?
接触検出について学ぶことで、ビットワイズ演算子の長い経路とビットマスキングの概念がわかりました。バイナリで追加するのは楽しいです!しかし、これはまだまったく霧に包まれており、私はSpriteKitとSceneKitの両方で見つけたいくつかのチュートリアルをまとめてみようとしています。 This is the most comprehensiveしかし、それはObj-Cであり、Swiftにどのように翻訳するのか分かりません。
これは私が作成したものです。どんな洞察も高く評価されるだろう。あなたは私が間違って設定したものを見ることができますか?赤いローリングボールが青のターゲットに当たったときに、簡単なPrint文を出したいと思います。フロア、ランプ、ターゲットは静的ですが、ローリングボールは.dynamicです。
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.
}
}
**更新:**私は問題を解決することができました。私は、シーン内の異なるノードに対して設定したcollisionBitMasksが不完全であることに気付きました。シーンのさまざまなノードの衝突の相互作用のより完全なリストを定義しました。また、 'contact.nodeA.categoryBitMask'を' contact.nodeA.physicsBody!.categoryBitMask'に変更しました。なぜそれが違いを生み出したのか分かりませんが、それはありました。なぜなのかご存知ですか? – brickm