Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

TSCN 檔案格式

TSCN (Text SCeNe) 檔案格式代表 Godot 內的單一節點樹。TSCN 檔具有人類可讀取且適合用於版本控制系統的特點。匯出時,TSCN 檔會被編譯為保存在 .import 資料夾內的二進位格式 .scn 檔,以減少資料大小並加速載入。

ESCN (Exported SCeNe) 的檔案格式與 TSCN 檔案格式完全相容,但對 Godot 來說則表示該檔案是從另一個程式匯出的,且無法從 Godot 內進行編輯。

為了使檔案更加緊湊,等於預設值的屬性不會儲存在場景/資源檔案中。可以手動寫入它們,但在儲存檔案時它們將被丟棄。

若需要完整的說明,請參考 ResourceFormatLoaderText 中負責剖析該格式的 resource_format_text.cpp 檔案。

備註

Godot 4 中的場景和資源檔案格式發生了顯著變化,引入了基於字串的 UID 來取代差異量整數 ID。

與Godot 3 相比,網格、骨架和動畫資料的儲存方式也有所不同。您可以閱讀本文中的一些變更:「4.0 的動畫資料返工<https://godotengine.org/article/animation-data- redesign- 40/>`__

使用 Godot 4.x 儲存的場景和資源在其標頭中包含“format=3”,而 Godot 3.x 使用“format=2”代替。

檔案結構

在 TSCN 檔中主要有五個區塊:

  1. 檔案描述元

  2. 外部資源

  3. 內部資源

  4. 節點

  5. 連接

檔案描述資源類似 [gd_scene load_steps=1 format=2] ,且應放在檔案的最前面。load_steps 參數 (理論上) 應為該檔案內含資源的數量。但,實務上,該值為多少應該無影響。

uid 是代表場景的基於字串的唯一識別碼。引擎使用它來追蹤移動的檔案,即使編輯器關閉時也是如此。腳本還可以使用「uid://」路徑前綴來載入基於 UID 的資源,以避免依賴檔案系統路徑。這使得可以在專案中移動檔案,但仍然能夠在腳本中加載它,而無需修改腳本。 Godot 不使用外部檔案來追蹤 ID,這意味著專案內不需要中央元資料儲存位置。有關詳細信息,請參閱“此拉取請求 <https://github.com/godotengine/godot/pull/50786>”。

這些區塊應照會順序排列,但要區分出各個段落可能有點困難。在這些區塊間的主要差異就是各個段落中所有專案標題的第一項元素。舉例來說,所有外部資源的標題都應以 [ext_resource ......] 開頭。

TSCN 檔案可以包含以分號 (;) 開頭的單行註解。但,以 Godot 編輯器保存時會移除註解。

檔案內的專案

當 resource_type 為下列其一時,標題看起來會像 [<resource_type> key=value key=value key=value ...]

  • ext_resource

  • sub_resource

  • node

  • connection

在每個標題後都會有 0 或多個 key = value 索引鍵/值組。數值可以是複雜的資料型別,如 Array, Transform, Color …等。舉例來說,Spatial 節點可能會類似:

