「敵の出現位置」「弾の発射位置」「エフェクトを出す場所」——ゲームには、決まった 座標 を扱いたい場面が山ほどあります。これをスクリプトに Vector2(150, 300) と直書きしてしまうと、位置を少し動かしたいだけでコードを開いて数値を打ち直す羽目になり、微調整のたびに消耗します。
この面倒を解消してくれるのが Marker2D ノードで す。座標を コードから切り離してエディタ上の「目印」 として置けるので、キャラクターを動かす感覚でドラッグして位置を決められます。この記事では、Marker2Dの基本から、スポーン地点や武器のマズル管理といった実践的な使い方までを解説します。
この記事でわかること
- Marker2D とは(Node2Dとの違いと、旧Position2Dとの関係)
@exportで スポーン地点にデータを持たせる 実践的な使い方global_position/global_rotationで 追従する基準点 を作る- Marker2Dを 散らからせず整理 するコツ
Marker2Dとは? Node2Dとの違い
Marker2D は、2D空間の「目印」として使う、とても軽量なノードです。中身は Node2D とほぼ同じですが、決定的な違いが1つあります。 エディタ上に常に十字のギズモが表示される ことです。

素の 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 グループに入れておき、管理側からまとめて読み取ります。

# 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ならワールド座標で正しく出せます。
キャラクターに追従する基準点(マズル)を作る
銃口、剣の先、杖の先端、足元——「キャラクターの特定部位」を基準にした処 理も、Marker2Dの得意分野です。キャラクターの子として置けば、 キャラの移動・回転に自動で追従 します。

プレイヤーシーンで、スプライトの子に 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の「見たまま編集」の利点が消える |
Marker2D・Marker2D2 のような汎用名 | PlayerSpawn・Muzzle・BossEntry など 役割が分かる名前 を付ける |
| ルート直下にバラバラに置く | SpawnPoints・EffectAnchors などの空のNode2Dに まとめて整理 する |
子マーカーで position を使う | ワールド座標が欲しいなら必ず global_position を使う(position は親からの相対座標) |
特に重要なのが position と global_position の違い です。子ノードの position は親から見た相対座標なので、親が動いたり回ったりすると意図しない位置になります。

スポーンや発射のように「画面上のこの場所」を指したいときは、 必ず global_position を使えば、親の移動・回転に影響されず正しいワールド座標が得られます。
Marker2Dの整理も効いてきます。関連するマーカーを親のNode2Dでまとめておくと、 親ごとまとめて移動・非表示 にでき、シーンツリーもすっきりします。

おまけ:先に知っておくと良いこと
Marker2Dでの座標管理に慣れたら、次はこのあたりが視野に入ります。
- 「線」の管理は Path2D / Curve2D :Marker2Dが「点」の管理なら、
Path2DとCurve2Dは「線(経路)」の管理です。敵の巡回ルートやカメラの移動パスを定義できます。マーカーで置いた点を経路に発展させる、という流れが自然です。 - 配置情報からレベルを自動生成 :
_ready()でマーカーの情報を読み、そこからレベル全体を組み立てるプロシージャルな作りにもつながります。 - 十字では物足りないなら独自ギズモ :
@toolスクリプトと_draw()で、エディタ上に自作の補助アイコンを描くこともできます。
まとめ
- Marker2D は「位置の目印」。中身はNode2Dとほぼ同じだが、 エディタに十字が常時表示 されるのが強み
- Godot 3の
Position2Dは Godot 4でMarker2Dにリネーム された @exportでスポーン地点に データを持たせ れば、デザイナーがインスペクタだけで湧きを調整できる- キャラの子に置けば 移動・回転に追従 し、
global_position/global_rotationで正しい発射位置・角度が得られる - 座標はコードで動かさず エディタで調整 、取得は
global_position、整理は 親Node2Dでグループ化
座標をハードコーディングしている箇所が1つでもあれば、Marker2Dへの置き換えを試してみてください。「位置を触るのにコードを開かなくていい」快適さは、一度知ると戻れません。
さらに学ぶために
- 「シーン」と「ノード」の基本を徹底解説 ——スポーンの土台になるインスタンス化
- グループによる柔軟なオブジェクト判定 ——スポーン地点をグループでまとめて取得する
- シグナルによるノード間の連携 ——スポーンやヒットを他ノードへ通知する
- Godot公式ドキュメント:Marker2D ——Marker2Dの一次情報