【Unity】コピペで動く!isGroundedが接地しない問題をRaycastで解決するぞ

IsGrounded3.png

 CharacterControllerの問題児「isGrounded」が信用ならないので自分で実装しよう、という話です。

 以前、🔍CharacterControllerのisGroundedは初期状態では false でファイナルアンサー!というエントリーで、isGroundedの接地判定がザル過ぎて使い物にならない!という話をしました。その中で改善案としてLinecastで判定を取るか、下方向へのオフセットを入れて地面に近づけるのがいいんじゃないかという話をしましたが、参考サイトの見解を右から左に受け流しただけで実際にコードを組んで検証するようなことまではしていませんでした。
その後自分で実際にやってみたら結構サクッとできてしまったので、コピペで動く形にまとめて紹介しようと思います。これくらいのこと公式でサポートして欲しいんですけどね。
では、コードは👇こちらからどうぞ。

isGroundedを自分で実装する

  1. コピペで動くコード
  2. コードの解説

コピペで動くコード

    private Transform _transform;

void Start()
{
_transform = transform;
}
接地判定したいスクリプト内でTransformを定義します。
Start()内で_transformにキャッシュしておきます。
    private bool IsGrounded
{
get
{
var ray = new Ray(_transform.position + new Vector3(0, 0.1f), Vector3.down);
var raycastHits = new RaycastHit[1];
var hitCount = Physics.RaycastNonAlloc(ray, raycastHits, 0.2f);
return hitCount >= 1;
}
}
新たな接地判定bool「IsGrounded」を作ります。
        if (IsGrounded)
{
// 地上の処理
}
接地判定を取りたい箇所で判定に使えばOKです。

コードの解説

自身の座標から下方向に向かって短いRay(見えない光線みたいなもの)を出します。
この光線が地面やオブジェクトなどのCollisionに接触すると hitCount に1以上の数値が入ります。hitCountが0でなければ地上、というわけです。このRayはとても便利で、例えばRayを水平に飛ばせば視線判定(キャラが見えているか)も実現できます。
なお、 RaycastAll と RaycastNonAlloc では機能に違いがないらしいので、メモリにゴミが残らないと噂の RaycastNonAlloc を使うのがよいと思います。

この IsGrounded を使えば、今までガクガクすぎて使い物にならなかった接地判定が見違えるように正確になります。今までの苦労は何だったんでしょうかね。

以上です。



おわりに、Unity教本をお探しならこちらは如何でしょうか。
👇上位表示の教本👇はKuroMikanも愛用しています。

ゲームのアンテナ