[node name="Cube" type="Node3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 2, 3)

場景樹

場景樹是由……節點構成的!各個節點的標題都是由名稱、母節點與 (大多數時候還會有) 型別所組成的。如, [node type="Camera" name="PlayerCamera" parent="Player/Head"]

其他有效的關鍵字包含:

  • instance

  • instance_placeholder

  • owner

  • ``index``(設定在樹中的出現順序。不存在的話,繼承節點優先於普通節點)

  • groups

檔案中的第一個節點同時也是根節點,該節點的標題不得包含 parent=Path/To/Node 專案。所有的場景檔案都必須只有 一個 根節點,否則 Godot 將無法匯入該檔案。其他結點的母級節點必須使用絕對路徑,但不得包含場景的根名稱。若某個節點為場景根節點的直接子節點,則路徑為 「 . 」`。下列為範例場景樹 (但無任何節點內容):

[node name="Player" type="Node3D"]                    ; The scene root
[node name="Arm" type="Node3D" parent="."]            ; Parented to the scene root
[node name="Hand" type="Node3D" parent="Arm"]         ; Child of "Arm"
[node name="Finger" type="Node3D" parent="Arm/Hand"]  ; Child of "Hand"

小訣竅

為了使檔案結構更容易掌握,您可以使用任何給定的節點或資源來保存檔案,然後在外部編輯器中自行檢查它。您還可以在 Godot 編輯器中進行差異量更改,並在啟用自動重新加載的“.tscn”或“.tres”檔案上保持外部文字編輯器打開,以查看發生的更改。

以下是一個場景範例,其中包含基於 RigidBody3D 的球,具有碰撞、視覺效果(網格 + 燈光)以及作為 RigidBody3D 父級的相機:

[gd_scene load_steps=4 format=3 uid="uid://cecaux1sm7mo0"]

[sub_resource type="SphereShape3D" id="SphereShape3D_tj6p1"]

[sub_resource type="SphereMesh" id="SphereMesh_4w3ye"]

[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_k54se"]
albedo_color = Color(1, 0.639216, 0.309804, 1)

[node name="Ball" type="RigidBody3D"]

[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("SphereShape3D_tj6p1")

[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("SphereMesh_4w3ye")
surface_material_override/0 = SubResource("StandardMaterial3D_k54se")

[node name="OmniLight3D" type="OmniLight3D" parent="."]
light_color = Color(1, 0.698039, 0.321569, 1)
omni_range = 10.0

[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.939693, 0.34202, 0, -0.34202, 0.939693, 0, 1, 3)

NodePath

使用樹狀結構並無法代表完整的場景。Godot 使用 NodePath(Path/To/Node) 結構來參照場景樹中的某個節點或節點的屬性。舉例來說,MeshInstance 使用 NodePoint() 來指向其骨架。同樣地,動畫軌使用 NodePath() 來指向動畫的節點屬性。

使用樹狀結構並無法代表完整的場景。Godot 使用 NodePath(Path/To/Node) 結構來參照場景樹中的某個節點或節點的屬性。舉例來說,MeshInstance 使用 NodePoint() 來指向其骨架。同樣地,動畫軌使用 NodePath() 來指向動畫的節點屬性。

NodePath 也可以使用 :property_name 字尾指向屬性,甚至指向向量、變換和顏色型別的特定元件。動畫資源使用它來指向要製作動畫的特定屬性。例如, NodePath("MeshInstance3D:scale.x") 指向 MeshInstance3D 中``scale`` Vector3 屬性的``x`` 元件。

例如,名為「mesh」的 MeshInstance3D 節點中的「骨骼」屬性指向其父節點「Armature01」:

[node name="mesh" type="MeshInstance3D" parent="Armature01"]
skeleton = NodePath("..")

骨架

Skeleton 節點繼承自 Spatial 節點,但同時 Skeleton 也以 bones/Id/Attribute=Value 這樣的格式來儲存一組索引鍵/值格式的骨頭列表。骨頭屬性由下列這幾個屬性構成:

  • position:Vector3

  • Rotation

  • scale:Vector3

這些屬性都是可選的。例如,骨骼可能只定義“位置”或“旋轉”,而不定義其他屬性。

下列為有兩個骨頭的骨骼節點範例:

[node name="Skeleton3D" type="Skeleton3D" parent="PlayerModel/Robot_Skeleton" index="0"]
bones/1/position = Vector3(0.114471, 2.19771, -0.197845)
bones/1/rotation = Quaternion(0.191422, -0.0471201, -0.00831942, 0.980341)
bones/2/position = Vector3(-2.59096e-05, 0.236002, 0.000347473)
bones/2/rotation = Quaternion(-0.0580488, 0.0310587, -0.0085914, 0.997794)
bones/2/scale = Vector3(0.9276, 0.9276, 0.9276)

BoneAttachment3D

BoneAttachment 節點為用來描述某個節點屬於某 Skeleton 節點的單一骨頭之子節點。BoneAttachment 有一個 bone_name=NameOfBone 屬性,而對應為母節點的骨頭之 bound_children 列表中則有 BoneAttachment 節點。

下列為 Skeleton 中有骨頭母節點的 MeshInstance 範例:

[node name="GunBone" type="BoneAttachment3D" parent="PlayerModel/Robot_Skeleton/Skeleton3D" index="5"]
transform = Transform3D(0.333531, 0.128981, -0.933896, 0.567174, 0.763886, 0.308015, 0.753209, -0.632331, 0.181604, -0.323915, 1.07098, 0.0497144)
bone_name = "hand.R"
bone_idx = 55

[node name="ShootFrom" type="Marker3D" parent="PlayerModel/Robot_Skeleton/Skeleton3D/GunBone"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0)

AnimationPlayer

class_AnimationPlayer 節點與儲存在 class_AnimationLibrary 資源中的一個或多個動畫庫搭配使用。動畫庫是各個 Animation 資源的集合,其結構記錄在 此處

動畫本身和動畫庫之間的這種分離是在 Godot 4 中完成的,以便動畫可以與 3D 網格分開匯入,這是 3D 動畫軟體中的常見工作流程。有關詳細信息,請參閱“原始拉取請求 <https://github.com/godotengine/godot/pull/59980>”。

如果庫名稱為空,則它充當此 AnimationPlayer 的唯一動畫來源。這允許直接使用``<animation_name>``從腳本播放動畫。如果您命名庫,則必須將其播放為``<library_name>/<animation_name>``。如果您不想使用多個動畫庫,這可以確保向後相容性並保留現有的工作流程。

資源

資源是組成各個節點的元件。舉例來說,MeshInstance 節點中會有附帶的 ArrayMesh 資源。該 ArrayMesh 資源可以在 TSCN 檔的內部或外部。

對資源的引用由資源標題中基於字串的唯一 ID 處理。這與每個外部資源也具有的「uid」屬性不同(但子資源沒有)。

資源的參照是以資源標題中的 id 數字來參照的。外部資源與內部資源分別使用 ExtResource(id)SubResource(id) 來參照。由於用來參照內部與外部資源有不同的方法,因此同一個 ID 可能參照到不同的內部或外部資源。

舉例來說,若要參照到資源 [ext_resource id=3 type="PackedScene" path=....] ,則可使用 ExtResource(3)

外部資源

外部資源會連結不包含 TSCN 檔自身的資源。外部資源由路徑、型別與 ID 組成。

Godot 會產生相對於資源目錄的絕對路徑,並以 res:// 開頭。但也可以使用相對於 TSCN 檔位置的相對路徑。

一些外部資源的範例:

[ext_resource type="Texture2D" uid="uid://ccbm14ebjmpy1" path="res://gradient.tres" id="2_eorut"]
[ext_resource type="Material" uid="uid://c4cp0al3ljsjv" path="material.tres" id="1_7bt6s"]

與 TSCN 檔類似,TRES 檔可以包含使用分號 (;) 開頭的單行註解。但,在使用 Godot 編輯器保存資源時,註解會被移除。

內部資源

一個 TSCN 檔可以包含網格、材質與其他資料。這些資料都放在 TSCN 檔中的 內部資源 區塊中。內部資源區塊的標題看起來與外部資源的標題類似,但內部資源的標題不含路徑。內部資源中的各個標題中也有 key=value 索引鍵/值組。舉例來說,膠囊型碰撞區域會像這樣:

[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_fdxgg"]
radius = 1.0
height = 3.0

有的內部資源會包含指向另一個內部資源的連結 (如網格會具有材質)。這種情況下,被參照的資源的資源必須要放在參照 之前 。這表示,在 TSCN 檔中,要注意檔案內部資源區塊的順序。

ArrayMesh

ArrayMesh 由包含在「_surfaces」陣列中的多個表面組成(注意前導底線)。每個表面的資料都儲存在具有以下鍵的字典中:

  • aabb:計算的可見性軸對齊邊界框。 Mesh.PrimitiveType Godot 列舉。 0 = 點,1 = 線,2 = 線帶,3 = 三角形(最常見),4 = 三角形帶。

  • attribute_data:頂點屬性資料,例如法線、切線、頂點顏色、UV1、UV2 和自訂頂點資料。

  • bone_aabbs:每個骨骼的軸對齊邊界框以提高可見性。

  • format:表面的緩衝區格式。

  • index_count:表面中索引的數量。這必須與“index_data”的大小相符。

  • “index_data”:索參資料,它決定從“vertex_data”中繪製哪些頂點。

  • lods:細節變化的級別,儲存為陣列。每個 LOD 等級代表陣列中的兩個值。第一個值是 LOD 等級最適合的螢幕空間百分比(邊緣長度);第二個值是應為給定 LOD 等級繪製的索引列表。

  • material:繪製表面時所使用的材質。

  • name:表面的名稱。這可以在腳本中使用,並從 3D DCC 匯入。

  • primitive:表面的原始型別,配對

  • skin_data:骨骼重量資料。

  • vertex_count:表面中的頂點數。這必須與“vertex_data”的大小相符。

  • vertex_data:頂點位置資料。

這是保存到自己的 .tres 檔案中的 ArrayMesh 的範例。為了簡潔起見,一些字段被縮短為“...”:

[gd_resource type="ArrayMesh" load_steps=2 format=3 uid="uid://dww8o7hsqrhx5"]

[ext_resource type="Material" path="res://player/model/playerobot.tres" id="1_r3bjq"]

[resource]
resource_name = "player_Sphere_016"
_surfaces = [{
"aabb": AABB(-0.207928, 1.21409, -0.14545, 0.415856, 0.226569, 0.223374),
"attribute_data": PackedByteArray(63, 121, ..., 117, 63),
"bone_aabbs": [AABB(0, 0, 0, -1, -1, -1), ..., AABB(-0.207928, 1.21409, -0.14545, 0.134291, 0.226569, 0.223374)],
"format": 7191,
"index_count": 1224,
"index_data": PackedByteArray(30, 0, ..., 150, 4),
"lods": [0.0382013, PackedByteArray(33, 1, ..., 150, 4)],
"material": ExtResource("1_r3bjq"),
"name": "playerobot",
"primitive": 3,
"skin_data": PackedByteArray(15, 0, ..., 0, 0),
"vertex_count": 1250,
"vertex_data": PackedByteArray(196, 169, ..., 11, 38)
}]
blend_shape_mode = 0

動畫

有下列事項需注意:

  • 「length」:動畫的長度(以秒為單位)。請注意,關鍵影格可以放置在「[0;」之外。 length]`` 間隔,但根據所選的插值模式,它們可能沒有效果。

  • loop_mode0 = 無循環,1 = 環繞循環,2 = 箝位循環。

  • step:在編輯器中編輯此動畫時使用的步長。這只在編輯器中使用;它不會以任何方式影響動畫播放。

每個軌道都是由一組索引鍵/值配對所組成的,其格式為 tracks/Id/Attribute 。每個軌道都包含了:

  • type:軌道的型別。這定義了該軌道可以動畫化哪種屬性,以及如何在編輯器中向使用者公開它。有效型別為「value」(一般屬性軌道)、「position_3d」、「rotation_3d」、「scale_3d」、「blend_shape」(最佳化的 3D 動畫軌道)、「method」(方法呼叫軌道)、``bezier``(貝塞爾曲線軌道)、``audio``(音頻播放軌道)、``animation``(播放其他動畫的軌道)。

  • 「imported」:如果軌道是從匯入的 3D 場景建立的,則為「true」;如果是由使用者在 Godot 編輯器中或使用腳本手動建立的,則為「false」。

  • enabled:如果軌道有效則為``true``,如果在編輯器中停用則為``false``。

  • path:將受軌道影響的節點屬性的路徑。該屬性寫在節點路徑後面,並使用 : 分隔符號。

  • interp:要使用的內插模式。 0 = 最近,1 = 線性,2 = 立方,3 = 線性角度,4 = 立方角度。

  • 「loop_wrap」:如果軌道設計為在動畫循環時環繞,則為「true」;如果軌道夾在第一個/最後一個關鍵影格,則為「false」。

  • keys:動畫軌道的值。此屬性的結構取決於“type”。

這是一個包含 AnimationPlayer 的場景,它使用通用屬性軌道隨時間縮小立方體。未使用 AnimationLibrary 工作流程,因此動畫庫的名稱為空(但動畫仍指定為「scale_down」名稱)。請注意,為了簡潔起見,沒有在此 AnimationPlayer 中建立「RESET」軌道:

[gd_scene load_steps=4 format=3 uid="uid://cdyt3nktp6y6"]

[sub_resource type="Animation" id="Animation_r2qdp"]
resource_name = "scale_down"
length = 1.5
loop_mode = 2
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(1, 1, 1), Vector3(0, 0, 0)]
}

[sub_resource type="AnimationLibrary" id="AnimationLibrary_4qx36"]
_data = {
"scale_down": SubResource("Animation_r2qdp")
}

[sub_resource type="BoxMesh" id="BoxMesh_u688r"]

[node name="Node3D" type="Node3D"]

[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "scale_down"
libraries = {
"": SubResource("AnimationLibrary_4qx36")
}

[node name="Box" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_u688r")

對於通用屬性「value」軌道,「keys」是一個字典,包含 3 個陣列,其位置位於「times」(PackedFloat32Array)中,緩動值位於「transitions」(PackedFloat32Array)中,值位於「values」中`` `(陣列)。還有一個附加的“update”屬性,它是一個整數,其值“0”=連續,“1”=離散,“2”=捕獲。

這是使用 3D 位置和 3D 旋轉軌道的第二個動畫資源。這些軌道(除了 3D Scale 軌道)取代了 Godot 3 中的 Transform 軌道。它們針對快速播放進行了最佳化,並且可以選擇壓縮。

這些最佳化軌道型別的缺點是它們無法使用自訂緩動值。相反,所有關鍵影格都使用線性插值。也就是說,您仍然可以透過更改軌道的插值模式來選擇對給定軌道中的所有關鍵影格使用最近插值或三次插值。

[sub_resource type="Animation" id="Animation_r2qdp"]
resource_name = "move_and_rotate"
length = 1.5
loop_mode = 2
step = 0.05
tracks/0/type = "position_3d"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = PackedFloat32Array(0, 1, 0, 0, 0, 1.5, 1, 1.5, 1, 0)
tracks/1/type = "rotation_3d"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Box")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = PackedFloat32Array(0, 1, 0.211, -0.047, 0.211, 0.953, 1.5, 1, 0.005, 0.976, -0.216, 0.022)

對於 3D 位置、旋轉和縮放軌跡,「keys」是一個 PackedFloat32Array,所有值都儲存在一個序列中。

在下面的視覺指南中,「T」是自動畫開始以來關鍵影格的時間(以秒為單位),「E」是關鍵影格的轉換(目前始終為「1」)。對於 3D 位置和比例軌道,XYZ 是 Vector3 的座標。對於 3D 旋轉軌跡,「X」、「Y」、「Z」 和「W」 是四元數的座標。

# For 3D position and scale, which use Vector3:
tracks/<id>/keys = PackedFloat32Array(T, E,   X, Y, Z,      T, E,   X, Y, Z, ...)

# For 3D rotation, which use Quaternion:
tracks/<id>/keys = PackedFloat32Array(T, E,   X, Y, Z, W,      T, E,   X, Y, Z, W, ...)