見出し画像

【Unity】Physics2D.Raycastを使用した壁との当たり判定

自機に向かってくる敵を実装していたのですが壁との当たり判定で苦労しました。
今まで作っていた縦スクロールSTGなどは壁の位置が固定もしくは変化するにしても座標が決まっていたので、例えば if(x<0) x=0; みたいにしておけば壁との当たり判定は出来たのですが、今作っている全方位スクロールSTGだと壁の座標が常に変化しているので、この方法は使えないんですよね。

こういう場合の実装方法を調べてみると「壁に当たった時は当たった方向と逆向きに少し戻す」という実装方法が良く解説されていたので実装してみると・・・

壁に当たった時に少し戻す時に戻した側に壁があるとすり抜けてしまうんですよね。
当たり判定を小さくしたり位置を変えたり戻す量を工夫してみたりしたのですが、戻ると言う動作があると上手く作る事が出来ませんでした(上手く出来る方法はあると思うのですが私には作れなった)
そしてなにより壁に当たってちょっと戻る動きがカッコ悪い(笑)

戻る動きを使わないようにすれば良いのではないかと思って調べてみるとUnityにはRaycastと言う「透明な光線を打ち光線に当たったオブジェクトの情報を取得する機能」がある事を知りRaycastを使ってやれば上手く出来るのではないかと思って実装してみると上手く出来ました。

実装方法としてはこんな感じ

Ray2D ray = new Ray2D(transform.position, -transform.up); // Rayを生成、-transform.upは進行方向
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction, 1f);//Raycastを生成

Debug.DrawRay(ray.origin, ray.direction * 1f, Color.green, 0.015f); // 長さ1f、緑色で1フレーム可視化
if (hit.collider)
{
    if (hit.collider.gameObject.layer == 12 || hit.collider.gameObject.layer == 7)//12は"kabe" 7は"teki"
    {
        ds = 0;//移動速度を0にする
    }

    Debug.Log(hit.collider.gameObject.layer);//Rayが当たった物をログ表示
    Debug.DrawRay(hit.point, hit.normal * 2f, Color.green, 0.015f); // 法線ベクトル表示、長さ2f、緑色で1フレーム可視化
}

当初1本のRaycastで判定を行っていたのですが半分くらい壁に埋まってしまう時があってBoxcast(箱型のRayを飛ばす)やSphereCast(丸型のRayを飛ばす)を使ってみたのですが中心に壁が当たった時の動きが不自然だったのでオブジェクトの左右から2本のRayを飛ばして判定する方法が一番自然に見える感じに出来ました。

当たった物との判定はPhysics2D.RaycastのlayerMaskでも出来るのですがcollider側でも判別出来てhit.collider.gameObject.layerに返ってくる数字で当たった物を区別出来ます。

Layerに設定した数字がcollider.gameObject.layerに返ってくる

layerMaskを使って判別する場合はビット演算で記述するようです。
tekiとの接触なら1 << 7
kabeとの接触なら1 << 12
他に&や|や~演算子も使えます。(C#の記述ではなくビット演算子記述なので&&や||とは記述しない)
例えばtekiもしくはkabeとの当たり判定のみ行いたい場合は

hit = Physics2D.Raycast(ray.origin, ray.direction, 0.8f, 1 << 12 | 1 << 7);

みたいに記述します。

余談ですが
hit.pointで当たった位置
hit.normalで当たった位置の法線ベクトル
hit.distanceで当たった距離
なども取得出来るので色々と使えそうです。

この記事が気に入ったらサポートをしてみませんか?