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]);
};
}
我怀疑这对任何人都有帮助,但我只是想让你们知道我是如何修复它的。抱歉超长的回答。
所以我正在为我的游戏引擎编写脚本,一切似乎都正常,但如果涉及任何变量,它就会随机崩溃。我通过检查包含我的脚本的文件夹来获取脚本。然后我获取该文件夹中的所有 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]);
};
}
我怀疑这对任何人都有帮助,但我只是想让你们知道我是如何修复它的。抱歉超长的回答。