Unityユーザーが最初に戸惑うGodotの概念(シーン/ノード)

Unityに慣れていると、Godotを触った瞬間にまずシーンノードで首をかしげがちです。私も最初は「GameObjectはどこ?」「Prefabは?」となりました。

この記事は、その最初のつまずきを乗り越えるための内容です。Godot4系を前提に、Unity用語との対応関係考え方のコツをまとめ直しました。

この記事でわかること

  • Godotのシーン/ノードがUnityのGameObject/Componentとどう違うかが分かります。
  • Prefab ≒ PackedSceneAdditiveシーン ≒ シーンのインスタンス化など、手元の作業に落とし込めます。
  • ライフサイクルやSignal、Autoloadなど、移行でハマりにくくなる実務の要所を押さえます。
Godotは「ノードを積み木みたいに組んで、それ丸ごとをシーンとして使い回す」エンジンです。

1) 「シーン/ノード」は「Prefab+階層」に近い

まずは対応関係のイメージから。ざっくりこんな感じです。

Unity Godot
GameObject Node(例:Node2D、Sprite2D、Area2D など)
ヒエラルキー ノードツリー(親子関係)
Prefab PackedScene(.tscn)
Additiveシーン シーンのインスタンス化(PackedScene.instantiate)
DontDestroyOnLoad Autoload(Project Settings → AutoLoad)
Componentスクリプト ノードに付けるスクリプト(GDScript/C#)
UnityEvent/Delegate Signal

UnityだとGameObjectに機能を付ける設計ですが、Godotは機能つきのノードを直接並べていくイメージです。UIでも敵キャラでも弾1発でも、それ自体が1つのシーンにできます。最初は大胆になんでもシーン化してOKです。

2) ノードは「機能つきの実体」

2Dアクションのプレイヤーなら、ベースにCharacterBody2Dを置いて、子にSprite2D、CollisionShape2D、Camera2Dなどをぶら下げます。スクリプトは必要なノードに素直に1本ずつ。雰囲気としては「GameObject+主要コンポーネントが1枚岩になっている」感じです。

# Player.gd(CharacterBody2D にアタッチ)
extends CharacterBody2D
const SPEED := 200.0


func _physics_process(delta: float) -> void:
var dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = dir * SPEED
move_and_slide()

3) PackedSceneとインスタンス化:Prefab運用とどう違う?

UnityのInstantiate(prefab)に相当するのが、GodotのPackedScene.instantiate()です。.tscnをロードして、欲しいときに実体化→ツリーに差し込むだけ。

# 弾をスポーン(親ノードにアタッチ)
@onready var bullet_scene: PackedScene = preload("res://scenes/Bullet.tscn")


func spawn_bullet(global_pos: Vector2) -> void:
var b = bullet_scene.instantiate()
add_child(b)
b.global_position = global_pos

シーンは入れ子にできます。敵1体もUIの1ウィジェットもエフェクトも、ぜんぶシーン。小さく作って組み合わせていくのがコツです。

4) 参照はGetComponentではなく「ノードパス」

GetComponent<T>()はありません。代わりに、ツリー上の位置(ノードパス)で取得します。型注釈を付けると補完も効いて安心。

@onready var anim: AnimationPlayer = $AnimationPlayer
@onready var area: Area2D = $Hitbox

横のノードを直参照しすぎると絡まりやすいので、連携はSignalに逃がすとラクです。

5) ライフサイクル対応表

Unity Godot 使いどころ
Awake enter_tree() ツリーに入った直後。早すぎる初期化はここだとこけることも
Start ready()_ 子ノードがそろった後。初期化の定番
Update process(delta) 毎フレーム(描画に同期)
FixedUpdate physics_process(delta) 物理フレーム固定(既定60Hz)
OnEnable/OnDisable enter_tree()/ _exit_tree() 入退場時のフック

実務的には「参照の確定は_ready() 以降」「物理はphysics_process()」の2つを覚えておけばOKです。

6) イベントはSignalでゆるくつなぐ

Signalは「発信側がイベント名を宣言→受信側が接続してコールバックを受ける」仕組み。インスペクタでもコードでもつなげます。

signal hit(damage: int)


func _on_area_entered(_other):
emit_signal("hit", 1)


func _ready():
$Enemy.connect("hit", Callable(self, "_on_enemy_hit"))


func _on_enemy_hit(dmg: int) -> void:
print("got hit:", dmg)

お互いを直接参照しないので、差し替え・テストがぐっと楽。大きめのプロジェクトほど恩恵があります。

7) シーン切り替えと永続オブジェクト:Autoload

DontDestroyOnLoadの代わりに、GodotはAutoloadでスクリプトやシーンを常駐させます。BGMやセーブ、共通データにどうぞ。

# Global.gd(Autoloadに登録)
extends Node
var score := 0

どこからでもGlobal.scoreのようにアクセスできます。やりすぎるとなんでも屋になりがちなので、役割はほどほどに。

8) 入力・物理・座標でよくある小さなつまずき

  • InputMap:プロジェクト>プロジェクト設定>インプットマップでアクションを登録 → Input.is_action_pressed(“jump”) の形で使います。
  • 2D/3Dのノードは別物:2DはNode2D系、3DはNode3D系。2DはY軸が下向き正です。
  • 物理_physics_process()とmove_and_slide()をセットで。フレーム不一致で挙動がぶれたらまずここを確認。
  • 座標:global_positionとpositionの取り違えは定番の事故。弾の発射位置などは global_positionが安心。

9) よくある質問(Unity視点)

Q. Prefab Variantはありますか?
A. Godotはシーン継承や、インスタンス化後の差分編集で近い運用ができます。ベース.tscnを継承して局所的に差し替えるのが実用的。

Q. GetComponent相当は?
A. 構造を明示して、必要な子は@onready varで取得。横連携はSignalに寄せると絡みにくいです。

Q. ScriptableObjectは?
A. Resource(.tres/.res) が近い立ち位置。パラメータやデータ定義を外だしできます。

Q. Timeline/Animatorは?
A. AnimationPlayer/AnimationTree が担当。2DスプライトはSpriteFrames、合成や遷移は AnimationTree

小さく宣伝

記事の内容を「避けゲー」を作りながら一気に身につけたい人向けに、Udemyで講座を用意しています。GDScriptの基礎 → 当たり判定 → 演出 → Windows向け出力まで、完成プロジェクト付きで伴走します。

【Godot】初心者向けアクションゲーム(避けゲー)の開発入門【Windows向け】

著者プロフィール
うんくん

IT系に特化した記事がメインです。(Unity多め。)
Udemy講師もやっています。よろしくお願いします。

※Amazonのアソシエイトとして、当メディアは適格販売により収入を得ています。

うんくんをフォローする
Godot
シェアする
うんくんをフォローする