ノード解説「Area2D」

はじめに

ゲームのキャラクターがアイテムを拾ったり、敵に接触したり、特定の場所に入ったら何かが起きる――こうした「接触判定」「範囲判定」を実装する場面で活躍するのが Area2D ノードです。この記事では、Area2D の役割から実装方法まで、ゲーム開発でよく使う使い方をご紹介します。

Area2D とは?

Area2D は、2D世界で「衝突判定用の領域」を定義するノードです。他のノードと接触したときや、範囲内に何かが入ったときに信号(シグナル)を発火させ、スクリプトから対応する処理を実行できます。

たとえるなら、Area2D は「見えない壁」ではなく「見えない警報装置のついた領域」です。ボールが転がってきたら感知する、敵が入ってきたら警告を出す――その役割を担います。

Area2D は Node2D を継承しており、位置・回転・スケールを持つ基本的な2Dノードとして機能します。

このノードを使うべき場面

  • アイテムの取得判定: コイン・鍵・パワーアップなど、プレイヤーが近づくと拾える(衝突検出)
  • ダメージゾーン: 炎・トゲ・敵の攻撃範囲など、範囲内に入るとダメージを受ける
  • オブジェクト間の接触判定: ボールが飛んできた、敵が近い、NPC に話しかけられる距離にいる
  • トリガー判定: 特定の場所に入ったらイベント開始、ボスが目覚める、隠し通路が現れる
  • 範囲攻撃: 爆発・魔法範囲・スキルの影響範囲などの判定

注意: 物理演算を伴わない「判定だけ」が必要な場合に使います。重力や跳ね返りが必要なら CharacterBody2D や RigidBody2D を使いましょう。

主なプロパティと機能

Area2D の代表的なプロパティとメソッドを表にまとめました。

プロパティ / メソッド 説明
area_entered 別の Area2D が範囲内に入ったときに発火するシグナル
area_exited 別の Area2D が範囲から出たときに発火するシグナル
body_entered PhysicsBody2D(CharacterBody2D など)が範囲内に入ったときに発火
body_exited PhysicsBody2D が範囲から出たときに発火
get_overlapping_areas() 現在範囲内にある全ての Area2D を取得
get_overlapping_bodies() 現在範囲内にある全ての PhysicsBody2D を取得
monitoring trueで判定を有効、falseで無効にする
monitorable trueで他のノードから検出される、falseで無視される

シグナルをスクリプトで受け取る基本的な書き方です。


extends Area2D

func _ready():
    # シグナルをスクリプトに接続
    area_entered.connect(_on_area_entered)
    area_exited.connect(_on_area_exited)

func _on_area_entered(area):
    print("Area が入ってきた: ", area.name)

func _on_area_exited(area):
    print("Area が出ていった: ", area.name)

もっと使いこなす:カスタマイズできるパラメータ

まずは基本を動かしてみてから、余裕が出たら試してみてください。

判定の有効 / 無効を切り替える

monitoringmonitorable を組み合わせることで、細かい判定制御ができます。

パラメータ 変更時の挙動
monitoring = false このノードは他を検出しなくなる。アイテムが非アクティブなときに便利
monitorable = false 他のノードからこのノードが検出されなくなる。敵の無敵時間に使える
両方 false 完全に判定が無効。演出中やポーズ時に活躍

# アイテムを拾った直後、判定を無効にして二重取得を防ぐ
func _on_area_entered(area):
    if area.is_in_group("player"):
        monitoring = false
        monitorable = false
        # フェードアウト演出を再生
        await get_tree().create_timer(0.3).timeout
        queue_free()

衝突マスクとレイヤー設定

Area2D には「自分がどのレイヤーか」と「どのレイヤーと衝突するか」を指定する機能があります。

  • Collision → Layer: このノードが属するレイヤー(例:「敵」「アイテム」)
  • Collision → Mask: このノードが検出する対象レイヤー(例:「プレイヤーとアイテムだけ検出」)

複雑なゲームでは、複数のレイヤーを使い分けることで判定を効率化できます。


# スクリプトから衝突マスクを変更する例
func set_collision_layers():
    # このノードは「敵」レイヤー(ビット1)に属する
    collision_layer = 1 << 1
    # 「プレイヤー」レイヤー(ビット0)と「プロジェクタイル」レイヤー(ビット2)を検出
    collision_mask = (1 << 0) | (1 << 2)

CollisionShape2D との組み合わせ

Area2D だけでは判定の形を決められません。子ノード として CollisionShape2D を追加し、円形・矩形・カプセルなどの判定形状を決めます。


# Area2D のセットアップ例(エディタで行うのが通常)
extends Area2D

func _ready():
    # 既に CollisionShape2D が子ノードにあることを前提
    var shape = $CollisionShape2D
    shape.shape = CircleShape2D.new()
    shape.shape.radius = 30.0  # 判定の半径を30ピクセルに

get_overlapping_bodies() で範囲内のオブジェクト一括取得

シグナルの on/off を待つのではなく、毎フレーム「今この範囲に何があるか」を調べたい場合があります。


# 敵の攻撃範囲内にいるプレイヤーに継続的にダメージを与える
extends Area2D

func _process(delta):
    var bodies = get_overlapping_bodies()
    for body in bodies:
        if body.is_in_group("player"):
            body.take_damage(10 * delta)  # 毎秒10ダメージ

グループ分けで判定を整理する

シグナル受け取り時に「どのタイプのノードなのか」をグループで判定すると、コードがシンプルになります。


# プレイヤーが接触したものが何かで処理を分ける
func _on_area_entered(area):
    if area.is_in_group("item"):
        collect_item(area)
    elif area.is_in_group("enemy"):
        take_damage(area.damage)
    elif area.is_in_group("trap"):
        trigger_trap(area)

まとめ

Area2D は、ゲームの「接触・範囲検出」を担当する便利なノードです。物理演算を使わず判定だけが欲しいときの基本装備と覚えておきましょう。

  • Area2D はシグナル(area_entered など)で接触を検出します
  • 判定形状は CollisionShape2D で定義します
  • monitoringmonitorable で判定の ON/OFF を細かく制御できます

次の記事では、物理演算を伴う CharacterBody2D について解説します。アクションゲームのキャラクター移動に欠かせないノードです。

シリーズ:Godot 4 ノード解説

  • 001. ノード解説「Node」
  • 002. ノード解説「Node2D」
  • 003. ノード解説「Sprite2D」
  • 004. ノード解説「AnimatedSprite2D」
  • 005. ノード解説「CollisionShape2D」
  • 006. ノード解説「RigidBody2D」
  • 007. ノード解説「Area2D」
  • 008. ノード解説「CharacterBody2D」
  • 009. ノード解説「TileMap」
  • 010. ノード解説「Camera2D」

この記事は Godot 4.x をもとに執筆しています。

コメント