2017-09-13 2 views
1

Ich versuche Kollisionserkennung zwischen verschiedenen Materialien innerhalb eines Scn-Knoten zu bekommen. Ich habe einen Würfel mit 6 verschiedenen Materialien/Farben und Kugeln am Würfel. Ich möchte Kollisionen in gleicher und unterschiedlicher Farbe erkennen, weiß aber nicht, wie man für jedes Material verschiedene Kategorien anwendet.Wie erhalten Sie Kollisionserkennung auf verschiedenen Materialien innerhalb eines Scn-Knotens

Kann ich Kategorien erstellen, um sie später verschiedenen Seiten des Cubes zuzuordnen?

let ballCategory = 0 
let cubeCategory = 1 
let ballGreen = 2 
let ballRed = 3 
let ballBlue = 4 
let ballYellow = 5 
let ballPurple = 6 
let ballOrange = 7 
let cubeGreen = 8 
let cubeRed = 9 
let cubeBlue = 10 
let cubeYellow = 11 
let cubePurple = 12 
let cubeOrange = 13 

Setup Sachen

var scnView: SCNView! 
var scnScene = SCNScene() 
var cameraNode: SCNNode! 
var cubeNode = SCNNode() 
var ball = SCNNode() 

var randomColor: UIColor? 

var timer = Timer() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    scnScene.physicsWorld.contactDelegate = self 

    scnView = self.view as? SCNView 

     view.scene = scnScene 
     view.isPlaying = true 

    } 

    setupView() 
    setupScene() 
    setupCamera() 
    spawnCube() 

} 

Will Physik Welt tat Kontakt Arbeit beginnen?

