質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2633閲覧

[swift3] contactDelegate 衝突判定を受け取れない

yohuchan

総合スコア11

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2016/12/10 14:40

swiftの勉強を始めたばかりの初心者ですが、よろしくお願いします。
physicsBody?.categoryBitMask & collisionBitMask & contactTestBitMaskなどの設定はあっているように思うのですが、どうにも判定受け取れません。何か違うところに問題があるように思えるのですが、お知恵をお貸しいただけたら幸いです。

class GameScene: SKScene,SKPhysicsContactDelegate { 〜〜略〜〜 let controllarea = SKShapeNode(rectOf: CGSize(width:1500 ,height:400)) let guideSprite = SKShapeNode(circleOfRadius: 30) 〜〜略〜〜 //カテゴリー分け let category_guide: UInt32 = 1 << 1 let category_box: UInt32 = 1 << 2 override func didMove(to view: SKView) { self.backgroundColor = UIColor.white self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)//物理空間を作る self.physicsWorld.gravity = CGVector(dx:0,dy:0)//重力を切る self.physicsWorld.contactDelegate = self//衝突情報を自分で受ける 〜〜略〜〜 //boxづくり for i in 0...5 { for h in 0...5{ let townSprite = SKShapeNode(rectOf: CGSize(width:200 ,height:200)) townSprite.fillColor = UIColor.blue townSprite.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width:200 ,height:200)) townSprite.physicsBody?.isDynamic = false townSprite.physicsBody?.categoryBitMask = category_box townSprite.physicsBody?.collisionBitMask = category_guide townSprite.physicsBody?.contactTestBitMask = category_guide townSprite.position = CGPoint (x: -1000 + 400 * h, y: -1000 + 400 * i) ad_x = -1000 + 400 * h ad_y = -1000 + 400 * i addressArray_x.append(ad_x) addressArray_y.append(ad_y) townArray.append(townSprite) } guideSprite.fillColor = UIColor.red guideSprite.physicsBody = SKPhysicsBody(circleOfRadius: 30) guideSprite.physicsBody?.isDynamic = false guideSprite.physicsBody?.categoryBitMask = category_guide guideSprite.physicsBody?.collisionBitMask = category_box guideSprite.physicsBody?.contactTestBitMask = category_box guideSprite.position = CGPoint(x: 500,y: 800) self.addChild(guideSprite) //コントローラー表示 controllarea.fillColor = UIColor(red: 0.6,green: 0.0 ,blue: 0.4,alpha: 0.5) controllarea.physicsBody?.isDynamic = false controllarea.position = CGPoint(x:0 ,y:0) self.addChild(controllarea) ~~~~~~~略~~~~~ }//did //コントロールする override func update(_ currentTime: TimeInterval) { //上: 〜〜略〜〜 //下: 〜〜略〜〜 //左: 〜〜略〜〜 //右: 〜〜略〜〜 } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch: AnyObject in touches { let location = touch.location(in: self) let touchNode = self.atPoint(location) 〜〜略〜〜 } } //touchBegan override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { for touch: AnyObject in touches { let location = touch.location(in: self) let touchNode = self.atPoint(location) 〜〜略〜〜 } } func didBegin(_ contact: SKPhysicsContact) { 〜〜略〜〜 } func didEnd(_ contact: SKPhysicsContact) { 〜〜略〜〜 } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2016/12/10 15:30 編集

判定受け取れないというのはdidBegin(_:)が呼ばれないということでしょうか?
yohuchan

2016/12/10 17:15

お世話になります。はい、didBeginが呼ばれないです。
fuzzball

2016/12/10 18:36

実際に確認できないので色々とテストしていただけますか?(リファレンス読みましたがイマイチ理解出来ませんでした)(その1)townSpriteとguideSpriteのcontactTestBitMaskの指定を逆にしてみる。(その2)両方のcontactTestBitMaskの指定をcategory_guide|category_boxにしてみる。(その3)両方のcontactTestBitMaskの指定を0xffffffffにしてみる。以上です。ちなみに、画面上ではちゃんと衝突してるんですよね?
yohuchan

2016/12/10 23:50

色々と丁寧に考えて頂き本当にありがとうございます。このプログラムの概要は、碁盤の目のように並んだ箱の街を赤いボールがコントロールキー(画面上に作ったもの)の操作で移動をして行くと、言ったものでして、箱とボールが衝突した時にそれ以上その方向には動かないようにするために衝突判定をさせたいのですが、完全にボールは箱の上を通過してしまう次第です。アドバイス通りにテストしてみましたがやはり呼び込まれないです。didBeginの中にprint()でフラグを準備してますが立ちません。本来ならプログラム全て載せたいところですが文字数制限があって叶いません。ケアレスミスなのか文法のミスなのか判らない次第です。もっと自分なりに考えてみますが、何かお気付きの点がありましたら教えていただけるとありがたいです。本当に貴重な時間を使わせてしまってすみません。
fuzzball

2016/12/11 01:13 編集

実際に使ったことがないのであまり自信が無いのですが、少なくともcategoryBitMaskとcollisionBitMaskの設定は間違っていないようなので、画面上では衝突していると思ったのですが、それすらしていないとなると、Maskの設定ではなく他の部分に問題がありそうですね。もっとシンプルなプログラムでテストしてみてはどうでしょうか?
guest

回答1

0

ベストアンサー

didBeginが呼ばれないのはともかく、画面上でも衝突しないのはおかしいです。
各BitMaskを一切設定しなくても画面上では衝突します。
(boxのcollisionBitMaskを0にすると画面上でも衝突しなくなります)

ということで、衝突判定を受け取れる最小限のプロジェクトを作ってみましたので参考にして下さい。
Gameテンプレートで新規プロジェクトを作成し、GameScene.swiftを丸ごと置き換えるだけです。
Swift2なので適当に修正して下さい。

swift

1import SpriteKit 2 3class GameScene: SKScene, SKPhysicsContactDelegate { 4 5 let category_guide: UInt32 = 1 << 1 6 let category_box: UInt32 = 1 << 2 7 8 override func didMoveToView(view: SKView) { 9 10 //world 11 self.backgroundColor = UIColor.whiteColor() 12 self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 13 self.physicsWorld.gravity = CGVectorMake(0.0, -5.0) 14 self.physicsWorld.contactDelegate = self 15 self.name = "world" 16 17 //guide 18 let guideSprite = SKShapeNode(circleOfRadius: 30) 19 guideSprite.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2) 20 guideSprite.fillColor = UIColor.redColor() 21 guideSprite.physicsBody = SKPhysicsBody(circleOfRadius: 30) 22 guideSprite.physicsBody!.dynamic = false 23 guideSprite.physicsBody!.affectedByGravity = false 24 guideSprite.physicsBody?.categoryBitMask = category_guide 25 guideSprite.physicsBody?.collisionBitMask = category_box 26 //guideSprite.physicsBody?.contactTestBitMask = category_box 27 guideSprite.name = "guide" 28 self.addChild(guideSprite) 29 30 //box 31 let townSprite = SKShapeNode(rectOfSize: CGSizeMake(50, 50)) 32 townSprite.position = CGPoint(x: self.frame.width/2-1, y: self.frame.height-5) 33 townSprite.fillColor = UIColor.blueColor() 34 townSprite.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(50, 50)) 35 townSprite.physicsBody?.categoryBitMask = category_box 36 townSprite.physicsBody?.collisionBitMask = category_guide 37 townSprite.physicsBody?.contactTestBitMask = category_guide 38 townSprite.name = "box" 39 self.addChild(townSprite) 40 } 41 42 override func update(currentTime: CFTimeInterval) { 43 } 44 45 func didBeginContact(contact: SKPhysicsContact) { 46 print(contact.bodyA) 47 print(contact.bodyB) 48 } 49}

投稿2016/12/12 04:48

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohuchan

2016/12/12 05:42

サンプルプログラムまで作っていただいてありがとうございます。 昨日アドバイス頂いた通りに超シンプルなプログラムを作ったりしながらfuzzballさんのプログラムを見て気が付きました。      〜 -------->townSprite.physicsBody?.isDynamic = false townSprite.physicsBody?.categoryBitMask = category_box           〜    guideSprite.physicsBody = SKPhysicsBody(circleOfRadius: 30) -------->guideSprite.physicsBody?.isDynamic = false    guideSprite.physicsBody?.categoryBitMask = category_guide   〜 矢印の部分の ****Sprite.physicsBody?.isDynamic = false ですが衝突する両方とも重力の影響を受けない設定にしてしまうとただのすれ違いになってしまうようです。 なので実際に移動するtownSpriteの方のtownSprite.physicsBody?.isDynamic = trueにしたら衝突判定されました。少なくとも衝突するどちらか一方が重力の影響を受けないとdidBeginは呼び出されないようです。(まだ推測の域を超えていないのですが。。) それにしても、fuzzballさんのように親身に考えていただける方がいるとは本当に感謝いたします。 この先まだまだ出てくるであろうトラブルにも向き合う勇気が出てきました。甘えてばかりでもいけないので自力で解いていこうとは思いますが、心折れそうな時にはまた相談したいと思います。その時はご縁があればよろしくお願いします。
fuzzball

2016/12/12 06:08 編集

なるほど。私のサンプルだと、両方ともfalseにすると衝突しないので試していませんでした。 なお、isDynamic = falseは「重力の影響を受けない」ではなく「動かない」という意味だと思います。リファレンスの直訳だと「physics bodyはそれに適用された全ての力と衝動を無視します」(ちなみに、重力の影響はaffectedByGravityプロパティを使います) で、「動かない者同士は衝突することがない」ので判定を端折っているんじゃないかと想像します。
yohuchan

2016/12/12 13:25

ありがとうございます。とても勉強になります。 今はたくさんの有効な情報が必要なのでとても助かります。 現在は、touchesBeganの長押し時の暴走と格闘中なので, また、お世話になるかもしれまでんが、よろしくお願いします。(^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問