2016-08-03 5 views
1

私はレベルベースのゲームを使用しています。レベル作成にXcodeシーンエディタを使用していますが、別々のシーンで作成された、ゲームのシーンで参照ノードとしてドラッグされました。コード内の参照ノードにカテゴリ、衝突および接触ビットマスクを割り当てます。

オブジェクトの物理ボディを作成しようとすると、作成した.scnファイルの参照ノードとして使用され、その物理ボディがゲームシーンのノードに参照されていないようですが、シーンエディタで直接作成されたプロパティは次のとおりです。

実際に参照ノードである各ノードの物理ボディをコードで設定しようとすると、物理ノードが設定されます(物理ボディがnilではありません)が、衝突は検出されません。

これは私が物理学のボディを設定し、コード、次のとおりです。

// player (I want to be notified when player collides with any walls) 
    playerNode = level1Scene.rootNode.childNodeWithName("playerNode", recursively: true)! 
    playerNode.physicsBody = SCNPhysicsBody(type: .Dynamic, shape: nil) 
    playerNode.physicsBody?.affectedByGravity = false 
    playerNode.physicsBody?.categoryBitMask = PhysicsCategory.Player.rawValue 
    playerNode.physicsBody?.collisionBitMask = PhysicsCategory.Wall.rawValue 
    playerNode.physicsBody?.contactTestBitMask = PhysicsCategory.Wall.rawValue 

    //wall from separate .scn file 
    let wallScene = SCNScene(named: "wallObject.scn") 
    let wall = wallScene!.rootNode.childNodeWithName("wall", recursively: true)! 
    wall.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: nil) 
    wall.physicsBody?.categoryBitMask = PhysicsCategory.Wall.rawValue 
    wall.physicsBody?.collisionBitMask = PhysicsCategory.Player.rawValue 
    wall.physicsBody?.contactTestBitMask = PhysicsCategory.Player.rawValue 

    // walls that are reference nodes of the wall and are located in game scene 
    let wall2 = level1Scene.rootNode.childNodeWithName("wallObject reference", recursively: true)! 
    wall2.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: nil) 
    wall2.physicsBody?.categoryBitMask = PhysicsCategory.Wall.rawValue 
    wall2.physicsBody?.collisionBitMask = PhysicsCategory.Player.rawValue 
    wall2.physicsBody?.contactTestBitMask = PhysicsCategory.Player.rawValue 
    print(wall2.physicsBody!) // prints <SCNPhysicsBody: 0x7fe5f9dc75a0> 

私は任意の連絡先について連絡ないです、またプレイヤーが物理的に接触上の任意の壁に衝突しません。私はなしで、これは今二日のために働くために取得しようとしてきた

level1Scene.physicsWorld.contactDelegate = self 

extension GameViewController: SCNPhysicsContactDelegate { 
    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) { 
     playerNode.physicsBody?.velocity = SCNVector3Zero 
     print("player and wall collided") 
    } 
} 

と私のゲームシーンに接触デリゲートを設定します。私はSCNPhysicsContactDelegateプロトコルにクラスを適合しています成功。私がSprite Kitを使って作業していたとき、ほとんどの場合私の問題に関する関連記事を見つけることができ、質問を投稿しても答えが出ました。しかし、シーンキットは私が推測するほど人気が​​ありませんし、私は何も見つけることができません。

私が間違っている箇所やコード内での衝突の検出方法を知っている場合は、教えてください。

答えて

1

あなたが投稿したコードに基づいて緩やかな例をまとめましたが、唯一の「問題」は、連絡先の代理人が正常に呼び出されるという点で効果があったことです。この場合のプレーヤーのジオメトリはSceneKitの宇宙船であり、wall2は他のシーンに追加されたSCNBoxで、Finderから船のシーンにドラッグされます。重力が含まれているので、船は壁に落ちるだけです。

オブジェクトがお互いに跳ね返りますが、連絡先の代理人が呼び出されていないだけですか?またはオブジェクトが互いに通過するかどうか。私はまたあなたがプレイヤーオブジェクトを移動させて接触を起こす方法を知っていますか?

import UIKit 
import QuartzCore 
import SceneKit 

let colors = [UIColor.redColor(), UIColor.brownColor(), UIColor.cyanColor(), UIColor.greenColor(), UIColor.yellowColor(), UIColor.blueColor()] 

enum PhysicsCategory:Int { 
    case Player = 2 
    case Wall = 4 
} 

