【Godot】Marker2Dを管理ノードとして活用する方法

作成: 2025-06-20最終更新: 2026-07-09

Marker2Dをスポーン地点や武器のマズル、エフェクト基準点の管理に使う方法を解説。Node2Dとの違い、@exportでのデータ付与、global_positionの使い方、整理のコツまで図解します。

「敵の出現位置」「弾の発射位置」「エフェクトを出す場所」——ゲームには、決まった 座標 を扱いたい場面が山ほどあります。これをスクリプトに Vector2(150, 300) と直書きしてしまうと、位置を少し動かしたいだけでコードを開いて数値を打ち直す羽目になり、微調整のたびに消耗します。

この面倒を解消してくれるのが Marker2D ノードです。座標を コードから切り離してエディタ上の「目印」 として置けるので、キャラクターを動かす感覚でドラッグして位置を決められます。この記事では、Marker2Dの基本から、スポーン地点や武器のマズル管理といった実践的な使い方までを解説します。

Marker2Dのイメージ。2Dシーン上のスポーン地点や銃口といった意味のある位置に、十字の目印(Marker2D)が置かれている様子

この記事でわかること

  • Marker2D とは(Node2Dとの違いと、旧Position2Dとの関係)
  • @exportスポーン地点にデータを持たせる 実践的な使い方
  • global_position / global_rotation追従する基準点 を作る
  • Marker2Dを 散らからせず整理 するコツ

Sponsored

Marker2Dとは? Node2Dとの違い

Marker2D は、2D空間の「目印」として使う、とても軽量なノードです。中身は Node2D とほぼ同じですが、決定的な違いが1つあります。 エディタ上に常に十字のギズモが表示される ことです。

Marker2DとNode2Dの比較図。左のNode2Dはエディタ上に何も表示されず位置が見えないが、右のMarker2Dは十字の目印が常に見えていて位置をドラッグで調整できる

素の Node2D は何も描画しないため、 エディタ上では位置が見えません (選択しないとどこにあるか分からない)。一方 Marker2D は十字の目印が常に見えているので、 オブジェクトをドラッグするのと同じ感覚 で座標を置いて微調整できます。コード内の抽象的な数値ではなく、目で見て触れる位置になるわけです。

補足: Godot 3にあった Position2D は、 Godot 4で Marker2D に名前が変わりました 。役割は同じ「位置の目印」です。古い記事やサンプルで Position2D と出てきたら Marker2D に読み替えてください。

実践:柔軟な敵スポーンシステムを組む

Marker2Dが真価を発揮するのが スポーン(出現)地点の管理 です。シューティングの敵編隊、タワーディフェンスの侵攻口、ローグライクのモンスター配置——「どこから」「何を」出すかをレベルデザイナーが コードを触らずに 調整できる仕組みを組んでみましょう。

まず、敵を出したい位置に Marker2D を置き、それぞれにスクリプトをアタッチして @export で「出す敵の種類」などの情報を持たせます。

# spawn_point.gd
extends Marker2D

@export var enemy_type: PackedScene   # この地点から出す敵(インスペクタで割り当て)
@export var enabled: bool = true      # この地点を使うか(デザイナーがオンオフできる)

こうしておくと、各スポーン地点は 「位置+出す敵+有効フラグ」を自分で持った目印 になります。あとは、それらを enemies_spawn_points グループに入れておき、管理側からまとめて読み取ります。

スポーンシステムの流れ図。複数のMarker2Dスポーン地点がそれぞれenemy_typeとenabledを@exportで持ち、GameManagerがグループからまとめて取得し、有効な地点のglobal_positionに敵を生成する
# game_manager.gd
func _ready() -> void:
    # スポーン地点をグループでまとめて取得
    for sp in get_tree().get_nodes_in_group("enemies_spawn_points"):
        if sp.enabled and sp.enemy_type:          # 有効かつ敵が設定済みの地点だけ
            var enemy := sp.enemy_type.instantiate()
            enemy.global_position = sp.global_position   # 目印の位置に出す
            add_child(enemy)

この設計のうれしさは、 レベルデザイナーがインスペクタだけで完結できる ことです。「この位置から」「このボスを」「今回は出す/出さない」を、コードを一切触らずにマーカーごとに設定できます。敵を増やしたければ Marker2D を1つ置いて敵シーンを割り当てるだけ。スポーンの仕組み(インスタンス化)と、地点のグループ管理を組み合わせた、実戦的なパターンです。

ポイントは2つです。

  • 位置はマーカー、ロジックはマネージャー :Marker2Dは「どこ・何を」というデータに徹し、「いつ・どう出すか」は GameManager が持ちます。役割が分かれるので、湧きの演出を変えてもマーカーはそのまま使えます。
  • global_position で出す :後述のとおり、マーカーが他ノードの子でも global_position ならワールド座標で正しく出せます。
