【Unity】ジャンプ中にジャンプができないように接地判定してみる (Ray編)

この記事の情報は次のバージョンで動作確認しています。

  • MacOS Monterey (12.1)
  • Unity (2021.3.2f1)
  • はじめに

    どうも、バッテラです。

    前回Collisionを使ってジャンプ中にジャンプできなくさせる方法の記事を書きました。

    www.m2game.net

    今回はRay(レイ)を使った方法で接地判定を実装してみたいと思います。

    Rayの衝突判定とは(考え方)

    Ray(レイ)とは日本語だと光線のことですが、線だと思ってください。
    一定の長さを持った線をキャラから伸ばして線が物体に衝突したかで判定する方法です。

    地面にレイヤー設定をする (エディタ)

    Rayを飛ばすと地面以外もヒットしていますが、なので対象を床だけ絞るためにLayerというのを設定します。これは後でスクリプトで使うものです。

    床のゲームオブジェクトに作ったレイヤーをセットします。

    キャラの足から下方向にRayを飛ばす (スクリプト)

    接地判定をするコードをこんな感じになりました。

    private bool IsGrand()
    {
        Vector3 offset = new Vector3(0, 0.1f, 0);
        float distance = 0.5f;
        LayerMask layerMask = LayerMask.GetMask(new string[]
        {
                "Floor",
        });
        Vector3 direction = Vector3.down;
    
        Vector3 position = transform.position + offset;
        Ray ray = new Ray(position, direction);
    
        DrawRay(ray, distance);
    
        return Physics.Raycast(ray, distance, layerMask);
    }
    

    こっからコードの解説をしていきますね。

    offset

    接地判定であればキャラの足からRayが飛ぶようにしたいので、原点からオフセット値になります。

    今回使ったキャラは足の位置が原点でそこからRayも飛ばしても何もヒットしなかったので少し上になるようにしています。

    まぁモデルによっては原点が異なるので調整しましょうということですね。

    distance

    Rayの長さです。

    長くすれば浮いた状態でも接地したことになるので、トライアンドエラーで調整していく感じ。

    layerMask

    指定レイヤーだけにRayを飛ばします(他は貫通する)。

    layerMaskはビット値で指定する値なんですがLayerMask.GetMaskメソッドを使うとレイヤー名を入れるだけでビット値に変換してくれます(複数レイヤーを指定可能)

    Layerで設定作った時のレイヤー名を入れればOKです。

    Physics.Raycast

    Rayを飛ばしてヒットしたらtrueが返ってくるメソッドです。

    このメソッドの結果で接地判定します。

    Rayを可視化するには (デバッグ)

    Rayが想定通りの方向、長さになっているかを確認する方法があります。

    www.m2game.net

    これをすればこのようにRayを可視化するこもできますよ。

    おわりに

    この記事を作り終わった時にRayとCollisionの判定方法の違いはなんだろうか?と思ってましたが、ほぼ同じことはできるけどRayはRigidbodyじゃなくても使えるというのが強みなんですよね。