TSCN文件格式
TSCN(文本场景)文件格式表示Godot内部的单个场景树。其优点是易于阅读,并且易于版本控制系统进行管理。导入期间,TSCN文件被编译为存储在 .import
文件夹中的二进制 .scn
文件。这样可以减小数据大小并加快加载速度。
ESCN(导出场景)文件格式与TSCN文件格式相同,但是用于向Godot指示该文件已从另一个程序导出,并且不应由用户在Godot内部进行编辑。
对于那些寻求完整描述的人来说,解析在 resource_format_text.cpp 文件的 ResourceFormatLoaderText
类中进行处理。
文件结构
TSCN文件中有五个主要部分:
- 文件描述符
- 外部资源
- 内部资源
- 节点
- 连接
文件描述符看起来像 [gd_scene load_steps=1 format=2]
,应该是文件中的第一项。从理论上讲, load_steps
参数应该是文件中资源的数量。但是,实际上,它的值似乎无关紧要。
这些部分应按顺序显示,但是可能很难区分它们。它们之间的唯一区别是该部分中所有项目的标题中的第一个元素。例如,所有外部资源的标题都应以 [ext_resource .....]
开头。
TSCN文件可能包含以分号(;
)开头的单行注释。但是,使用Godot编辑器保存文件时,注释将被丢弃。
文件中的条目
标题看起来像 [<resource_type> key=value key=value key=value ...]
,其中 resource_type
是以下之一:
ext_resource
sub_resource
node
connection
在每个标题下方都有零个或多个 key = value
对。值可以是复杂的数据类型,例如Arrays、Transforms、Colors等。例如,一个Spatial节点如下所示:
[node name="Cube" type="Spatial" parent="."]
transform=Transform( 1.0, 0.0, 0.0 ,0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 )
场景树
场景树由……节点组成!每个节点的标题由其名称、父级和(大多数情况下)一种类型组成。例如 [node type="Camera" name="PlayerCamera" parent="Player/Head"]
其他有效的关键字包括:
instance
instance_placeholder
owner
index
(如果两个节点具有相同的名称)groups
文件中的第一个节点(也是场景根)的标题中不得包含 parent=Path/To/Node
条目。所有场景文件应完全具有 一个 场景根。否则,Godot将无法导入文件。其他节点的父路径应为绝对路径,但不应包含场景根名称。如果节点是场景根的直接子代,则路径应为 "."
。这是一个示例场景树(但没有任何节点内容):
[node name="Player" type="Spatial"] ; The scene root
[node name="Arm" parent="." type="Spatial"] ; Parented to the scene root
[node name="Hand" parent="Arm" type="Spatial"]
[node name="Finger" parent="Arm/Hand" type="Spatial"]
与内部资源类似,每个节点的文档当前不完整。幸运的是,可以很容易地找到,因为您可以简单地保存文件并将该节点包含其中。一些示例节点是:
[node type="CollisionShape" name="SphereCollision" parent="SpherePhysics"]
shape = SubResource(8)
transform = Transform( 1.0 , 0.0 , -0.0 , 0.0 , -4.371138828673793e-08 , 1.0 , -0.0 , -1.0 , -4.371138828673793e-08 ,0.0 ,0.0 ,-0.0 )
[node type="MeshInstance" name="Sphere" parent="SpherePhysics"]
mesh = SubResource(9)
transform = Transform( 1.0 , 0.0 , -0.0 , 0.0 , 1.0 , -0.0 , -0.0 , -0.0 , 1.0 ,0.0 ,0.0 ,-0.0 )
[node type="OmniLight" name="Lamp" parent="."]
light_energy = 1.0
light_specular = 1.0
transform = Transform( -0.29086464643478394 , -0.7711008191108704 , 0.5663931369781494 , -0.05518905818462372 , 0.6045246720314026 , 0.7946722507476807 , -0.9551711678504944 , 0.199883371591568 , -0.21839118003845215 ,4.076245307922363 ,7.3235554695129395 ,-1.0054539442062378 )
omni_range = 30
shadow_enabled = true
light_negative = false
light_color = Color( 1.0, 1.0, 1.0, 1.0 )
[node type="Camera" name="Camera" parent="."]
projection = 0
near = 0.10000000149011612
fov = 50
transform = Transform( 0.6859206557273865 , -0.32401350140571594 , 0.6515582203865051 , 0.0 , 0.8953956365585327 , 0.44527143239974976 , -0.7276763319969177 , -0.3054208755493164 , 0.6141703724861145 ,14.430776596069336 ,10.093015670776367 ,13.058500289916992 )
far = 100.0
节点路径
树形结构不足以代表整个场景。Godot使用 NodePath(Path/To/Node)
结构来引用该节点的属性或场景树中任何位置的另一个节点。例如,MeshInstance使用 NodePath()
指向其骨架。同样,动画轨迹使用 NodePath()
指向要动画的节点属性。
[node name="mesh" type="MeshInstance" parent="Armature001"]
mesh = SubResource(1)
skeleton = NodePath("..:")
[sub_resource id=3 type="Animation"]
...
tracks/0/type = "transform
tracks/0/path = NodePath("Cube:")
...
骨架
Skeleton节点继承了Spatial节点,但也可能具有以 bones/Id/Attribute=Value
格式在键值对中描述的骨骼列表。骨骼属性包括:
name
parent
rest
pose
enabled
bound_children
name
必须是每个骨骼的第一个属性。parent
是骨骼列表中父骨骼的索引,使用父索引,骨骼列表将构建到骨骼树中。rest
是处于其“静止(resting)”位置的骨骼的变换矩阵。pose
是姿势矩阵;以rest
为基础。bound_children
是NodePath()
的列表,该列表指向该骨骼的BoneAttachments。
具有两个骨骼的骨架节点的示例:
[node name="Skeleton" type="Skeleton" parent="Armature001" index="0"]
bones/0/name = "Bone.001"
bones/0/parent = -1
bones/0/rest = Transform( 1, 0, 0, 0, 0, -1, 0, 1, 0, 0.038694, 0.252999, 0.0877164 )
bones/0/pose = Transform( 1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
bones/0/enabled = true
bones/0/bound_children = [ ]
bones/1/name = "Bone.002"
bones/1/parent = 0
bones/1/rest = Transform( 0.0349042, 0.99939, 0.000512929, -0.721447, 0.0248417, 0.692024, 0.691589, -0.0245245, 0.721874, 0, 5.96046e-08, -1.22688 )
bones/1/pose = Transform( 1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
bones/1/enabled = true
bones/1/bound_children = [ ]
BoneAttachment
BoneAttachment节点是一个中间节点,用于描述在Skeleton节点中以单个骨骼为父节点的某些节点。BoneAttachment具有 bone_name=NameOfBone
属性,并且作为父级的相应骨骼在其 bound_children
列表中具有BoneAttachment节点。
在Skeleton中以一个骨骼为父级的一个MeshInstance的示例:
[node name="Armature" type="Skeleton" parent="."]
transform = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, -0.0219986, 0.0125825, 0.0343127)
bones/0/name = "Bone"
bones/0/parent = -1
bones/0/rest = Transform(1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0)
bones/0/pose = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0)
bones/0/enabled = true
bones/0/bound_children = [NodePath("BoneAttachment:")]
[node name="BoneAttachment" type="BoneAttachment" parent="Armature"]
bone_name = "Bone"
[node name="Cylinder" type="MeshInstance" parent="Armature/BoneAttachment"]
mesh = SubResource(1)
transform = Transform(1.0, 0.0, 0.0, 0.0, 1.86265e-09, 1.0, 0.0, -1.0, 0.0, 0.0219986, -0.0343127, 2.25595)
AnimationPlayer
AnimationPlayer用作动画库。它以 anim/Name=SubResource(ResourceId)
格式存储动画;每行都引用一个Animation资源。所有动画资源都使用AnimationPlayer的根节点。根节点存储为 root_node=NodePath(Path/To/Node)
。
[node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"]
root_node = NodePath("..")
autoplay = ""
playback_process_mode = 1
playback_default_blend_time = 0.0
playback_speed = 1.0
anims/default = SubResource( 2 )
blend_times = [ ]
资源
资源是组成节点的组件。 例如,MeshInstance节点将具有附带的ArrayMesh资源。 ArrayMesh资源可以是TSCN文件的内部或外部资源。
对资源的引用由资源标题中的 id
数字处理。外部资源和内部资源分别以 ExtResource(id)
和 SubResource(id)
引用。因为引用内部和外部资源的方法不同,所以内部和外部资源的ID可以相同。
例如,要引用资源 [ext_resource id=3 type="PackedScene" path=....]
,则应使用 ExtResource(3)
。
外部资源
外部资源是指向TSCN文件本身未包含的资源的链接。外部资源由路径、类型和ID组成。
Godot总是生成相对于资源目录的绝对路径,因此以 res://
为前缀,但是相对于TSCN文件位置的路径也有效。
一些示例外部资源是:
[ext_resource path="res://characters/player.dae" type="PackedScene" id=1]
[ext_resource path="metal.tres" type="Material" id=2]
像TSCN文件一样,TRES文件可能包含以分号(;
)开头的单行注释。但是,使用Godot编辑器保存资源时,注释将被丢弃。
内部资源
TSCN文件可以包含网格、材质和其他数据。这些包含在文件的 内部资源 部分中。内部资源的标题与外部资源的标题相似,不同之处在于它没有路径。 内部资源在每个标题下还具有 键=值
对。例如,胶囊碰撞形状如下所示:
[sub_resource type="CapsuleShape" id=2]
radius = 0.5
height = 3.0
一些内部资源包含到其他内部资源的链接(例如具有材质的网格)。在这种情况下,引用的资源必须在对其的引用 之前 出现。这意味着顺序在文件的内部资源部分中很重要。
遗憾的是,关于这些子资源的格式的文档并不完整,通过检查已保存的资源文件可以找到一些示例,但是只有通过查看Godot的源码才能找到其他示例。
ArrayMesh
ArrayMesh由多个表面组成,每个表面的格式为 surface\Index={}
。每个表面都是一组顶点和一种材质。
TSCN文件支持两种表面格式:
- 对于旧格式,每个表面都有三个基本键:
primitive
arrays
morph_arrays
primitive
是一个枚举变量,primitive=4
是被频繁使用的PRIMITIVE_TRIANGLES
。arrays
是一个二维数组,它包含:- 顶点位置数组
- 切线数组
- 顶点颜色数组
- UV数组1
- UV数组2
- 骨骼索引数组
- 骨骼权重数组
- 顶点索引数组
morph_arrays
是一个morph数组。每个morph恰好一个没有顶点索引数组的arrays
。
ArrayMesh的一个示例:
[sub_resource id=1 type="ArrayMesh"]
surfaces/0 = {
"primitive":4,
"arrays":[
Vector3Array(0.0, 1.0, -1.0, 0.866025, -1.0, -0.5, 0.0, -1.0, -1.0, 0.866025, 1.0, -0.5, 0.866025, -1.0, 0.5, 0.866025, 1.0, 0.5, -8.74228e-08, -1.0, 1.0, -8.74228e-08, 1.0, 1.0, -0.866025, -1.0, 0.5, -0.866025, 1.0, 0.5, -0.866025, -1.0, -0.5, -0.866025, 1.0, -0.5),
Vector3Array(0.0, 0.609973, -0.792383, 0.686239, -0.609973, -0.396191, 0.0, -0.609973, -0.792383, 0.686239, 0.609973, -0.396191, 0.686239, -0.609973, 0.396191, 0.686239, 0.609973, 0.396191, 0.0, -0.609973, 0.792383, 0.0, 0.609973, 0.792383, -0.686239, -0.609973, 0.396191, -0.686239, 0.609973, 0.396191, -0.686239, -0.609973, -0.396191, -0.686239, 0.609973, -0.396191),
null, ; No Tangents,
null, ; no Vertex Colors,
null, ; No UV1,
null, ; No UV2,
null, ; No Bones,
null, ; No Weights,
IntArray(0, 2, 1, 3, 1, 4, 5, 4, 6, 7, 6, 8, 0, 5, 9, 9, 8, 10, 11, 10, 2, 1, 10, 8, 0, 1, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 5, 0, 3, 0, 9, 11, 9, 5, 7, 9, 10, 11, 11, 2, 0, 10, 1, 2, 1, 6, 4, 6, 1, 8)
],
"morph_arrays":[]
}
动画
动画资源由轨道组成。 此外,它还有 length
、loop
和 step
应用于所有轨道。
length
和step
都是以秒为单位的持续时间。
每个轨道由格式为 tracks/Id/Attribute
的键值对列表描述。每个轨道包括:
type
path
interp
keys
loop_wrap
imported
enabled
type
必须是每个轨道的第一个属性。type
的值可以是:transform
value
method
path
的格式为NodePath(Path/To/Node:attribute)
。它是动画化节点或属性的路径,相对于AnimationPlayer中定义的根节点。The
interp
is the method to interpolate frames from the keyframes. It is an enum variable with one of the following values:0
(constant)1
(linear)2
(cubic)
keys
对应于关键帧。它显示为PoolRealArray()
,但对于具有不同类型的轨道可能具有不同的结构。- 变换轨道使用
keys
中的每12个实数来描述关键帧。第一个数字是时间戳,第二个数字是转换,后跟三数字转换向量,四数字旋转四元数 (X, Y, Z, W) ,最后是三数字缩放向量。变换轨道中的默认变换为1.0。
- 变换轨道使用
[sub_resource type="Animation" id=2]
length = 4.95833
loop = false
step = 0.1
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature001")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = true
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -0.0358698, -0.829927, 0.444204, 0, 0, 0, 1, 0.815074, 0.815074, 0.815074, 4.95833, 1, -0.0358698, -0.829927, 0.444204, 0, 0, 0, 1, 0.815074, 0.815074, 0.815074 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature001/Skeleton:Bone.001")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = true
tracks/1/enabled = false
tracks/1/keys = PoolRealArray( 0, 1, 0, 5.96046e-08, 0, 0, 0, 0, 1, 1, 1, 1, 4.95833, 1, 0, 5.96046e-08, 0, 0, 0, 0, 1, 1, 1, 1 )