強火で進め

このブログではプログラム関連の記事を中心に書いてます。

【Unity】 Platform Effector 2D

動作検証環境

  • Unity 2022.2.0f1

はじめに

Platform Effector 2D は2Dゲームの床を作る時に使うコンポーネントです。

docs.unity3d.com

プロパティ

プロパティ名 説明
Use Collider Mask Collider Mask を使いたい時にチェック。
Collider Mask ここでチェックを付けた Layer に対してのみ Platform Effector 2D の処理対象となる。
Use One Way チェックした時、一方通行の設定が有効。
Use One Way Grouping チェックした時、複数の Collider が使われている時に全ての Collider が一方通行を通過した時のみ地面に着地する。チェックされてない時は通過した Collider のみが地面に着地する。
Surface Arc Use One Way がチェックしされている時のみ有効。地面の範囲を角度で指定。
Use Side Friction チェックした時、横から当たった時に Friction (摩擦)が考慮されます。
Use Side Bounce チェックした時、横から当たった時に Bounce (跳ね返り)が考慮されます。
Side Arc 衝突が発生した時に側面とみなす角度を設定。側面と判定された時には Use Side Friction と Use Side Bounce の設定が反映されます。

解説

Use One Way Grouping

この様なサンプルを準備します。

こういう構成になっていて、

こういう Component を設定しています。

■ Use One Way Grouping にチェックしない時

通過した赤いBoxだけが地面に立ちます。

■ Use One Way Grouping にチェックした時

両方が通過しない場合には地面に立たずに落下します。

Surface Arc

Scene ビュー上には角度が可視化されています。

指定した角度の範囲に衝突法線( collision normal )が収まった場合、地面とみなされます。

Circle Collider 2D と一緒に使った時

Surface Arc の範囲から外れたら落下しているのが確認できます。

Polygon Collider 2D と一緒に使った時

最初は Surface Arc = 30 、途中から Surface Arc = 140 に変更しています。

30 の時は壁を通過しますが 140 になったら壁に衝突し始めるのが確認できます。

なお、 Surface Arc の円弧の範囲が壁際で分かりやすい様に自作のデバッグ描画を行っています。

因みにコードはこちらになります。

using UnityEngine;

public class DebugSurfaceArc : MonoBehaviour
{
    [SerializeField] PlatformEffector2D platform;
    float arc = 0;
    [SerializeField] float scale = 1.0f;

    private Transform trans;
    // Start is called before the first frame update

    private void Start()
    {
        trans = gameObject.transform;
        if (platform == null)
        {
            Debug.LogError("PlatformEffector2Dの参照を設定して下さい。");
        }
    }
    void OnDrawGizmos()
    {
        if (trans == null) return;
        if (platform != null)
        {
            arc = platform.surfaceArc;
        }

        float halfArc = arc * 0.5f;
        float arc1 = 90.0f + halfArc;
        float arc2 = 90.0f - halfArc;
        Vector3 startPoint = trans.position;
        float rad;

        Vector3 normal = Vector3.up;

        // Arcの範囲
        {
            Vector3 direction;

            Gizmos.color = Color.white;
            // 円弧描画のAPIが無いので DrawWireSphere で代用
            Gizmos.DrawWireSphere(startPoint, scale);

            Gizmos.color = Color.green;
            startPoint = trans.position;
            // 度(°)をラジアンに変換
            rad = Mathf.PI / 180 * arc1;
            direction = Vector3.zero;
            direction.x = Mathf.Cos(rad);
            direction.y = Mathf.Sin(rad);
            direction *= scale;
            Gizmos.DrawRay(startPoint, direction);
            rad = Mathf.PI / 180 * arc2;
            direction = Vector3.zero;
            direction.x = Mathf.Cos(rad);
            direction.y = Mathf.Sin(rad);
            direction *= scale;
            Gizmos.DrawRay(startPoint, direction);
        }

        // Surface面と法線との直角を表す
        {
            float lineSize = 0.2f * scale;
            Vector3 p1, p2, p3;

            startPoint = trans.position;
            p1 = startPoint;
            p1.x += lineSize;
            p2 = p1;
            p2.y += lineSize;
            p3 = p2;
            p3.x -= lineSize;
            Gizmos.color = Color.yellow;
            Gizmos.DrawLine(startPoint, p1);
            Gizmos.DrawLine(p1, p2);
            Gizmos.DrawLine(p2, p3);
        }

        // 法線
        Gizmos.color = Color.red;
        Gizmos.DrawRay(startPoint, normal * scale);
    }
}

移動している円の顔が衝突する壁の法線は緑の矢印で示した向きとなります。

これは Surface Arc = 140 まで増やすと範囲内に収まる事が確認できます。その為、 140 に変わった時点から壁に衝突する様になりました。

Box Collider 2D と一緒に使った時

Box Collider 2D と一緒に使った時にはこのくらい小さい範囲でも衝突が発生します。 Surface Arc = 1 でも衝突が発生し、 0 にすると流石に通過する様になります。

円の顔が地面にぶつかる時の衝突法線は緑の矢印の向きとなります。これは Surface Arc の範囲内となるので衝突するという挙動になります。

Use Side Friction と Use Side Bounce

■ Use Side Friction 、 Use Side Bounce のどちらにもチェックをしていない時

■ Use Side Friction をチェックした時

摩擦が効いているので回転が発生しているのが確認できます。

■ Use Side Bounce をチェックした時

跳ねるようになったのが確認できます。