BoneAttachment3D
2026/4/14大约 5 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — BoneAttachment3D
BoneAttachment3D
节点继承关系
定义
BoneAttachment3D 是一个附着到 3D 骨骼上的"挂载点"节点。把它放在 Skeleton3D 下面,指定要附着到哪根骨骼上,然后它就会自动跟着那根骨骼一起运动。你可以在 BoneAttachment3D 下面挂载武器、帽子、特效、灯光等任何 Node3D 子节点。
想象 BoneAttachment3D 是在木偶手上绑一根绳子,绳子的另一端拴一把剑。当木偶的手臂转动时,剑也跟着转动,完全不需要你额外写代码去控制剑的位置。你只需要告诉它"绑在手上"就行了。
一句话理解:BoneAttachment3D 让你把任何 3D 节点"粘"到某根骨骼上,自动跟随骨骼运动。最常见的用途是让角色手持武器、穿戴装备、显示特效。
使用频率:★ 基本用不到——只有在骨骼上挂载东西时才需要用到。
节点用途
- 在角色手上挂载武器(剑、枪、盾牌等)
- 在角色头上挂载帽子、头盔等装饰物
- 在骨骼上挂载粒子特效(手上冒火、脚下发光等)
- 在骨骼上挂载光源(角色手持火把照亮周围)
- 在骨骼上挂载碰撞体(武器碰撞检测区域)
使用场景
典型场景
- 角色换装系统:不同 BoneAttachment3D 挂载不同的装备模型
- 武器系统:角色手持的武器跟随手部骨骼运动
- 特效系统:角色攻击时手上出现火焰特效,特效跟随手部
- 灯光系统:角色手持火把,光源跟随手部骨骼
不适用场景
- 2D 角色挂载装备 -> 2D 中直接把 Sprite2D 放到 Bone2D 下面即可,不需要 BoneAttachment
- 不需要跟随骨骼运动的物体 -> 直接放在 Node3D 下面
- 1个骨骼上需要多个挂载点 -> 在同一个 BoneAttachment3D 下面放多个子节点即可
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| Skeleton3D | 骨骼系统(Skeleton),BoneAttachment3D 必须作为其子节点 | 必需 |
| MeshInstance3D | 挂载武器、装备的 3D 模型 | 挂载物品时必需 |
| GPUParticles3D | 挂载粒子特效 | 需要特效时 |
| Light3D | 挂载光源 | 需要动态光源时 |
| Area3D / CollisionShape3D | 挂载碰撞区域(用于武器伤害检测) | 需要碰撞检测时 |
典型节点树结构:
CharacterBody3D
└── Model
└── Skeleton3D
├── (骨骼...)
├── BoneAttachment3D ← 右手挂载点
│ ├── MeshInstance3D ← 剑的模型
│ ├── GPUParticles3D ← 剑上的火焰特效
│ └── Area3D ← 武器碰撞区域
│ └── CollisionShape3D
├── BoneAttachment3D ← 头部挂载点
│ └── MeshInstance3D ← 帽子模型
└── BoneAttachment3D ← 左手挂载点
└── Light3D ← 火把光源生效必备素材/资源
| 资源 | 类型 | 说明 |
|---|---|---|
| Skeleton3D | 场景节点 | BoneAttachment3D 必须放在 Skeleton3D 下面才能工作 |
| 骨骼名称 | StringName | 需要知道要附着到的骨骼名称,在编辑器中选择 |
| 挂载物品的模型 | MeshInstance3D / 其他 Node3D | 作为 BoneAttachment3D 的子节点 |
节点属性与信号
附着属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
BoneName | StringName | "" | — | 要附着到的骨骼名称。在编辑器的检查器面板中下拉选择 |
UseExternalSkeleton | bool | false | — | 是否使用外部骨骼。默认 false,从父节点查找 Skeleton3D。如果 Skeleton3D 不是直接父节点,可以设为 true 并手动指定 |
ExternalSkeleton | NodePath | "" | — | 外部骨骼的路径。仅当 UseExternalSkeleton 为 true 时生效 |
继承自 Node3D 的属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
Position | Vector3 | (0,0,0) | Node3D | 相对于骨骼的偏移位置。可以微调挂载物的位置 |
Rotation | Vector3 | (0,0,0) | Node3D | 相对于骨骼的旋转角度。可以微调挂载物的朝向 |
Scale | Vector3 | (1,1,1) | Node3D | 挂载物的缩放比例 |
信号
| 信号 | 参数 | 说明 |
|---|---|---|
| (无特有信号) | — | BoneAttachment3D 没有自己特有的信号,继承自 Node3D 的信号照常可用 |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
GetBoneName() | StringName | 获取当前附着的骨骼名称 |
SetBoneName(name) | void | 设置要附着到的骨骼名称 |
IsOverridingBonePose() | bool | 是否在覆盖骨骼的变换 |
SetOverridingBonePose(override) | void | 设置是否覆盖骨骼变换 |
代码示例
动态切换角色手持的武器
C
using Godot;
public partial class WeaponSwitcher : Node3D
{
private BoneAttachment3D _handAttachment;
// 预加载不同的武器场景
[Export] public PackedScene SwordScene { get; set; }
[Export] public PackedScene BowScene { get; set; }
[Export] public PackedScene ShieldScene { get; set; }
private Node3D _currentWeapon;
public override void _Ready()
{
// 获取右手骨骼的挂载点
_handAttachment = GetNode<BoneAttachment3D>("Model/Skeleton3D/RightHandAttachment");
// 确认挂载到了正确的骨骼
GD.Print($"武器挂载在骨骼: {_handAttachment.GetBoneName()}");
}
/// <summary>
/// 切换武器
/// </summary>
public void EquipWeapon(string weaponType)
{
// 移除当前武器
if (_currentWeapon != null)
{
_currentWeapon.QueueFree();
_currentWeapon = null;
}
// 根据类型创建新武器
switch (weaponType)
{
case "Sword":
_currentWeapon = SwordScene.Instantiate<Node3D>();
break;
case "Bow":
_currentWeapon = BowScene.Instantiate<Node3D>();
break;
case "Shield":
_currentWeapon = ShieldScene.Instantiate<Node3D>();
break;
default:
GD.PrintErr($"未知武器类型: {weaponType}");
return;
}
// 挂载到骨骼上
_handAttachment.AddChild(_currentWeapon);
GD.Print($"已装备武器: {weaponType}");
}
public override void _Input(InputEvent @event)
{
// 按 1/2/3 切换武器
if (@event.IsActionPressed("weapon_1"))
EquipWeapon("Sword");
else if (@event.IsActionPressed("weapon_2"))
EquipWeapon("Bow");
else if (@event.IsActionPressed("weapon_3"))
EquipWeapon("Shield");
}
}GDScript
extends Node3D
@onready var hand_attachment: BoneAttachment3D = $Model/Skeleton3D/RightHandAttachment
# 预加载不同的武器场景
@export var sword_scene: PackedScene
@export var bow_scene: PackedScene
@export var shield_scene: PackedScene
var current_weapon: Node3D
func _ready():
# 确认挂载到了正确的骨骼
print("武器挂载在骨骼: ", hand_attachment.get_bone_name())
## 切换武器
func equip_weapon(weapon_type: String):
# 移除当前武器
if current_weapon:
current_weapon.queue_free()
current_weapon = null
# 根据类型创建新武器
match weapon_type:
"Sword":
current_weapon = sword_scene.instantiate()
"Bow":
current_weapon = bow_scene.instantiate()
"Shield":
current_weapon = shield_scene.instantiate()
_:
push_error("未知武器类型: %s" % weapon_type)
return
# 挂载到骨骼上
hand_attachment.add_child(current_weapon)
print("已装备武器: ", weapon_type)
func _input(event):
# 按 1/2/3 切换武器
if event.is_action_pressed("weapon_1"):
equip_weapon("Sword")
elif event.is_action_pressed("weapon_2"):
equip_weapon("Bow")
elif event.is_action_pressed("weapon_3"):
equip_weapon("Shield")编辑器中使用 BoneAttachment3D
在 Godot 编辑器中使用 BoneAttachment3D 非常简单:
- 右键点击 Skeleton3D 节点 -> 添加子节点 -> 选择 BoneAttachment3D
- 在检查器面板中找到
Bone Name属性,从下拉列表中选择要附着到的骨骼 - 右键点击 BoneAttachment3D -> 添加子节点 -> 放置你的武器/装备模型
- 调整 Position 和 Rotation 来微调位置和朝向
