如何解决调试游戏引擎的脚本
您好,我为我的游戏引擎创建了一个脚本系统,我想知道是否有任何方法可以在运行时调试它。脚本系统如何工作的基本原则是创建一个新项目,它使用对引擎代码的引用,以便您可以使用它提供的功能。然后它将脚本导出为 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 举报,一经查实,本站将立刻删除。