Godot Engine v4.4からv4.7にプロジェクトをアップデートした際のメモ

Godot Engine v4.4で開発していたゲームをv4.7にアップデートした際,.tscnファイルのフォーマットが変更されて,シーンを保存するだけでGitの差分が発生してしまって大変面倒くさかったため,対応をメモ.

発生した事象

Godot EngineのIDE上でシーンを保存した際,.tscnファイルに以下のような差分が現れた:

-[gd_scene load_steps=4 format=3 uid="uid://bsgf7j36jrcwm"]
+[gd_scene format=3 uid="uid://bsgf7j36jrcwm"]

...

-[node name="StaticBody3D" type="StaticBody3D" parent="Floor" index="0"]
+[node name="StaticBody3D" type="StaticBody3D" parent="Floor" index="0" unique_id=393512056]

原因

.tscnファイルのフォーマットのドキュメントを参照したところ,以下の2つの記述が怪しかった:

The file descriptor looks like [gd_scene format=3 uid="uid://cecaux1sm7mo0"] and should be the first entry in the file. Note that scenes saved before Godot 4.6 will also have a load_steps=<int> attribute in the file descriptor. This attribute is now deprecated and should be ignored if present.

Note that unique_id is only present in scenes saved with Godot 4.6 or later. Therefore, it is not guaranteed to be present.

どうやらv4.6以降では,以下の仕様変更があったらしい:

  1. [gd_scene]という項目にあったload_steps=<int>という項目が廃止されている
  2. [node]にunique_idというプロパティが追加されている

2.について詳しく調べたところ,uid=<String>というプロパティがunique_id=<int>に変更されていた模様.Migrating to a new versionにそんな説明無かった気がするが….

対応

全ての.tscnファイルを手作業で再保存し,プロジェクトフォルダ内の.tscnファイルの内容を検査するPythonスクリプトを用意してチェックした.

以下のPythonスクリプトにより,全ての.tscnファイルにunique_idが出現しているかを簡易チェックできる. IDE上でシーンを再保存する前は各ファイル内にはunique_idが存在せず,全てのシーンの再保存後は各ファイル内にunique_idが存在することを確認できる.

# Source - https://stackoverflow.com/a/35188365
# Posted by Roland Smith
# Retrieved 2026-10-06, License - CC BY-SA 3.0
# Modified by chqwa

import os
import re

# rx = re.compile(r"\[node .*uid=\"(.*)\".*\]")
rx = re.compile(r"\[node .*unique_id=([0-9]+).*\]")

for root, dirs, files in os.walk('.'):
    for filename in files:
        base, ext = os.path.splitext(filename)
        if ext == ".tscn":
            filepath = os.path.join(root, filename)
            print(f"{filepath} ---------------------")
            with open(filepath, encoding="utf-8") as df:
                data = df.read()
            for match in rx.finditer(data):
                # Use the MatchObject as you like
                print(match.span(), match.group(1))

おわり