Godotのリストに戻る

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

作成: 2025-06-20更新: 2025-06-20ノード・シーンブログ記事を読む

概要

Marker2Dは、位置情報(Transform)のみを持つ最も軽量な2Dノードです。レンダリングや物理演算の負荷がないため、ゲーム全体を管理するスクリプトのホストとして最適です。

Unityで空のGameObjectを使っていた経験がある方には、Marker2Dはまさにそれに相当するノードです。最初は「なぜ位置情報だけのノードが必要なのか?」と疑問でしたが、GameManagerやSpawnManagerなどの管理スクリプトを整理する際に、その価値がよくわかりました。

Marker2Dの特徴

  • 最小限の機能: 位置情報のみ(描画・物理なし)
  • 軽量: メモリ使用量が最小
  • エディタ表示: シーンエディタでアイコン表示(実行時は非表示)
  • Unityの空GameObject相当: 管理用途に特化

基本的な使い方

GameManagerの実装

# GameManager.gd (Marker2Dにアタッチ)
extends Marker2D

signal game_started
signal game_over
signal score_updated(new_score)

var score: int = 0
var is_game_active: bool = false
var current_level: int = 1

func _ready():
    # シーンツリーのルート近くに配置
    process_mode = Node.PROCESS_MODE_ALWAYS

func start_game():
    is_game_active = true
    score = 0
    emit_signal("game_started")

func add_score(points: int):
    score += points
    emit_signal("score_updated", score)

func end_game():
    is_game_active = false
    emit_signal("game_over")

PuzzleManagerの実装

# PuzzleManager.gd
extends Marker2D

var switches_activated: int = 0
var total_switches: int = 3
@onready var door = $"../Door"

func _ready():
    # 全てのスイッチを検索して接続
    for switch in get_tree().get_nodes_in_group("puzzle_switches"):
        switch.activated.connect(_on_switch_activated)

func _on_switch_activated():
    switches_activated += 1
    
    if switches_activated >= total_switches:
        solve_puzzle()

func solve_puzzle():
    door.open()
    print("パズル解決!")

実践的な活用例

SpawnManagerの実装

# SpawnManager.gd
extends Marker2D

@export var enemy_scene: PackedScene
@export var spawn_interval: float = 2.0
@export var spawn_points: Array[Marker2D] = []

var spawn_timer: Timer

func _ready():
    setup_spawn_timer()

func setup_spawn_timer():
    spawn_timer = Timer.new()
    spawn_timer.wait_time = spawn_interval
    spawn_timer.timeout.connect(spawn_enemy)
    add_child(spawn_timer)
    spawn_timer.start()

func spawn_enemy():
    if spawn_points.is_empty():
        return
    
    var spawn_point = spawn_points.pick_random()
    var enemy = enemy_scene.instantiate()
    get_parent().add_child(enemy)
    enemy.global_position = spawn_point.global_position

EventManagerの実装

# EventManager.gd (Autoloadとして使用)
extends Marker2D

# グローバルイベントシステム
signal player_died
signal level_completed
signal item_collected(item_type)
signal dialog_started
signal dialog_ended

var event_queue: Array = []

func trigger_event(event_name: String, data = null):
    event_queue.append({
        "name": event_name,
        "data": data,
        "timestamp": Time.get_ticks_msec()
    })
    
    # イベントに応じた処理
    match event_name:
        "player_death":
            emit_signal("player_died")
        "level_complete":
            emit_signal("level_completed")

Marker2Dを使うべき場面

適している用途

  • ゲーム全体の状態管理
  • イベントシステム
  • スポーン地点の管理
  • パズルロジック
  • タイマー管理
  • データ集計

適さない用途

  • 視覚的な要素が必要な場合 → Sprite2D
  • 物理判定が必要な場合 → Area2D
  • UI要素 → Control系ノード

組織化のベストプラクティス

シーン構造の例

Main (Node2D)
├── Managers (Node2D)
│   ├── GameManager (Marker2D)
│   ├── SpawnManager (Marker2D)
│   ├── AudioManager (Marker2D)
│   └── SaveManager (Marker2D)
├── World (Node2D)
│   ├── Player
│   ├── Enemies
│   └── Environment
└── UI (CanvasLayer)

マネージャー間の通信

# GameManager.gd
extends Marker2D

@onready var spawn_manager = $"../SpawnManager"
@onready var audio_manager = $"../AudioManager"

func start_game():
    spawn_manager.enable_spawning()
    audio_manager.play_bgm("game_theme")

func pause_game():
    spawn_manager.disable_spawning()
    audio_manager.pause_bgm()

パフォーマンスの比較

ノードタイプメモリ使用処理負荷用途
Marker2D最小なし管理・ロジック
Node2D基本的な2Dノード
Sprite2D描画あり画像表示
CharacterBody2D物理演算ありキャラクター

デバッグのコツ

# デバッグ表示の追加
extends Marker2D

@export var debug_mode: bool = false

func _draw():
    if debug_mode and Engine.is_editor_hint():
        # エディタでのみ表示
        draw_circle(Vector2.ZERO, 10, Color.RED)
        draw_string(get_theme_default_font(), 
                   Vector2(15, 5), 
                   name, 
                   HORIZONTAL_ALIGNMENT_LEFT, 
                   -1, 
                   16)

実装して学んだこと

Marker2Dを管理ノードとして使うようになってから、プロジェクトの構造が非常にすっきりしました。以前はNode2DやSprite2Dに管理スクリプトをアタッチしていましたが、「このスプライトは何のためにあるの?」という混乱がありました。

特に良かったのは、マネージャー系のノードを「Managers」フォルダにまとめられるようになったことです。シーンツリーが整理され、他の開発者(あるいは未来の自分)が見ても、どこに何があるかすぐに理解できるようになりました。

また、Marker2Dは本当に軽量なので、大量に使ってもパフォーマンスへの影響がほとんどありません。スポーンポイントなどにも気軽に使えるのが便利です。