本文介绍了如何在scn节点中的不同材料上进行碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在scn节点中的不同材质之间进行碰撞检测。我有一个立方体,上面有6种不同的材料/颜色和球。我想检测相同和不同的彩色碰撞,但不知道如何对每种材料应用不同的类别。

I'm trying to get collision detection between different materials within an scn node. I have a cube with 6 different materials/ colors and balls coming at the cube. I'd like to detect same and different colored collisions but don't know how to apply different categories to each material.

import UIKit
import SceneKit

class GameViewController: UIViewController, SCNPhysicsContactDelegate {

我可以稍后创建类别以分配给多维数据集的不同面吗?

Can I create categories to assign to different sides of the cube later?

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

设置内容

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 physics world did begin contact work?

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设置,当我尝试将类别添加到不同面/材料时出现错误

Cube setup, I'm getting an error when I try to add a category to the different sides/ materials

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, I'm also getting an error when I try to add a different category to different ball colors

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

}

}

也许有一种方法可以简化此过程,而只是用匹配颜色的限定符检测球和立方体的碰撞?

Maybe there's a way to simplify this and just detect ball and cube collisions with a qualifier of matching color?

谢谢!

推荐答案

SCNBox类根据需要自动创建SCNGeometryElement对象以处理多种材料。在您的情况下,您要向geometry.materials添加6种不同的材质,因此您将自动具有6个不同的GeometryElements,一个用于立方体的每一侧。

The SCNBox class automatically creates SCNGeometryElementobjects as needed to handle the number of materials. In your case, you are adding 6 different materials to geometry.materials, so you automatically have 6 different GeometryElements, one for each side of the cube.

从SCNPhysicsContact,您可以在两个物理实体之间获取。

From the SCNPhysicsContact, you can get the contact point between the two physics bodies.

到那时,您可以执行,它将为您提供一系列。在这种情况下,数组将具有2个元素,即2个结果,一个用于立方体,一个用于球。

With that point, you can then do a Hit Test, which will give you an Array of Hit Test Result's. In this case the array will have 2 elements, meaning 2 Results, one for the cube and one for the ball.

仔细检查这两个元素,确定哪个是多维数据集(通过获取结果的'node'属性,并查看节点的名称是'cube'还是'ball',可以做到这一点,当然,在创建节点时,您需要设置其name属性)。

Go through those 2 elements and determine which one is the cube (do that by getting the 'node' property of the result and see if the node's name is 'cube' or 'ball', of course you will need to set the name property of the nodes when you create them).

现在,您知道哪个是多维数据集的结果,请获取属性。使用该索引来获取被球撞到的脸的颜色。

Now that you know which one is the result for the Cube, get the Geometry Index property of the Result. Use that index to get the color of the face which was collided by the ball.

几何元素将与材料数组中的材料具有相同的顺序,因此例如,如果您的几何元素索引为0,则它​​是材料数组中的第一个材料,依此类推。

The geometry elements will have the same order as the materials in your array of materials, so for example if you got Geometry Element index 0, that is the first material in your materials array, and so on.

这篇关于如何在scn节点中的不同材料上进行碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 02:42