Godot 4.4 GDExtension自定义类作为参数/属性实现问询
解决Godot 4.4 GDExtension自定义类作为属性/方法参数的问题
核心要点
要让自定义类能作为其他类的属性并在编辑器中选择实例,关键是正确注册自定义类的类型,并在PropertyInfo中指定类的字符串类名,而非直接使用C++指针类型。
最小化示例代码
假设我们有两个自定义类:MyCustomNode(继承自Node)和MyController(继承自Node),目标是让MyController拥有一个MyCustomNode类型的属性,且编辑器中能选择场景内的对应实例。
1. 自定义类头文件(my_custom_node.h)
#ifndef MY_CUSTOM_NODE_H #define MY_CUSTOM_NODE_H #include <godot_cpp/classes/node.hpp> using namespace godot; class MyCustomNode : public Node { GDCLASS(MyCustomNode, Node) protected: static void _bind_methods() {} }; #endif // MY_CUSTOM_NODE_H
2. 控制器类头文件(my_controller.h)
#ifndef MY_CONTROLLER_H #define MY_CONTROLLER_H #include <godot_cpp/classes/node.hpp> #include "my_custom_node.h" using namespace godot; class MyController : public Node { GDCLASS(MyController, Node) private: MyCustomNode* target = nullptr; protected: static void _bind_methods() { // 注册属性:用PROPERTY_TYPE_OBJECT指定类型,通过PROPERTY_HINT_NODE_TYPE限定可选类 ClassDB::add_property("MyController", PropertyInfo( PROPERTY_TYPE_OBJECT, "target", PROPERTY_HINT_NODE_TYPE, "MyCustomNode" // 必须与自定义类的注册名称完全一致 ), "set_target", "get_target"); // 绑定带自定义类参数的方法,参数配置逻辑同上 ClassDB::add_method("set_target_direct", &MyController::set_target, PropertyInfo( PROPERTY_TYPE_OBJECT, "new_target", PROPERTY_HINT_NODE_TYPE, "MyCustomNode" )); } public: void set_target(MyCustomNode* p_target) { target = p_target; } MyCustomNode* get_target() const { return target; } }; #endif // MY_CONTROLLER_H
3. GDExtension入口文件(gdextension_entry.cpp)
#include <godot_cpp/core/class_db.hpp> #include <godot_cpp/godot.hpp> #include "my_custom_node.h" #include "my_controller.h" using namespace godot; void initialize_my_extension(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } // 先注册被依赖的自定义类,再注册依赖它的类 ClassDB::register_class<MyCustomNode>(); ClassDB::register_class<MyController>(); } void uninitialize_my_extension(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } } extern "C" { GDExtensionBool GDE_EXPORT my_extension_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization* r_initialization) { godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); init_obj.register_initializer(initialize_my_extension); init_obj.register_terminator(uninitialize_my_extension); init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); return init_obj.init(); } }
4. SCons配置文件(SConstruct)
确保编译配置正确,避免编译错误:
import os import sys env = Environment() # 替换为你的Godot 4.4路径 godot_path = os.environ.get("GODOT4_PATH", "/path/to/your/godot4") env.Append(TOOLS_PATH = os.path.join(godot_path, "tools")) sys.path.append(os.path.join(godot_path, "modules", "gdextension", "cmake")) from godot_cpp import godot_build # 配置编译参数 godot_build(env, target="debug", cpp_std="c++17") # 添加所有源文件 env.Append(SOURCES = [ "gdextension_entry.cpp", "my_custom_node.cpp", "my_controller.cpp" ]) # 生成扩展库 env.SharedLibrary("my_extension", env.SOURCES)
关键注意事项
- 注册顺序:必须先注册被依赖的
MyCustomNode,再注册MyController,否则ClassDB无法识别类名,会触发编译或运行时错误。 - PropertyInfo类名匹配:
PROPERTY_HINT_NODE_TYPE后的字符串必须和ClassDB::register_class的类名完全一致,编辑器才能过滤出正确的可选实例。 - 编译错误排查:若scons报错,优先检查头文件是否正确包含、类是否完成注册、
PropertyInfo的参数是否合法(比如类名拼写错误)。 - 编辑器行为:完成编译并启用扩展后,在编辑器中添加
MyController节点,属性面板的target会显示为节点选择器,仅能选择场景中的MyCustomNode实例,与原生Godot节点属性行为一致。
内容的提问来源于stack exchange,提问作者Chris Camacho
相关产品推荐
相关产品推荐

