もう9年か10年前くらいになりますか、レースゲームを作りかけていたことがあります。
OpenGLで作っていて、コース4つとCPUの動きまで出来ていたのですが、それ以降のUIまわりの対応や自分の技術的問題で公開できないままとなっていました。
今でもそのゲームに未練がありまして、何ならUnityを使えば当時よりもはるかに作りやすいんじゃないのと思い立ちました。
そして先日Twitterにも投稿した動画がこちら。
……いかにもUnityですね。まずは動くことが大事。
当たり判定の計算の都合で平らに見える地面でも派手に跳ねていますが後々空を飛ぶ予定なので(恐らく)問題なし。
Terrainで地面を作ってブロックを置くくらいならだいぶ楽に作れますね。その割に当たり判定にやや苦戦しました。
以下ごく基本的な内容ですが、自分が試した方法を書いてみます。
Unityでオブジェクトの当たり判定を取りたい時は、といえばまずColliderとRigidBodyを使った物理演算。
RidigBodyをつけた物体は何も書かなくても重力に従って落ち、Colliderをつけた物体にぶつかってくれます。
物理演算を活かしたゲームの場合はコードを書かなくても遊べるものがで来る優れものですね。
ただし今回は宙に浮いたり必ずしも物理的な動きをさせるわけではないので、この自動計算は使わないことにしました。
物体を自前で動かす場合、RigidBodyのisKinematicをtrueにすることで物理演算が行われなくなります。しかもColliderとの衝突判定も行われず(OnCollision~が呼ばれない)、ほかの物体をすり抜けるようになります。
ではすり抜けないためにどうするかと言えばColliderのisTriggerをtrueにすると、OnCollision~の代わりにOnTrigger~系が呼ばれるので、ぶつかった後の動きは自分で制御してねという形になります。
ただこのOnTrigger~、受け取れる引数がColliderなので「何がぶつかったか」は分かっても「どこにぶつかったか」が分からず、OnCollision~の代わりにしようとするとその後の計算がだいぶ面倒そうなことになります。
しかもこのTriggerが呼ばれるのはFixUpdateの直後なので、Update内で座標更新をしていると計算タイミングのズレも起こってさらに面倒。結局この複雑になって駄目でした。
後で考えてみると、このTriggerをTrueにしたColliderの使い方は衝突して跳ね返る判定とかではなく「特定のボックス内にいるとドアが開く」とかそういうすり抜けを前提にしたものなんだろうなー気付くのでした。
そして最終的に取った方法がRigidBodyを外した上でUpdate内でRaycast。物理演算をしないならRigidBodyが要らないのは当然の話でした。
Colliderとの当たり判定を取るPhysics.RaycastとかBoxCastはUpdate内で呼んでいいらしいので、これを呼ぶことで「どこにぶつかったか」の情報を取れるのでした。どっとはらい。
地面のTerrainとの判定も取れるので全てRaycastで解決できるのですが、それはそれでぶつかった後の動きにはそれなりに苦労するのでした(能力不足)。それでも過去に作ったものと比べると格段に楽なものでした。
ということで、これ以降もいけるところまで作ってみる所存です。
少し前までTerrainを「テライン」と呼んでいましたがどちらかと云うとテレインですね。テレーン