Sponsored

キャラクターに追従する基準点(マズル)を作る

銃口、剣の先、杖の先端、足元——「キャラクターの特定部位」を基準にした処理も、Marker2Dの得意分野です。キャラクターの子として置けば、 キャラの移動・回転に自動で追従 します。

マズル追従の図。プレイヤーの子として銃口にMuzzleマーカーを置くと、キャラクターが左右どちらを向いても銃口の位置と角度に追従し、弾がその位置・角度で発射される

プレイヤーシーンで、スプライトの子に Marker2D を追加し、銃口の位置に置いて「Muzzle」と名付けます。あとは発射時に、そのマーカーの global_position(位置)と global_rotation(角度)を弾に渡すだけです。

# player.gd
@onready var muzzle: Marker2D = $Sprite2D/Muzzle
@export var bullet_scene: PackedScene

func _process(_delta: float) -> void:
    if Input.is_action_just_pressed("shoot"):
        var bullet := bullet_scene.instantiate()
        bullet.global_position = muzzle.global_position   # 銃口の位置から
        bullet.global_rotation = muzzle.global_rotation   # 銃口の向きで
        get_tree().current_scene.add_child(bullet)        # 弾はプレイヤーの子にしない

キャラが右を向いても左を向いても、Muzzleは常に銃口にあるので、弾は正しい位置と角度で飛びます。同じ要領で、足元の砂埃、背中のジェット炎など、あらゆる「部位を基準にしたエフェクト」に応用できます。

注意: スプライトを flip_h で左右反転している場合、global_rotation だけでは弾の向きが合わないことがあります。反転に応じて角度を補正するか、muzzle.global_transform.x(マーカーの右方向ベクトル)を進行方向に使うと確実です。

よくある間違いとベストプラクティス

よくある間違いベストプラクティス
コードで位置を動かす(marker.position.x += 10位置調整はエディタに任せ、コードは global_position読むだけ にする。動かすとMarker2Dの「見たまま編集」の利点が消える
Marker2DMarker2D2 のような汎用名PlayerSpawnMuzzleBossEntry など 役割が分かる名前 を付ける
ルート直下にバラバラに置くSpawnPointsEffectAnchors などの空のNode2Dに まとめて整理 する
子マーカーで position を使うワールド座標が欲しいなら必ず global_position を使う(position は親からの相対座標)

特に重要なのが positionglobal_position の違い です。子ノードの position は親から見た相対座標なので、親が動いたり回ったりすると意図しない位置になります。

positionとglobal_positionの違いの図。親ノードが移動・回転すると、子マーカーのposition(相対座標)は同じ値でも実際の位置がずれるが、global_position(ワールド座標)は常に画面上の正しい絶対位置を指す

スポーンや発射のように「画面上のこの場所」を指したいときは、 必ず global_position を使えば、親の移動・回転に影響されず正しいワールド座標が得られます。

Marker2Dの整理も効いてきます。関連するマーカーを親のNode2Dでまとめておくと、 親ごとまとめて移動・非表示 にでき、シーンツリーもすっきりします。

Marker2D整理の対比図。悪い例はルート直下に多数のMarker2Dが散らばり煩雑、良い例はSpawnPointsやEffectAnchorsという親Node2Dの下に役割ごとにまとめられている

おまけ:先に知っておくと良いこと

Marker2Dでの座標管理に慣れたら、次はこのあたりが視野に入ります。

  • 「線」の管理は Path2D / Curve2D :Marker2Dが「点」の管理なら、Path2DCurve2D は「線(経路)」の管理です。敵の巡回ルートやカメラの移動パスを定義できます。マーカーで置いた点を経路に発展させる、という流れが自然です。
  • 配置情報からレベルを自動生成_ready() でマーカーの情報を読み、そこからレベル全体を組み立てるプロシージャルな作りにもつながります。
  • 十字では物足りないなら独自ギズモ@tool スクリプトと _draw() で、エディタ上に自作の補助アイコンを描くこともできます。

まとめ

  • Marker2D は「位置の目印」。中身はNode2Dとほぼ同じだが、 エディタに十字が常時表示 されるのが強み
  • Godot 3の Position2D は Godot 4で Marker2D にリネーム された
  • @export でスポーン地点に データを持たせ れば、デザイナーがインスペクタだけで湧きを調整できる
  • キャラの子に置けば 移動・回転に追従 し、global_position / global_rotation で正しい発射位置・角度が得られる
  • 座標はコードで動かさず エディタで調整 、取得は global_position 、整理は 親Node2Dでグループ化

座標をハードコーディングしている箇所が1つでもあれば、Marker2Dへの置き換えを試してみてください。「位置を触るのにコードを開かなくていい」快適さは、一度知ると戻れません。

さらに学ぶために