C++游戏引擎脚本无法加载变量

C++ game engine scripting can't load variables

所以我正在为我的游戏引擎编写脚本,一切似乎都正常,但如果涉及任何变量,它就会随机崩溃。我通过检查包含我的脚本的文件夹来获取脚本。然后我获取该文件夹中的所有 dll 文件并将它们注册到 ScriptManager 中。然后在 NativeComponent 中我说出我想要的脚本,然后我从 ScriptManager 中检索所述脚本并将其添加到组件中。

NativeScript:

struct DLL_API NativeScript {
        std::unordered_map<unsigned int, std::string> nameToScriptIndex{};
        unsigned int scriptIndex = 0;
        std::array<GameObject*, HGE_MAX_SCRIPTS> scripts{nullptr};

        GameObject* gameObject = nullptr;

        void (*instantiateScript)(NativeScript*, const unsigned int&) = {};

        GameObject* (*instantiateFunction)() = {};
        void(*destroyFunction)(NativeScript*) = {};

        template<typename T>
        void addScript() {
            instantiateFunction = []() {return static_cast<GameObject*>(new T()); };
            destroyFunction = [](NativeScript* nativeScript) {delete nativeScript->gameObject; nativeScript->gameObject = nullptr; };
        }

        //name is the name of the dll file in which the script is in
        void addScript(const std::string& name) {
            nameToScriptIndex[scriptIndex] = name;
            scriptIndex += 1;
            
            instantiateScript = [](NativeScript* nativeScript, const unsigned int& index) {

                if (ScriptManager::getScript(nativeScript->nameToScriptIndex[index]) != nullptr) {
                    GameObject* script = ScriptManager::getScript(nativeScript->nameToScriptIndex[index]);



//I believe the error is this line 
                    nativeScript->scripts[index] = (GameObject*)malloc(sizeof(script));
                    memcpy(nativeScript->scripts[index], script, (sizeof(script)));
                }
                else
                    Debug::systemErr("Couldn't find script: " + nativeScript->nameToScriptIndex[index]);
            };
        }

        void destroyScripts() {

        }

    };

现在我只使用数组中的第一个脚本进行测试

运行脚本的场景代码:

if (system.getComponentManager()->hasComponent<NativeScript>(entity)) {
                auto& script = system.getComponentManager()->getComponent<NativeScript>(entity);

                if (!script.scripts[0]) {
                    script.instantiateScript(&script, 0);

                    //add the entity reference to the script (to call things like getComponent<>())
                    script.scripts[0]->entity = entity;
                    script.scripts[0]->scene = this;
                    script.scripts[0]->created = true;

                    //startup the script
                    script.scripts[0]->start();
                }

            }

最后是脚本本身:

//test script
    class DLL_API TestScript : public Script {
    public:
    public:

        //GuiFrame* frame;

        Vec2f testVariable;

        void start() {
            testVariable = Vec2f();
        }

        void update() {

        }

    };

    __declspec(dllexport) Script* CreateScript()
    {
        return new TestScript();
    }

我通常遇到的错误是说该变量不存在。我在 dll 上尝试了很多不同的导出选项,但无济于事。如果您需要更多 类 或代码,请询问。

抛出的错误在删除运算符中。我没有任何信息或变量,只是它在删除运算符中抛出异常。

所以我修复了它。我不知道如何进行任何 DLL 链接,所以我在这里找到了这篇精彩的文章:https://www.gamasutra.com/blogs/ZacHills/20170406/295378/Scripting_with_C.php。然后我跟着做,然后我做了不同的一件事,而不是存储 createScript();函数本身 我存储了一个指向使用它创建的脚本的指针。所以现在我存储了函数本身,我不必手动分配任何东西,函数会为我做这件事。

void ScriptManager::loadScriptFromDLL(const std::string& path, const std::string& _name, const bool& supressError) {
        //credits to https://www.gamasutra.com/blogs/ZacHills/20170406/295378/Scripting_with_C.php bc idk how tf to do this

        HINSTANCE dllHandle = LoadLibraryA(path.c_str());

        if (!dllHandle) {
            Debug::systemErr("Couldn't load dll file containing scripts at: " + path);
        }

        typedef GameObject* (__stdcall* scriptPointer)();

        scriptPointer createScript = (scriptPointer)GetProcAddress(dllHandle, "CreateScript");

        if (!createScript) {
            Debug::systemErr("Couldn't find the create function of a script in the dll file containing scripts at: " + path + "(Check if there is an export function for the script)");
        }

        GameObject* out = createScript();

        std::string name = _name.substr(0, _name.length() - 4);

        if (scriptPathToName.find(path) == scriptPathToName.end() && scriptNameToScript.find(name) == scriptNameToScript.end()) {
            scriptPathToName[path] = name;
            numberToPath[scriptAmount] = path;
            scriptNameToScript[name] = out;

//HERE
            scriptNameToScriptCreate[name] = createScript;

            Debug::systemSuccess("Loaded script: " + name, DebugColor::Blue);
            scriptAmount += 1;
        }
        else {
            if(!supressError)
            Debug::systemErr("Already loaded script file: " + path + ", or already loaded script with name: " + name);
        }

    }

在此代码中显示了我存储函数的行,该函数存储在无序映射中:

static std::unordered_map<std::string, GameObject* (__stdcall*)()> scriptNameToScriptCreate;

现在创建脚本:

GameObject* ScriptManager::createScript(const std::string& name) {
    return scriptNameToScriptCreate[name]();
}

现在在本机脚本中 class:

void addScript(const std::string& name) {
            nameToScriptIndex[scriptIndex] = name;
            scriptIndex += 1;
            
            instantiateScript = [](NativeScript* nativeScript, const unsigned int& index) {

                if (ScriptManager::getScript(nativeScript->nameToScriptIndex[index]) != nullptr)
                    nativeScript->scripts[index] = ScriptManager::createScript(nativeScript->nameToScriptIndex[index]);
                else
                    Debug::systemErr("Couldn't find script: " + nativeScript->nameToScriptIndex[index]);
            };
        }

而不是:

void addScript(const std::string& name) {
            nameToScriptIndex[scriptIndex] = name;
            scriptIndex += 1;
            
            instantiateScript = [](NativeScript* nativeScript, const unsigned int& index) {

                if (ScriptManager::getScript(nativeScript->nameToScriptIndex[index]) != nullptr) {
                    GameObject* script = ScriptManager::getScript(nativeScript->nameToScriptIndex[index]);
                    nativeScript->scripts[index] = (GameObject*)malloc(sizeof(script));
                    memcpy(nativeScript->scripts[index], script, (sizeof(script)));
                }
                else
                    Debug::systemErr("Couldn't find script: " + nativeScript->nameToScriptIndex[index]);
            };
        }

我怀疑这对任何人都有帮助,但我只是想让你们知道我是如何修复它的。抱歉超长的回答。