You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot中基于子节点动态创建属性列表的实现困惑

解决Godot动态生成属性列表的问题

一、先修复_get/_set的无限循环问题

你之前的实现没有处理非动态属性的情况,导致Godot访问节点内置属性(比如name、position)时也会进入你的_get/_set,进而引发报错或无限递归。修改成下面这样:

var propertyHolder = {}

func _get(key):
    if propertyHolder.has(key):
        return propertyHolder[key]
    # 交给父类处理其他属性
    return super._get(key)

func _set(key, value):
    if propertyHolder.has(key):
        propertyHolder[key] = value
        return true
    # 交给父类处理其他属性
    return super._set(key, value)

二、动态收集子节点的属性定义

让每个子节点暴露自己需要的属性信息,父节点遍历收集后返回给编辑器:

  1. 子节点侧:定义返回属性列表的方法
# 子节点脚本
func get_dynamic_properties():
    # 返回该子节点需要的属性信息,比如枚举类型
    return [
        PropertyInfo(Variant.INT, "weapon_type", PROPERTY_HINT_ENUM, "Sword,Bow,Staff"),
        PropertyInfo(Variant.BOOL, "is_blessed")
    ]

# 子节点本地存储属性值
var _local_props = {
    "weapon_type": 0,
    "is_blessed": false
}
  1. 父节点侧:重写_get_property_list收集所有子节点的属性
# 父节点脚本
func _get_property_list():
    var props = []
    # 先继承父类的属性列表
    props.append_array(super._get_property_list())
    
    # 遍历所有子节点,收集动态属性
    for child in get_children():
        if child.has_method("get_dynamic_properties"):
            props.append_array(child.get_dynamic_properties())
    
    return props

三、优化属性存储与访问(可选,更符合组合性)

如果不想父节点统一管理所有属性,可以把属性存储放到子节点本地,父节点仅做转发:

# 父节点的_get/_set修改为转发给子节点
func _get(key):
    for child in get_children():
        if child.has_method("get_dynamic_property"):
            var val = child.get_dynamic_property(key)
            if val != null:
                return val
    return super._get(key)

func _set(key, value):
    for child in get_children():
        if child.has_method("set_dynamic_property"):
            if child.set_dynamic_property(key, value):
                return true
    return super._set(key, value)
# 子节点实现对应的方法
func get_dynamic_property(key):
    return _local_props.get(key, null)

func set_dynamic_property(key, value):
    if _local_props.has(key):
        _local_props[key] = value
        # 可选:属性变化时触发子节点逻辑
        _on_property_changed(key, value)
        return true
    return false

func _on_property_changed(key, value):
    # 子节点自己处理属性变化后的逻辑
    match key:
        "weapon_type": print("武器类型切换为: ", value)

四、编辑器属性列表刷新

当子节点添加/移除时,需要通知编辑器更新属性面板:

# 父节点脚本
func _ready():
    notify_property_list_changed()
    # 监听子节点变化事件
    connect("child_entered_tree", self, "_on_child_tree_changed")
    connect("child_exiting_tree", self, "_on_child_tree_changed")

func _on_child_tree_changed(child):
    notify_property_list_changed()

内容的提问来源于stack exchange,提问作者epic man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:26:27