第一部分 04:常用属性系统
这一章讲你在 Inspector 面板里最常看到、也最容易懵的一堆属性:
position
global_position
rotation
rotation_degrees
scale
visible
z_index
modulate
self_modulate
texture
disabled
size
anchors
offsets
先建立一个大分类:
Node 基础属性:name、process_mode、script
Node2D 变换属性:position、rotation、scale、z_index
CanvasItem 显示属性:visible、modulate、self_modulate
Control UI 属性:position、size、anchor、offset
物理/碰撞属性:disabled、collision_layer、collision_mask
资源引用属性:texture、shape、tile_set、animation
Godot 里很多 2D 节点都继承自 Node2D,而 Node2D 本身就是带有 position、rotation、scale 等 2D 变换能力的节点;同时 Node2D 和 Control 都继承自 CanvasItem,所以它们都会共享一些显示相关属性,比如 visible、z_index、modulate。(Godot Engine documentation)
1. 属性到底是什么
Godot 的属性,就是节点身上的可配置数据。
比如一个 Sprite2D:
Sprite2D
├── position
├── rotation
├── scale
├── visible
├── texture
├── flip_h
└── z_index
这些属性可以在两个地方修改。
方式一:Inspector 面板修改
选中节点,右边 Inspector 里改。
比如:
选中 Player
→ Inspector
→ Transform
→ Position
这种适合固定配置。
方式二:代码修改
$Sprite2D.visible = false
$Sprite2D.position = Vector2(100, 200)
$Sprite2D.scale = Vector2(2, 2)
这种适合运行时变化。
比如:
角色移动
UI 隐藏
天气变暗
宝箱打开
敌人死亡
镜头缩放
2. position:位置
它是什么
position 表示当前节点相对于父节点的位置。
position = Vector2(100, 200)
意思是:
x = 100
y = 200
Godot 2D 坐标里:
x 向右增加
y 向下增加
这个和网页坐标很像。
前端类比
left: 100px;
top: 200px;
不过注意,Godot 不是 CSS 布局系统,它是游戏世界坐标。
示例
场景结构:
World Node2D
└── Player CharacterBody2D
如果:
$Player.position = Vector2(100, 200)
意思是:
Player 在 World 里的位置是 x=100, y=200
常见写法
position.x += 10
position.y += 10
或者:
position += Vector2(10, 0)
但是角色移动时,不建议直接改 position,更推荐用 CharacterBody2D 的 velocity + move_and_slide()。
velocity = direction * speed
move_and_slide()
因为直接改 position 有可能绕开物理碰撞。
3. global_position:全局位置
它是什么
global_position 表示节点在整个 2D 世界中的位置。
简单说:
position:相对于父节点
global_position:相对于整个世界
Node2D 官方文档里也把 global_position、position、global_rotation、global_scale 等作为 2D 变换相关属性。(Godot Engine documentation)
示例
假设结构是:
World Node2D
└── Player CharacterBody2D
如果:
$World.position = Vector2(100, 100)
$World/Player.position = Vector2(50, 50)
那么:
Player.position = Vector2(50, 50)
Player.global_position = Vector2(150, 150)
因为 Player 在 World 里面,World 自己又偏移了 100,100。
什么时候用 position
适合:
设置子节点相对于父节点的位置
调整 Sprite 相对于角色中心的位置
调整 CollisionShape2D 的偏移
调整 UI 子元素的局部位置
比如:
$BodySprite.position = Vector2(0, -8)
意思是让角色图片相对于玩家根节点上移一点。
什么时候用 global_position
适合:
生成对象到世界某个位置
让怪物追踪玩家
让特效出现在玩家当前位置
判断两个对象之间距离
比如生成攻击特效:
var effect = hit_effect_scene.instantiate()
get_tree().current_scene.add_child(effect)
effect.global_position = player.global_position
或者怪物追玩家:
var direction = (player.global_position - global_position).normalized()
velocity = direction * speed
move_and_slide()
4. rotation 和 rotation_degrees:旋转
Godot 有两个常用旋转属性:
rotation:弧度
rotation_degrees:角度
rotation
单位是弧度。
rotation = 1.5708
1.5708 大约是 90 度。
rotation_degrees
单位是角度,更适合人类阅读。
rotation_degrees = 90
入门阶段你可以优先用 rotation_degrees。
示例:让箭头旋转
$Arrow.rotation_degrees = 45
示例:让节点朝向目标
look_at(target.global_position)
比如怪物头顶的箭头指向玩家:
$Arrow.look_at(player.global_position)
常见坑
2D 游戏里,旋转会围绕节点的原点进行。
如果你觉得旋转怪怪的,可能是:
图片原点不在你以为的位置
Sprite2D 的 centered 配置不合适
子节点位置有偏移
5. scale:缩放
它是什么
scale 表示缩放比例。
scale = Vector2(2, 2)
表示 x、y 都放大 2 倍。
scale = Vector2(0.5, 0.5)
表示缩小到一半。
前端类比
transform: scale(2);
示例:让道具变大
$ItemSprite.scale = Vector2(1.2, 1.2)
示例:点击按钮时放大
func _on_button_pressed():
scale = Vector2(1.1, 1.1)
注意
scale 会影响子节点。
比如:
Player CharacterBody2D
├── Sprite2D
└── CollisionShape2D
如果你改:
$Player.scale = Vector2(2, 2)
那么玩家图片和碰撞形状可能都会被缩放。
如果你只想放大图片,不想影响碰撞,改 Sprite2D.scale 更合适:
$Player/Sprite2D.scale = Vector2(2, 2)
6. visible:显示和隐藏
它是什么
visible 控制节点是否显示。
visible = false
隐藏。
visible = true
显示。
CanvasItem 文档说明,CanvasItem 可以被隐藏,并且隐藏父 CanvasItem 也会隐藏它的子项。(Godot Engine documentation)
前端类比
有点像:
display: none;
但不是完全等价。
示例:隐藏背包面板
$UI/InventoryPanel.visible = false
显示背包:
$UI/InventoryPanel.visible = true
切换显示状态:
$UI/InventoryPanel.visible = !$UI/InventoryPanel.visible
常见用途
打开/关闭 UI
隐藏已经拾取的道具
隐藏调试面板
控制对话框显示
控制角色某个部件显示
注意
隐藏节点不等于删除节点。
visible = false
只是看不见,节点还在,脚本也可能还在运行。
如果你真的不要这个节点了,用:
queue_free()
7. z_index:2D 显示层级
它是什么
z_index 控制 2D 绘制顺序。
值越大,通常越靠前显示。
z_index = 10
CanvasItem 文档说明,Canvas item 默认会按树顺序绘制,子项默认绘制在父项之上,也可以通过 z-index 等属性调整绘制顺序。(Godot Engine documentation)
前端类比
z-index: 10;
示例
Ground z_index = 0
Player z_index = 10
TreeTop z_index = 20
UI z_index = 100
RPG 常见问题
你可能会遇到:
玩家走到树后面,但玩家还盖在树上
这时候需要处理显示层级。
简单做法:
地面层:z_index = 0
玩家:z_index = 10
树冠:z_index = 20
更复杂的俯视角 RPG 会用 y-sort,也就是根据 y 坐标自动排序:
越靠下的对象越靠前显示
这个后面讲 2D RPG 排序时再展开。
8. modulate:颜色叠加
它是什么
modulate 可以给节点整体叠加颜色。
比如:
modulate = Color(1, 0, 0)
节点会偏红。
CanvasItem 文档提到,可以通过 modulate 或 self_modulate 调整 CanvasItem 的颜色。(Godot Engine documentation)
Color 怎么写
Godot 的 Color 通常是:
Color(r, g, b, a)
每个值一般是 0 到 1。
Color(1, 1, 1, 1) # 白色,完全不透明
Color(1, 0, 0, 1) # 红色
Color(0, 1, 0, 1) # 绿色
Color(0, 0, 1, 1) # 蓝色
Color(1, 1, 1, 0.5) # 半透明
示例:受伤闪红
func flash_damage():
$Sprite2D.modulate = Color(1, 0.3, 0.3, 1)
await get_tree().create_timer(0.1).timeout
$Sprite2D.modulate = Color(1, 1, 1, 1)
示例:夜晚变暗
$World.modulate = Color(0.45, 0.55, 0.8, 1)
这个可以让整个世界偏蓝、偏暗。
不过真正完整的昼夜系统,后面可以结合 CanvasModulate、灯光、Shader 来做。
9. self_modulate:只影响自己
modulate 和 self_modulate 很像,但区别很重要。
modulate:影响自己和子节点
self_modulate:只影响自己,不影响子节点
示例
结构:
Player Node2D
├── BodySprite Sprite2D
└── WeaponSprite Sprite2D
如果你改:
$Player.modulate = Color(1, 0, 0, 1)
玩家身体和武器都会变红。
如果你只想让 Player 根节点自己的绘制变色,使用 self_modulate。不过很多容器节点本身不绘制内容,所以实际项目里更常直接改具体的 Sprite2D.modulate。
10. texture:图片资源
它是什么
texture 是图片纹理资源。
Sprite2D、TextureRect 等节点都可能用到它。
Sprite2D 设置图片
$Sprite2D.texture = preload("res://assets/player.png")
TextureRect 设置图片
$TextureRect.texture = preload("res://assets/ui/avatar.png")
区别是:
Sprite2D:游戏世界里的图片
TextureRect:UI 界面里的图片
常见用途
角色贴图
NPC 贴图
道具图标
技能图标
头像
按钮背景
11. flip_h / flip_v:图片翻转
这是 Sprite2D 很常用的属性。
$Sprite2D.flip_h = true
水平翻转。
$Sprite2D.flip_v = true
垂直翻转。
RPG 角色朝向例子
if direction.x < 0:
$BodySprite.flip_h = true
elif direction.x > 0:
$BodySprite.flip_h = false
常用于:
角色向左走,图片水平翻转
角色向右走,图片恢复
注意
如果你的角色是上下左右四方向动画,单纯 flip_h 不够,需要切换不同动画。
比如:
walk_down
walk_up
walk_left
walk_right
这个后面讲动画系统时再细讲。
12. centered:Sprite2D 是否居中
Sprite2D.centered 控制图片是否以节点原点为中心显示。
$Sprite2D.centered = true
默认通常是居中。
centered = true
节点位置在图片中心。
图片
┌────────┐
│ ● │ ← 节点原点
└────────┘
centered = false
节点位置在图片左上角。
● ┌────────┐
│ │
└────────┘
什么时候改
像素风游戏里,如果图片显示发虚、抖动、偏半格,有时会检查:
centered
像素吸附
图片尺寸
节点坐标是否为整数
Camera2D zoom
13. size:UI 尺寸
size 是 Control 节点常见属性。
$Panel.size = Vector2(300, 200)
表示宽 300,高 200。
Control 是 Godot GUI 控件的基类,它有位置、尺寸、anchor、offset 等布局概念,会根据父控件调整自身位置和尺寸。(Godot Engine documentation)
前端类比
width: 300px;
height: 200px;
示例:设置面板大小
$InventoryPanel.size = Vector2(400, 300)
注意
如果这个 UI 节点在 Container 下面,比如 VBoxContainer、HBoxContainer、GridContainer,你直接改 size 可能不生效或者很快被容器覆盖。
因为 Container 会自动控制子节点布局。
这种情况应该改:
custom_minimum_size
size_flags
Container 设置
14. anchors:UI 锚点
它是什么
Anchor 决定 UI 元素参考父节点的哪个位置。
比如:
左上角
右上角
中心
底部
铺满
Godot 的 UI 锚点是 Control 的核心布局概念。官方文档里举例说,把每个 anchor 设置为 0.5,可以让 offset 的参考点移动到父节点中心。(Godot Engine documentation)
前端类比
有点像:
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
或者:
position: fixed;
right: 20px;
bottom: 20px;
常见锚点预设
Godot 编辑器里可以直接点 Anchor Presets。
常用:
Top Left:左上
Top Right:右上
Bottom Left:左下
Bottom Right:右下
Center:居中
Full Rect:铺满父节点
UI 例子
血条放左上角:
Anchor Preset: Top Left
金币放右上角:
Anchor Preset: Top Right
对话框放底部:
Anchor Preset: Bottom Wide
暂停菜单居中:
Anchor Preset: Center
遮罩铺满屏幕:
Anchor Preset: Full Rect
15. offsets:UI 偏移
Anchor 决定“参考点”。
Offset 决定“离参考点多远”。
比如右上角按钮:
Anchor: Top Right
Offset: 往左 20,往下 20
在 Godot 里,UI 的位置经常由:
anchor_left
anchor_top
anchor_right
anchor_bottom
offset_left
offset_top
offset_right
offset_bottom
共同决定。
入门阶段不用死抠数学,优先用编辑器的 Anchor Presets。
实用建议
做 UI 时,顺序这样来:
1. 先选 Control 节点
2. 点 Anchor Presets
3. 选左上/右上/居中/铺满
4. 再微调 Position 和 Size
别一开始就手动调四个 anchor 和四个 offset,容易把自己绕进去。
16. custom_minimum_size:UI 最小尺寸
当 UI 节点在 Container 里面时,这个很有用。
比如:
HBoxContainer
├── Button
├── Button
└── Button
如果你想让按钮至少 120x40:
$Button.custom_minimum_size = Vector2(120, 40)
前端类比:
min-width: 120px;
min-height: 40px;
17. mouse_filter:UI 鼠标穿透
这是做 UI 时很常见的坑。
Control 节点有 mouse_filter,决定它怎么处理鼠标事件。
常见值:
Stop:接收鼠标事件,并阻止继续传递
Pass:接收鼠标事件,但允许继续传递
Ignore:忽略鼠标事件,鼠标可以穿透
示例
如果你做了一个透明遮罩 UI,结果点击不到下面按钮,可能就是遮罩拦截了鼠标。
可以设置:
$Overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
18. disabled:禁用
很多节点都有 disabled 或类似属性。
比如 Button.disabled:
$StartButton.disabled = true
按钮就不能点了。
CollisionShape2D.disabled
碰撞形状也可以禁用:
$CollisionShape2D.disabled = true
不过修改碰撞形状的 disabled 状态时,更稳的写法是延迟设置:
$CollisionShape2D.set_deferred("disabled", true)
这个常用于:
门打开后关闭碰撞
宝箱打开后关闭交互碰撞
敌人死亡后关闭碰撞
攻击判定短暂开启后关闭
19. collision_layer 和 collision_mask:碰撞层
这个先简单讲,不展开太深。
collision_layer:我属于哪一层
collision_mask:我检测哪一层
比如:
Player 在 Player 层
Wall 在 World 层
Enemy 在 Enemy 层
InteractArea 检测 Interactable 层
前端没有特别贴切的类比,硬要类比的话,有点像事件命名空间 + 过滤规则。
简单例子
玩家:
collision_layer = Player
collision_mask = World, Enemy, Interactable
墙:
collision_layer = World
collision_mask = Player, Enemy
意思是:
玩家属于 Player 层
玩家会和 World、Enemy、Interactable 发生检测
墙属于 World 层
墙会检测 Player、Enemy
这部分后面讲碰撞系统时要单独开一章。
20. velocity:角色速度
velocity 是 CharacterBody2D 很核心的属性。
velocity = Vector2(100, 0)
move_and_slide()
表示角色以每秒 100 像素向右移动。
常见写法
extends CharacterBody2D
@export var speed: float = 120.0
func _physics_process(delta):
var direction = Vector2.ZERO
if Input.is_action_pressed("ui_right"):
direction.x += 1
if Input.is_action_pressed("ui_left"):
direction.x -= 1
if Input.is_action_pressed("ui_down"):
direction.y += 1
if Input.is_action_pressed("ui_up"):
direction.y -= 1
velocity = direction.normalized() * speed
move_and_slide()
为什么要 normalized
如果你同时按右和下:
direction = Vector2(1, 1)
这个向量长度大于 1,会导致斜着走更快。
所以要:
direction.normalized()
让方向长度归一化。
21. speed:自定义属性
speed 不是 Godot 内置通用属性,一般是我们自己写的。
@export var speed: float = 120.0
加上 @export 后,它会出现在 Inspector 里。
这样你就可以在编辑器里调速度,不用每次改代码。
前端类比
有点像组件 props 的默认值:
function Player({ speed = 120 }) {}
但 Godot 的 @export 更像:
把脚本变量暴露给编辑器配置
常见自定义属性
@export var speed: float = 120.0
@export var max_health: int = 100
@export var attack_damage: int = 10
@export var interact_distance: float = 32.0
@export var npc_name: String = "村民"
@export var item_id: String = "potion"
22. script:脚本属性
在 Inspector 里你会看到节点有一个 Script。
比如:
Player CharacterBody2D
Script: player.gd
这表示这个节点挂了一个脚本。
脚本开头通常是:
extends CharacterBody2D
意思是:
这个脚本继承 CharacterBody2D
所以这个脚本控制的是一个 CharacterBody2D 类型节点
常见坑
如果节点是 Node2D,但脚本写:
extends CharacterBody2D
可能会报错或挂不上。
因为脚本继承类型要和节点类型匹配。
23. name:节点名称
每个节点都有名字。
Player
Sprite2D
CollisionShape2D
Camera2D
代码里经常通过名字找节点:
$Sprite2D
$Camera2D
$UI/HealthBar
命名建议
不要一直用默认名:
Sprite2D
Sprite2D2
Sprite2D3
建议语义化:
BodySprite
ShadowSprite
WeaponSprite
TalkArea
InteractArea
Hitbox
Hurtbox
这样代码更清楚:
@onready var body_sprite = $BodySprite
@onready var interact_area = $InteractArea
24. owner:先知道即可
owner 和“这个节点是否属于某个场景文件、是否会被保存”有关。
入门阶段你先记一句:
编辑器里创建的节点通常会正确保存到 .tscn
运行时代码 add_child 出来的节点通常只是运行时存在,不会自动写回场景文件
普通游戏开发初期不用太纠结。
25. 属性组合示例:玩家节点
推荐结构:
Player CharacterBody2D
├── BodySprite Sprite2D
├── CollisionShape2D
├── InteractArea Area2D
│ └── CollisionShape2D
└── Camera2D
玩家根节点常用属性:
position:玩家在地图中的位置
velocity:玩家移动速度
z_index:玩家显示层级
BodySprite 常用属性:
texture:玩家图片
flip_h:左右翻转
modulate:受伤闪红
visible:隐藏/显示
CollisionShape2D 常用属性:
shape:碰撞形状
disabled:是否禁用碰撞
Camera2D 常用属性:
zoom:镜头缩放
enabled:是否启用
position_smoothing_enabled:是否平滑跟随
26. 属性组合示例:宝箱节点
结构:
Chest StaticBody2D
├── Sprite2D
├── CollisionShape2D
├── InteractArea Area2D
│ └── CollisionShape2D
└── AnimationPlayer
常用属性:
Chest.position:宝箱位置
Chest.z_index:显示层级
Sprite2D.texture:宝箱图片
CollisionShape2D.shape:实体碰撞范围
InteractArea/CollisionShape2D.shape:交互范围
AnimationPlayer:播放打开动画
打开宝箱时:
func open():
$AnimationPlayer.play("open")
$InteractArea/CollisionShape2D.set_deferred("disabled", true)
27. 属性组合示例:UI 节点
结构:
UI CanvasLayer
└── HUD Control
├── HealthLabel Label
├── GoldLabel Label
└── InventoryButton Button
HUD 常用属性:
anchors:适配屏幕
offsets:相对锚点偏移
visible:显示/隐藏 HUD
HealthLabel 常用属性:
text:显示血量
position:位置
modulate:文字颜色
InventoryButton 常用属性:
text:按钮文字
disabled:是否禁用
pressed 信号:点击响应
28. Inspector 里常见分组
你选中一个 2D 节点,经常会看到类似分组:
Node
CanvasItem
Node2D
Transform
Visibility
Ordering
Texture
Material
Script
大概可以这样理解:
Node:节点基础设置
CanvasItem:显示相关
Node2D / Transform:位置、旋转、缩放
Visibility:显示隐藏、颜色叠加
Ordering:绘制顺序
Texture:图片资源
Script:挂载脚本
不同节点会有不同分组。
比如 Sprite2D 有 Texture。
Button 有 Text、Theme、Layout。
CollisionShape2D 有 Shape、Disabled。
29. 常见属性速查表
| 属性 | 常见节点 | 作用 |
|---|---|---|
| position | Node2D、Control | 位置 |
| global_position | Node2D | 世界位置 |
| rotation | Node2D | 弧度旋转 |
| rotation_degrees | Node2D | 角度旋转 |
| scale | Node2D、Control | 缩放 |
| visible | CanvasItem | 显示/隐藏 |
| z_index | CanvasItem | 绘制层级 |
| modulate | CanvasItem | 颜色叠加,影响子节点 |
| self_modulate | CanvasItem | 颜色叠加,只影响自己 |
| texture | Sprite2D、TextureRect | 图片资源 |
| flip_h | Sprite2D | 水平翻转 |
| centered | Sprite2D | 是否居中显示 |
| size | Control | UI 尺寸 |
| anchors | Control | UI 锚点 |
| offsets | Control | UI 偏移 |
| custom_minimum_size | Control | UI 最小尺寸 |
| disabled | Button、CollisionShape2D 等 | 禁用 |
| velocity | CharacterBody2D | 移动速度 |
| shape | CollisionShape2D | 碰撞形状 |
| script | Node | 挂载脚本 |
30. 新手常见坑
坑 1:改了 position,但角色穿墙
角色移动不要优先直接改:
position += direction * speed
更推荐:
velocity = direction * speed
move_and_slide()
坑 2:改了父节点 scale,子节点全变大
如果你只想改图片大小,改:
$Sprite2D.scale
不要改整个 Player:
$Player.scale
除非你确实想让碰撞、子节点一起变大。
坑 3:UI 在游戏世界里跟着镜头跑
UI 不要直接放在 World 下面。
推荐:
Main
├── World
├── Player
└── UI CanvasLayer
└── HUD Control
坑 4:visible=false 后逻辑还在跑
隐藏只是隐藏,不是销毁。
visible = false
节点依然存在。
要删除:
queue_free()
坑 5:Control 在 Container 里,手动 size 不听话
如果 UI 节点在 Container 下,布局由 Container 管。
这时候优先改:
custom_minimum_size
size_flags
Container 设置
而不是死磕 size。
坑 6:position 和 global_position 混用
如果对象在多层父节点下面,position 和 global_position 可能差很多。
生成对象到世界坐标时,优先用:
global_position
调整子节点相对位置时,优先用:
position
31. 这一章你先记住这些
position:相对父节点的位置
global_position:世界位置
rotation_degrees:角度旋转
scale:缩放,会影响子节点
visible:显示隐藏,不等于删除
z_index:2D 显示层级
modulate:颜色叠加,适合闪红、变暗、半透明
texture:图片资源
size:UI 尺寸
anchors:UI 适配参考点
offsets:UI 相对锚点偏移
disabled:禁用按钮或碰撞
velocity:角色移动速度
最重要的一句话:
游戏世界里的对象,重点看 position、global_position、rotation、scale、z_index;UI 里的对象,重点看 size、anchors、offsets;显示效果重点看 visible、modulate、texture。
如果您觉得这篇文章有帮助,请点个赞吧~
评论
请登录后发表评论
去登录