collisionBitMaskはどのように機能しますか?Swift/SpriteKit 質問する

collisionBitMaskはどのように機能しますか?Swift/SpriteKit 質問する

私の知る限り、Physics ボディのデフォルトは、collisionBitMask を等しい数値に設定するまで、ボディ同士が衝突すると互いに跳ね返ることです。

しかし、collisionBitmasks のせいで、非常に単純なはずのことを成し遂げるのに大きな問題を抱えていると思います。

let RedBallCategory  : UInt32 = 0x1 << 1
let GreenBallCategory: UInt32 = 0x1 << 2
let RedBarCategory : UInt32 = 0x1 << 3
let GreenBarCategory : UInt32 = 0x1 << 4
let WallCategory : UInt32 = 0x1 << 5


greenBall.physicsBody?.categoryBitMask = GreenBallCategory
greenBall.physicsBody?.contactTestBitMask = RedBarCategory
greenBall.physicsBody?.collisionBitMask = GreenHealthCategory

redBall.physicsBody?.categoryBitMask = RedBallCategory
redBall.physicsBody?.contactTestBitMask = GreenBarCategory
redBall.physicsBody?.collisionBitMask = RedHealthCategory

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory
borderBody.categoryBitMask = WallCategory

ここに 2 つのボールと境界ボディがあります。必要な衝突検出は得られますが、境界ボディのカテゴリ ビット マスクを追加すると、ボールが画面を通過して画面から外れることが許可されてしまいます。これは望ましくありません。

また、ボールが互いに跳ね返るようにしたいのですが、ボールの categoryBitMask の 1 つをコメント アウトした場合にのみ、ボールは跳ね返ります。それ以外の場合は、ボールは互いに通り抜けてしまいます。

これらの各アイテムには異なる衝突ビットマスクがあるため、これはまったく意味がありません。また、すべての数字を 5 に設定するとすべてが互いに通過できるようになりますが、すべてを 6 に設定するとすべてが互いに衝突するようになることもありました。

衝突ビットマスクは具体的にどのように機能するのでしょうか。また、交差する多数の衝突ルールを管理する適切な方法はあるのでしょうか。

ベストアンサー1

カテゴリ、コンタクト、衝突ビット マスクを適切に設定していないため、目的の動作が得られません。これを動作させる設定方法の例を次に示します。

greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall

redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected

以下のドキュメントを読むことをお勧めしますカテゴリBitMaskこれは、物理体がどのカテゴリに属する​​かを定義するマスクです。

シーン内のすべての物理ボディは、最大 32 個の異なるカテゴリに割り当てることができ、各カテゴリはビット マスク内のビットに対応します。ゲームで使用するマスク値を定義します。collisionBitMask プロパティと contactTestBitMask プロパティと組み合わせて、どの物理ボディが相互に作用するか、およびゲームにこれらの作用がいつ通知されるかを定義します。

連絡先テストビットマスク- 現在の物理ボディとの交差通知を引き起こすボディのカテゴリを定義するマスク。

2 つのボディが同じ空間を共有する場合、各ボディのカテゴリ マスクは、論理 AND 演算を実行して、他のボディの接触マスクに対してテストされます。いずれかの比較の結果がゼロ以外の値になった場合は、SKPhysicsContact オブジェクトが作成され、物理ワールドのデリゲートに渡されます。最高のパフォーマンスを得るには、関心のある相互作用の接触マスクのビットのみを設定します。

衝突ビットマスク- この物理ボディと衝突できる物理ボディのカテゴリを定義するマスク。

2 つの物理ボディが互いに接触すると、衝突が発生する可能性があります。このボディの衝突マスクは、論理 AND 演算を実行して、他のボディのカテゴリ マスクと比較されます。結果がゼロ以外の値の場合、このボディは衝突の影響を受けます。各ボディは、他のボディの影響を受けるかどうかを個別に選択します。たとえば、これを使用して、ボディの速度に無視できるほどの変化をもたらす衝突計算を回避することができます。

したがって、基本的にこれらすべてを設定するには、次のような質問を自分に問いかける必要があります。

さて、シーンには緑のボール、赤のボール、壁のオブジェクトがあります。どのボディ間で衝突を発生させるか、またはいつ接触を登録するか? 緑のボールと赤のボールが互いに衝突し、壁に衝突するようにします。問題ありません。まずカテゴリを適切に設定し、次に衝突ビット マスクを次のように設定します。

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory

wall.collisionBitMask = GreenBall | RedBall

ここで、何らかの接触が発生したときにそれを検出したい ( didBeginContact: メソッド内)... しかし、すべての可能性のある接触について通知を受け取りたいのではなく、ボール間の接触についてのみ通知を受け取りたいのです (ボールと壁の接触は無視されます)。contactTestBitMasksこれを実現するために設定してみましょう:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;

以上です。重要なのは、接触検出を使用しない場合は を設定しないことですcontactTestBitMask。これはパフォーマンス上の理由によるものです。衝突検出が不要で、接触の検出のみに関心がある場合は、 を設定できますcollisionBitMask = 0

重要:

didBeginContactメソッドを使用するには、物理​​ワールドのコンタクトデリゲートが設定されていることを確認してくださいdidEndContact

self.physicsWorld.contactDelegate = self; //where self is a current scene

これが少しでも役に立つことを願います。

おすすめ記事