2016年6月27日月曜日

[Unity][2D]接地判定するスクリプト

ローグライクの製作に疲れて息抜きにアクションゲームを作っているので、アクションゲーム用です。
キャラクターが空中に居るかどうかを判定する接地判定のメモとスクリプト。

前提

  • 接地判定用のBoxCollider2Dが存在する(キャラクターの当たり判定の流用でもOK)
  • 地形のColliderにLayerが設定されている

手順

UnityにはPhysics2D.BoxCastというメソッドが存在します。
このメソッドは特定の方向に四角いあたり判定を飛ばして、衝突を検出するメソッドです。Raycastのぶっとい版です。
(類似品にCircleCastや3D用のPhysics.BoxCast,Physics.SphereCastなどもあります)
このメソッドのdistanceパラメータで飛ばす距離を指定できるので、ごく短い距離のBoxCastを垂直下向きに飛ばして地面と接触したかを見れば接地判定できます。

但しひとつ注意点があって、Castを飛ばす元がすでに地形と接触している場合、BoxCastが反応せずにすり抜けてしまいます。
この現象はテラシュールブログさんの記事に詳しいです。
これを回避するために、BoxCastはBoxColliderの中心ではなく少し上から発射するように設定します。

スクリプト

というわけでスクリプトです。
このスクリプトをアタッチするとお手軽に接地判定ができるぞ。
/**
JudgeGround.cs
Copyright (c) 2016 Hassaku
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
using UnityEngine;
public class JudgeGround : MonoBehaviour{
// BoxCastの発生元を少し上にずらす距離
private const float Epsilon = 0.005f;
/// <summary>
/// 接地判定に利用するBoxCollider
/// </summary>
public BoxCollider2D Collider;
/// <summary>
/// Colliderと地面の距離がこの値より小さければ接地と判定する
/// </summary>
public float FloatingDistance = 0.01f;
/// <summary>
/// 地形のレイヤーマスク
/// </summary>
public LayerMask GroundLayerMask;
/// <summary>
/// 接地しているかどうかを取得する
/// </summary>
public bool IsGround { get; private set; }
/// <summary>
/// 接地しているときのRaycastのコリジョン状態を取得します
/// </summary>
public RaycastHit2D RaycastHit { get; private set; }
protected void FixedUpdate() {
// BoxColliderの真下に短くぶっといRaycast(BoxCast)を撃つ
// 衝突すれば接地中
// すでに地面にめり込んでいる場合は判定されないので少し上から撃つ
// FloatingDirectionより地面との距離が小さいならば接地と判定
RaycastHit = Physics2D.BoxCast(
origin: new Vector2(Collider.transform.position.x, Collider.transform.position.y) + Collider.offset + new Vector2(0f, Epsilon),
size: Collider.size,
angle: 0f,
direction: Vector2.down,
distance: FloatingDistance + Epsilon,
layerMask: GroundLayerMask
);
IsGround = RaycastHit;
}
}
view raw JudgeGround.cs hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