微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

调试游戏引擎的脚本

如何解决调试游戏引擎的脚本

您好,我为我的游戏引擎创建了一个脚本系统,我想知道是否有任何方法可以在运行时调试它。脚本系统如何工作的基本原则是创建一个新项目,它使用对引擎代码的引用,以便您可以使用它提供的功能。然后它将脚本导出为 dll,引擎读取该脚本并在引擎中使用该脚本。不过,我不知道如何在那里做断点之类的事情。

ScriptManager.h:

#define RegisterScript(className) extern "C" {__declspec(dllexport) Script* CreateScript(){ return new className(); } }

    struct GameObject;

    class DLL_API ScriptManager {
    private:
        static size_t scriptAmount;
        static double timeElapsed;

        static bool loadDllFromFolder(const std::string& path,const bool& supressError);

    public:
        static std::unordered_map<size_t,std::string> numberToPath;
        static std::unordered_map<std::string,std::string> scriptPathToName;
        static std::unordered_map<std::string,GameObject* (__stdcall*)()> scriptNametoScript;
        static std::unordered_map<std::string,HINSTANCE> scriptNametoHandle;

        static void loadScriptFromDLL(const std::string& path,const std::string& name,const bool& supressError);
        static void init();
        static void close();
        static void update();
        static void checkForScripts(const bool& supressError);
        //static size_t getAmountOfScripts();
        static GameObject* instantiateScript(const std::string& name);
        static bool checkScript(const std::string& name);

    };

ScriptManager.cpp:

std::unordered_map<std::string,std::string> ScriptManager::scriptPathToName{};
    std::unordered_map<std::string,GameObject* (__stdcall*)()> ScriptManager::scriptNametoScript{};
    std::unordered_map<size_t,std::string> ScriptManager::numberToPath{0};
    std::unordered_map<std::string,HINSTANCE> ScriptManager::scriptNametoHandle{};

    size_t ScriptManager::scriptAmount = 1;
    double ScriptManager::timeElapsed = 0;


    void ScriptManager::loadScriptFromDLL(const std::string& path,const std::string& _name,const bool& supressError) {

        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)");
        }

        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] = createScript;
            scriptNametoHandle[name] = dllHandle;

            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);
        }
    }

    void ScriptManager::init() {
        checkForScripts(false);
    }

    void ScriptManager::update() {
        ProfileMethod("ScriptManager update");
        timeElapsed += Time::getDeltaTime();

        if (timeElapsed >= HFR_SCRIPT_MANAGER_UPDATE_DELAY) {
            timeElapsed = 0;
            checkForScripts(true);
        }
    }

    void ScriptManager::checkForScripts(const bool& supressError) {
        
        if(!loadDllFromFolder(HFR_SCRIPTS,supressError))
            Debug::systemErr("Couldn't load scripts folder wtf");
    }

    void ScriptManager::close() {
        for (size_t i = 1; i < scriptAmount; i++) {
            FreeLibrary(scriptNametoHandle[scriptPathToName[numberToPath[i]]]);
            Debug::systemSuccess("Deleted script: " + scriptPathToName[numberToPath[i]],DebugColor::Blue);
        }
    }

    GameObject* ScriptManager::instantiateScript(const std::string& name) {
        if (scriptNametoScript.find(name) != scriptNametoScript.end()) {
            return scriptNametoScript[name]();
        }
        else {
            Debug::systemErr("No script found of name: " + name);
            return nullptr;
        }
    }

    bool ScriptManager::checkScript(const std::string& name) {
        return (scriptNametoScript.find(name) != scriptNametoScript.end());
    }

    bool ScriptManager::loadDllFromFolder(const std::string& path,const bool& supressError) {
        DIR* dir;

        struct dirent* ent;

        if ((dir = opendir(path.c_str())) != NULL) {

            while ((ent = readdir(dir)) != NULL) {
                std::string file = ent->d_name;

                if (file.find(".") != std::string::npos) {
                    if (file.find(".dll") != std::string::npos) {

#ifdef _DEBUG
                        if (file.substr(file.find(".dll") - 2,2) == "_D")
                            loadScriptFromDLL(path + file,file,supressError);
                        else if (!supressError && file.substr(file.find(".dll") - 2,2) != "_R")
                            Debug::systemErr("Couldn't load script dll: " + file + ",because it doesn't have debug identification,it should be: scriptname_D.dll. At path: " + path);
#else
                        if (file.substr(file.find(".dll") - 2,file.find(".dll")) == "_R")
                            loadScriptFromDLL(path + file,supressError);
                        else if (!supressError)
                            Debug::systemErr("Couldn't load script dll: " + file + ",because it doesn't have release identification,it should be: scriptname_R.dll. At path: " + path);
#endif
                    }
                }
                else {
                    //we have found a folder or a blank file
                    loadDllFromFolder(path + file + "/",supressError);
                }

            }

            closedir(dir);
            return true;
        }
        else
            return false;
    }

这是我制作的基本脚本, testscript.h(自动生成):

namespace testProject{

    class testScript : public Script {
    public:
        void start();
        void update();
        void fixedUpdate();
        void lateUpdate();
        void stop();
    };
    RegisterScript(testScript)

}

testscript.cpp:

#include "testScript.h"
using namespace HFR;

namespace testProject{

    void testScript::start() {
        Debug::log("start");
        //how do i put a breakpoint here?
    }

    void testScript::update() {

    }

    void testScript::fixedUpdate() {

    }

    void testScript::lateUpdate() {

    }

    void testScript::stop() {

    }

}

如果您想知道这是将脚本放入游戏对象的位置:

struct DLL_API NativeScript {
        std::unordered_map<unsigned int,std::string> nametoScriptIndex{};
        unsigned int scriptAmount = 0;

        std::array<GameObject*,HFR_MAX_SCRIPTS> scripts{nullptr};

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

        //name is the name of the dll file in which the script is in
        void addScript(const std::string& name) {
            if (ScriptManager::checkScript(name)) {
                nametoScriptIndex[scriptAmount] = name;
                scriptAmount += 1;
            }
            else
                Debug::systemErr("Couldn't add script with name: " + name + ",because it wasn't registered");
            
            instantiateScript = [](NativeScript* nativeScript,const unsigned int& index) {
                GameObject* script = ScriptManager::instantiateScript(nativeScript->nametoScriptIndex[index]);
                if (script != nullptr)
                    nativeScript->scripts[index] = script;
                else
                    Debug::systemErr("Couldn't find script: " + nativeScript->nametoScriptIndex[index]);
            };
        }

        void destroyScripts() {

        }

    };

然后我会调用instantiateScript,它会运行存储的instantiateScript 函数

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?