Node.add_child
2026/4/14大约 3 分钟
最后同步日期:2026-04-16 | Godot 官方原文 — Node.add_child
Node.add_child
定义
add_child 就像往一个文件夹里放文件——你把一个节点"挂"到另一个节点下面,让它成为子节点。被添加的节点会出现在父节点的子节点列表中,并跟随父节点一起进入场景树(SceneTree)。
这是 Godot 中最常用的节点操作之一,几乎所有动态创建 UI、生成敌人、加载子弹等场景都会用到它。
函数签名
C#
public void AddChild(Node node, bool forceReadableName = false, InternalMode internalMode = InternalMode.Disabled)GDScript
add_child(node: Node, force_readable_name: bool = false, internal: int = 0) -> void参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| node | Node | 是 | 要添加的子节点。不能为 null,也不能是已经在场景树中的节点 |
| forceReadableName | bool | 否 | 为 true 时,自动生成的节点名会保留原名而非被重命名为 @Node@123 格式 |
| internalMode | InternalMode | 否 | 内部模式。Disabled(默认)= 普通子节点;Front = 插入到子节点列表最前面;Back = 插入到最后面 |
返回值
无返回值(void)。
代码示例
基础用法
最简单的用法——创建一个节点并添加为子节点:
C#
public override void _Ready()
{
// 创建一个新节点
var newNode = new Node();
newNode.Name = "MyChild";
// 将它添加为当前节点的子节点
AddChild(newNode);
// 运行结果: 场景树中出现新节点,路径为 "当前节点/MyChild"
GD.Print(GetChild(0).Name); // 运行结果: MyChild
}GDScript
func _ready():
# 创建一个新节点
var new_node = Node.new()
new_node.name = "MyChild"
# 将它添加为当前节点的子节点
add_child(new_node)
# 运行结果: 场景树中出现新节点,路径为 "当前节点/MyChild"
print(get_child(0).name) # 运行结果: MyChild实际场景
动态生成一个 Sprite2D 作为角色:
C#
public partial class Spawner : Node2D
{
[Export] public PackedScene ExEnemyScene;
public override void _Ready()
{
// 动态创建一个 Sprite2D 敌人
var enemy = new Sprite2D();
enemy.Name = "Enemy";
enemy.Position = new Vector2(100, 200);
AddChild(enemy);
// 验证:子节点数量
GD.Print(GetChildCount()); // 运行结果: 1
// 验证:获取子节点
var found = GetNode<Sprite2D>("Enemy");
GD.Print(found.Position); // 运行结果: (100, 200)
}
}GDScript
extends Node2D
@export var enemy_scene: PackedScene
func _ready():
# 动态创建一个 Sprite2D 敌人
var enemy = Sprite2D.new()
enemy.name = "Enemy"
enemy.position = Vector2(100, 200)
add_child(enemy)
# 验证:子节点数量
print(get_child_count()) # 运行结果: 1
# 验证:获取子节点
var found = get_node("Enemy")
print(found.position) # 运行结果: (100, 200)进阶用法
批量添加多个子节点,并处理 forceReadableName 参数:
C#
public override void _Ready()
{
// 批量创建 3 个节点
for (int i = 0; i < 3; i++)
{
var child = new Node();
child.Name = $"Item_{i}";
AddChild(child);
}
// 遍历所有子节点
foreach (var child in GetChildren())
{
GD.Print(child.Name);
}
// 运行结果:
// Item_0
// Item_1
// Item_2
// 注意:如果添加同名节点,后添加的会自动重命名
var duplicate = new Node();
duplicate.Name = "Item_0"; // 与已有的重名
AddChild(duplicate);
GD.Print(duplicate.Name); // 运行结果: Item_0@2 (自动重命名避免冲突)
}GDScript
func _ready():
# 批量创建 3 个节点
for i in range(3):
var child = Node.new()
child.name = "Item_%d" % i
add_child(child)
# 遍历所有子节点
for child in get_children():
print(child.name)
# 运行结果:
# Item_0
# Item_1
# Item_2
# 注意:如果添加同名节点,后添加的会自动重命名
var duplicate = Node.new()
duplicate.name = "Item_0" # 与已有的重名
add_child(duplicate)
print(duplicate.name) # 运行结果: Item_0@2 (自动重命名避免冲突)注意事项
- 不能添加已经在场景树中的节点:如果一个节点已经有父节点,必须先调用
RemoveChild()将其移除,或者用GetParent().RemoveChild(this),否则会报错。 - 被添加的节点会立即进入场景树:
add_child调用后,子节点的_EnterTree()和_Ready()回调会立即执行。 - 性能提示:在循环中大量添加子节点时,可以考虑先暂停场景树处理(
GetTree().Paused = true),添加完再恢复,避免每添加一个节点都触发一次场景树更新。 - C# 差异:C# 中方法名用 PascalCase(
AddChild),GDScript 中用 snake_case(add_child)。