extension GameViewController: SCNPhysicsContactDelegate { 

    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) { 
     playerNode.geometry?.firstMaterial?.diffuse.contents = colors[Int(arc4random_uniform(UInt32(colors.count)))] 
     print("player and wall collided") 
    } 
} 

class GameViewController: UIViewController { 

    var playerNode:SCNNode! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // create a new scene 
     //let scene = SCNScene() 
     let scene = SCNScene(named: "art.scnassets/ship.scn")! 

     //playerNode = SCNNode(geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)) 
     playerNode = scene.rootNode.childNodeWithName("ship", recursively: true)! 
     playerNode.geometry?.firstMaterial?.diffuse.contents = UIColor.redColor() 
     playerNode.physicsBody = SCNPhysicsBody(type: .Dynamic, shape: nil) 
     playerNode.physicsBody?.affectedByGravity = true 
     playerNode.physicsBody?.categoryBitMask = PhysicsCategory.Player.rawValue 
     playerNode.physicsBody?.collisionBitMask = PhysicsCategory.Wall.rawValue 
     playerNode.physicsBody?.contactTestBitMask = PhysicsCategory.Wall.rawValue 

     initPlayer() 
     //scene.rootNode.addChildNode(playerNode) 

     //let wall = SCNNode(geometry: SCNBox(width: 20, height: 0.25, length: 20, chamferRadius: 0)) 
     let wallScene = SCNScene(named: "art.scnassets/wallObject.scn") 
     let wall = wallScene!.rootNode.childNodeWithName("wall", recursively: true)! 
     wall.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: nil) 
     wall.physicsBody?.categoryBitMask = PhysicsCategory.Wall.rawValue 
     wall.physicsBody?.collisionBitMask = PhysicsCategory.Player.rawValue 
     wall.physicsBody?.contactTestBitMask = PhysicsCategory.Player.rawValue 
     //scene.rootNode.addChildNode(wall) 

     let wall2 = scene.rootNode.childNodeWithName("wallObject reference", recursively: true)! 
     wall2.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: nil) 
     wall2.physicsBody?.categoryBitMask = PhysicsCategory.Wall.rawValue 
     wall2.physicsBody?.collisionBitMask = PhysicsCategory.Player.rawValue 
     wall2.physicsBody?.contactTestBitMask = PhysicsCategory.Player.rawValue 


     scene.physicsWorld.contactDelegate = self 

     // retrieve the SCNView 
     let scnView = self.view as! SCNView 
     scnView.playing = true 
     scnView.scene = scene 
     scnView.allowsCameraControl = true 
     scnView.autoenablesDefaultLighting = true 
     scnView.showsStatistics = true 
     scnView.backgroundColor = UIColor.lightGrayColor() 

     // add a tap gesture recognizer 
     let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) 
     scnView.addGestureRecognizer(tapGesture) 
    } 

    func handleTap(gestureRecognize: UIGestureRecognizer) { 
     initPlayer() 
    } 

    func initPlayer() { 
     playerNode.position = SCNVector3Make(0, 12, 0) 
     playerNode.eulerAngles = SCNVector3Make(Float(drand48() * M_PI/2), Float(drand48() * M_PI/2), Float(drand48() * M_PI/2)) 
     playerNode.physicsBody?.velocity = SCNVector3Zero 
     playerNode.physicsBody?.angularVelocity = SCNVector4Zero 
    } 
} 
+0

私は問題が何かを考え出しました。私は壁の参照ノードをたくさん持っていて、それらはすべて同じ名前を持っています。そのため、物理学のボディを1つだけに設定していました。私はすべての子ノードを列挙し、その名前でこれらのプロパティを設定することで問題を解決しましたが、これが正常に実行された場合は懐疑的でした。私は200の壁を持っているので、私はそれらのそれぞれの物理体を設定するループを実行すると、同じことが200回繰り返されます。ファイルの壁のために壁の物理ボディを直接参照する場所を設定すると良いでしょうか? – Larisa

+0

パフォーマンスに大きな影響を与えることはありません。私はそれを利便性の問題としてもっと見るだろう。ソースscnファイルでこれらのパラメータを設定すると、すべての壁が同じプロパティを持つことになりますが、コードで設定すると柔軟性が得られます。おそらく、いくつかの壁が他の壁より多くの跳ね返りを持つか、別の衝突カテゴリに属する​​ようにしたいと思うかもしれません...まだ、いくつかのデフォルトの物理プロパティを含めることは理にかなっています。 – lock

関連する問題