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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:41:15