🦶

[Unity] 両足の接地判定を作り空中ジャンプを禁止する

2023/09/17に公開

タイトルの通り空中ジャンプを防止するための接地判定を作ります。
接地判定にはColliderを使う手法もありますが、その場合はColliderの上部、側面部に触れた場合にも接地判定が行われるため望ましくありません。
よって今回はRaycastを用います。
https://nosystemnolife.com/unity_raycast/

MMD4Mecanimで導入したモデルであれば以下の画像のように足用のボーンが分けられているはずなので、左右の足それぞれにRaycastを用いる事でより精度の高い接地判定が可能となります。

それぞれのRaycastを行うスクリプトを書いていきます。

GroundCheck3D
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GroundCheck3D : MonoBehaviour
{
    // 接地判定を行う対象レイヤーマスク
    [SerializeField] LayerMask groundLayers = 0;
    // 原点から見たRayの始点弄るためのoffset
    [SerializeField] Vector3 offset = new Vector3(0, 0.1f, 0f);
    private Vector3 direction, position;
    // Rayの長さ
    [SerializeField] float distance = 0.35f;
    /*
    Boolで返す。
    Rayの範囲にgroundLayersで指定したレイヤーが存在するかどうか
    */
    public bool CheckGroundStatus()
    {
        // Rayの方向。足下なのでdown
        direction = Vector3.down;
        // Rayの始点。原点 + offset
        position = transform.position + offset;
        Ray ray = new Ray(position, direction);
        // RayをGizmoで確認するためのDrawRay
        Debug.DrawRay(position, direction * distance, Color.red);

        return Physics.Raycast(ray, distance, groundLayers);
    }
}

以上のスクリプトを両足のInspectorに追加します。

またGroundCheck3Dを使用するコードも用意しておきましょう。

PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    ..
    private Rigidbody playerRb;
    public GroundCheck3D rightGround, leftGround;
    public bool onGround = true;
    ..
    void Start()
    {
        playerRb = GetComponent<Rigidbody>();
    }
    
    void Update()
    {
        ..
	if (onGround)
        {
	    if (Input.GetButtonDown("Jump"))
            {
	        // onGround = trueの場合のみジャンプを行う
                playerRb.velocity = Vector3.up * 10;
            }
        }
	setti();
    }
    
    // 左右足のRaycastにより接地判定を行う。
    private void setti()
    {
        if (rightGround.CheckGroundStatus() || leftGround.CheckGroundStatus())
        {
	    // 片方の足どちらかがtrueであれば接地とみなす
	    onGround = true;
        }
        else
        {
            onGround = false;
        }
        Debug.Log("onGround:" + onGround);
    }

ゲームを実行するとRayが確認され、実際にRayの長さを変えることで接地判定が変化するのが分かるはずです。

以上によりMMDモデルを用いた両足での接地判定から空中ジャンプの禁止が実現出来ました。
アクションゲームを作る上ではよく使いそうな技術なので勉強になりました。

Discussion