func physicsWorld(world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) { 
      print("Physics called") 

    if (contact.nodeA == cubeNode || contact.nodeA == ball) && (contact.nodeB == cubeNode || contact.nodeB == ball) { 

     print("contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 2 && contact.nodeB.physicsBody!.categoryBitMask == 8) || (contact.nodeB.physicsBody!.categoryBitMask == 2 && contact.nodeA.physicsBody!.categoryBitMask == 8) { 

     print("green contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 3 && contact.nodeB.physicsBody!.categoryBitMask == 9) || (contact.nodeB.physicsBody!.categoryBitMask == 3 && contact.nodeA.physicsBody!.categoryBitMask == 9) { 

     print("green contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 4 && contact.nodeB.physicsBody!.categoryBitMask == 10) || (contact.nodeB.physicsBody!.categoryBitMask == 4 && contact.nodeA.physicsBody!.categoryBitMask == 10) { 

     print("green contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 5 && contact.nodeB.physicsBody!.categoryBitMask == 11) || (contact.nodeB.physicsBody!.categoryBitMask == 5 && contact.nodeA.physicsBody!.categoryBitMask == 11) { 

     print("green contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 6 && contact.nodeB.physicsBody!.categoryBitMask == 12) || (contact.nodeB.physicsBody!.categoryBitMask == 6 && contact.nodeA.physicsBody!.categoryBitMask == 12) { 

     print("green contact") 

    } 

    if (contact.nodeA.physicsBody!.categoryBitMask == 7 && contact.nodeB.physicsBody!.categoryBitMask == 13) || (contact.nodeB.physicsBody!.categoryBitMask == 7 && contact.nodeA.physicsBody!.categoryBitMask == 13) { 

     print("green contact") 

    } 

} 

func setupView() { 
    scnView = self.view as! SCNView 
    scnView.showsStatistics = false 
    scnView.allowsCameraControl = false 
    scnView.autoenablesDefaultLighting = true 

} 

func setupScene() { 
    scnScene = SCNScene() 
    scnView.scene = scnScene 
    scnScene.background.contents = UIColor.black 
} 

func setupCamera() { 

    cameraNode = SCNNode() 

    cameraNode.camera = SCNCamera() 
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) 
    scnScene.rootNode.addChildNode(cameraNode) 

} 

Cube-Setup, Ich erhalte eine Fehlermeldung, wenn ich versuche, eine Kategorie zu den verschiedenen Seiten/Materialien

func spawnCube() { 

    var geometry:SCNGeometry 

    geometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.05) 

    cubeNode = SCNNode(geometry: geometry) 

    let greenMaterial = SCNMaterial() 
    greenMaterial.diffuse.contents = UIColor.green 
    greenMaterial.locksAmbientWithDiffuse = true 

    let redMaterial = SCNMaterial() 
    redMaterial.diffuse.contents = UIColor.red 
    redMaterial.locksAmbientWithDiffuse = true 

    let blueMaterial = SCNMaterial() 
    blueMaterial.diffuse.contents = UIColor.blue 
    blueMaterial.locksAmbientWithDiffuse = true 

    let yellowMaterial = SCNMaterial() 
    yellowMaterial.diffuse.contents = UIColor.yellow 
    yellowMaterial.locksAmbientWithDiffuse = true 

    let purpleMaterial = SCNMaterial() 
    purpleMaterial.diffuse.contents = UIColor.purple 
    purpleMaterial.locksAmbientWithDiffuse = true 

    let orangeMaterial = SCNMaterial() 
    orangeMaterial.diffuse.contents = UIColor.orange 
    orangeMaterial.locksAmbientWithDiffuse = true 

    geometry.materials = [greenMaterial, redMaterial, blueMaterial, 
          yellowMaterial, purpleMaterial, orangeMaterial] 

    cubeNode.physicsBody?.mass = 10000 
    cubeNode.physicsBody?.restitution = 0 
    cubeNode.physicsBody?.damping = 0 
    cubeNode.physicsBody = SCNPhysicsBody.kinematic() 
    cubeNode.physicsBody?.categoryBitMask = Int(cubeCategory) 
    cubeNode.physicsBody?.contactTestBitMask = Int(ballCategory) 
    cubeNode.physicsBody?.isAffectedByGravity = false 

    cubeNode.position = SCNVector3(x: 0, y: 0, z: 0) 

    scnScene.rootNode.addChildNode(cubeNode) 
} 

Ball-Setup hinzufügen, erhalte ich auch einen Fehler, wenn ich versuche, eine andere Kategorie Farben unterschiedlich Ball

Vielleicht gibt es einen Weg

func spawnBall() { 

    var geometry:SCNGeometry 

    geometry = SCNSphere(radius: 0.25) 

    let ball = SCNNode(geometry: geometry) 

    let randomNumberForColor = Int(arc4random_uniform(6)) 

    if randomNumberForColor == 1 { 
     randomColor = UIColor.green 
    } 
    if randomNumberForColor == 2 { 
     randomColor = UIColor.red 
    } 
    if randomNumberForColor == 3 { 
     randomColor = UIColor.blue 
    } 
    if randomNumberForColor == 4 { 
     randomColor = UIColor.yellow 
    } 
    if randomNumberForColor == 5 { 
     randomColor = UIColor.purple 
    } 
    if randomNumberForColor == 6 { 
     randomColor = UIColor.orange 
    } 
    if randomNumberForColor == nil { 
     randomColor = UIColor.green 
    } 

    let greenMaterial = SCNMaterial() 
    greenMaterial.diffuse.contents = randomColor 
    greenMaterial.locksAmbientWithDiffuse = true; 

    geometry.materials = [greenMaterial] 

    ball.physicsBody?.mass = 0.00001 
    ball.physicsBody?.restitution = 1 
    ball.physicsBody?.damping = 0 
    ball.physicsBody = SCNPhysicsBody.dynamic() 
    ball.physicsBody?.categoryBitMask = Int(ballCategory) 
    ball.physicsBody?.contactTestBitMask = Int(cubeCategory) 
    ball.physicsBody?.isAffectedByGravity = false 

    randomX() 
    randomY() 
    randomZ() 

    ball.position = SCNVector3(x: Float(randomNumX!), y: Float(randomNumY!), z: Float(randomNumZ!)) 

    scnScene.rootNode.addChildNode(ball) 

    let force = SCNVector3(x: Float(-randomNumX!)/2, y: Float(-randomNumY!)/2, z: Float(-randomNumZ!)/2) 

    ball.physicsBody?.applyForce(force, at: cubeNode.position, asImpulse: true) 

} 

func randomX() { 

    randomNumX = Int(arc4random_uniform(10)) - 5 

} 

func randomY() { 

    randomNumY = Int(arc4random_uniform(20)) - 10 

} 

func randomZ() { 

    randomNumZ = Int(arc4random_uniform(10)) - 5 

} 

} fügen Sie diese vereinfachen und nur Ball- und Würfelkollisionen mit einem Qualifier passender Farbe erkennen?

Danke!

+0

Wenn Sie einen Kontakt entdecken, warum vergleichen Sie nicht einfach die Farbe des Balls mit der Farbe des Gesichts? Ist das dein Nachher? –

+0

Ja genau, haben Sie eine empfohlene Implementierung dafür? – spapp

Antwort

0

Die SCNBox-Klasse erstellt automatisch SCNGeometryElement-Objekte nach Bedarf, um die Anzahl der Materialien zu verarbeiten. In Ihrem Fall fügen Sie geometry.materials 6 verschiedene Materialien hinzu, sodass Sie automatisch 6 verschiedene GeometryElements haben, eines für jede Seite des Cubes.

Aus dem SCNPhysicsContact können Sie die contact point zwischen den beiden Physikkörpern erhalten.

Mit diesem Punkt können Sie dann eine Hit Test tun, die Ihnen ein Array von Hit Test Result geben wird. In diesem Fall hat das Array 2 Elemente, dh 2 Ergebnisse, eins für den Würfel und eins für den Ball.

Gehen Sie durch diese 2 Elemente und bestimmen Sie, welche der Würfel ist (tun Sie dies, indem Sie die Eigenschaft 'node' des Ergebnisses erhalten und sehen, ob der Name des Knotens 'cube' oder 'ball' ist) Legen Sie die Namenseigenschaft der Knoten fest, wenn Sie sie erstellen).

Nun, da Sie wissen, welche das Ergebnis für den Cube ist, erhalten Sie die Geometry Index Eigenschaft des Ergebnisses. Verwenden Sie diesen Index, um die Farbe des Gesichts zu erhalten, das vom Ball kollidiert wurde.

Die Geometrieelemente haben die gleiche Reihenfolge wie die Materialien in Ihrem Materialarray. Wenn Sie also beispielsweise den Geometry-Element-Index 0 haben, ist dies das erste Material in Ihrem Material-Array und so weiter.

Verwandte Themen