プロジェクト演習Ⅳ インタラクティブゲーム制作 プログラミング4 2011/11/29 当たり判定総復習
今日の内容 当たり判定の素材を整理しよう 戻し方で苦労しよう 基礎となる計算の整理 座標系の正規化 球ベース判定 角張系判定 速度分解 ゲームの特性に合わせた戻し方
覚えておいて欲しい計算 距離を算出できると判定に使える 点と点 点と線&線と線 点と平面&線と平面 まさかこれが出来ないという人はおるまいね? 点と線&線と線 fk_Mathクラス参照 点と平面&線と平面 「三次元幾何要素表現と交差交線計算」参照 線と平面の交差判定は、パラメータu,vを算出することで三角形との衝突判定になるので重要
座標系の正規化とは こういう計算よりは こういう計算の方が楽そうだよね
球ベース判定の傾向と対策 球 カプセル 球だけで押し通すのは厳しいが、他の判定と併用することも多い 複雑な判定の前に球ベースで判定しておくなど 球の中心を「点」から「線分」に拡張することにより、「カプセル」へと進化する カプセル 球よりボリュームの広いエリアをカバー 球の弾丸貫通問題対策としても使用 ボーンのように組み合わせれば人型キャラの判定は十分作れる
球とカプセル 中心間の距離が、お互いの半径の合計より小さかったら衝突 球がうぞぞぞぞっと動いた軌跡 組み合わせて人型にしたり、弾丸貫通 問題への対処に使う 線分と線分(点)の距離で判定ができる
真の衝突判定とは ある瞬間にぶつかってるかどうか、を 調べるだけでは「干渉判定」でしかない 「これくらい動く予定なんだけど、 どこかでぶつかっちゃう?」を調べる !!!! ! ! ?
角張り系判定 球VS球では安定した接地が難しいため、乗っかることを前提とした物体は角張り系の判定が必要 直方体 凸包 三角形メッシュ集合体 XYZ軸に平行に配置された直方体はAABB、 自由に回転が許されたものはOBBと呼ぶ 球やカプセルとの判定も可能で、 その場合は座標系の正規化を使って処理を行う 凸包 対球に関しては最強レベルの判定素材 凸包同士や、その他の判定素材との連携が困難 三角形メッシュ集合体 DirectXやXNAではデフォルトでサポートしている 点や線との判定は容易だが、閉じた形状は表せないので運用に注意が必要
凸包とは 凹んだ部位のない 立体 n角柱、n角錐なども凸包に含まれる 点(球)との内外判定がべらぼうに簡単 衝突検出になると 難しいが。。。
三角形と線分の判定を駆使 理論上はどんなポリゴンモデルでも対応可能 破綻無く判定するのが困難だが… どこでぶつかったのか、を明確に判断できるのは線分系の判定なので、それをひたすら駆使する
用途に応じて使い分け キャラクターは球 マップはブロック 見た目はゴージャスに作った形状でもいい それらを覆うような球を当たり判定用に用意して、親子関係を結べばいい entry()しなければ表示されない マップはブロック 球だとつるつるすべって操作性に難がある
とりあえずおすすめは キャラ&可動障害物 地形 乗っかれる必要が あるデカキャラなど 視界判定 攻撃判定 球(カプセル)、OBB ベクトルの内積による角度判定&距離 攻撃判定 球、カプセル
ではない 戻し方 動物体の次フレームでの位置を仮定する その動きを阻害する可能性のある物体全てと衝突判定を行う 戻しベクトルが発生したら動物体に適用する 全物体と判定を終えたら終了… ではない
以下のようなシチュを考える 右図のような状況の場合、Aに衝突して発生した戻しベクトルによって、Bに衝突する危険性がある 真上から見た図 A B
解決案 候補の物体と判定して、「戻しベクトルが発生しなかったら」判定終了とする 色々効率化の余地はあるだろうが、とりあえずはこうしておこう do { 戻しベクトル初期化 for(障害物候補全部) { 当たり判定する 戻しベクトル加算 } 動物体に適用 } while(適用したベクトルがゼロじゃなかったらもう1回ループ);
重力の扱い 基本的には常時下向きの力を働かせる そうすると、同じ高さで並べたブロックでつっかかる 速度をXZ方向とY方向に分解して2回判定 足下のブロックから先に判定できればいいが、そうもいかない 速度をXZ方向とY方向に分解して2回判定 真横から見た図 A B
どちらが好ましいか? ぶつかった時点で 止まるタイプ 壁擦れするタイプ
効率的な判定のためテクニック 距離で刈り込む クラスタで刈り込む OBBの判定より距離の判定の方が軽い 具体的な距離の値が要らない(距離内かどうかだけが知りたい)場合は、ベクトルの長さの2乗と判定距離の2乗で比較しよう if(vec.dist2() < d*d) のように判定 クラスタで刈り込む 常時全物体と判定するのはナンセンスの極み
クラスタリングって? モノの分類や、 グループ分けのこと 真上から見た図 マップを領域ごとに分割する 領域ごとに「どの物体が存在しているか」のリストを持つ 判定したくなったら、自分が居る領域のリストに問い合わせて判定 真上から見た図
クラスタリングに必要な部品 座標→クラスターIDへの変換 配列の配列 (x, z)の座標値を、一定間隔ごとの整数値に変換する必要がある vector< vector<int> >などを使う 本当はlistなどに出来ればした方がよい
当たり判定クラスの設計方針 現状のfkutシリーズではまだまだです 共通の基底クラスを持たせて、個別の判定クラスはそれを継承して作るようにすべき チームを超えて設計して、共通のクラスを開発するのもgood! こうなるよりは… vector<fkut_OBB *> obbArray; vector<fkut_Capsule *> capArray; vector<fkut_... *> otherArray; この方がいい vector<fkut_Collision *> colArray;