This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
如果您需要与外部软件或硬件进行底层交互,而 Lua 无法满足需求,Defold SDK 允许您根据目标平台使用 C、C++、C#、Objective-C、Java 或 JavaScript 为引擎编写扩展。原生扩展的典型用例包括:
C# 支持是实验性的,用于原生扩展,而不是 Defold 脚本组件。它使用 .NET 9 NativeAOT 生成静态库;将 .cs 源文件添加到扩展的 src 文件夹,构建服务就会生成项目文件。目标平台支持取决于当前 NativeAOT 和构建服务的能力。最新工作流程和经测试的设置请参阅官方原生扩展语言示例。
Defold通过基于云的构建解决方案,为零配置原生扩展提供了入口点。任何开发并添加到游戏项目中的原生扩展(无论是直接添加还是通过库项目添加),都将成为普通项目内容的一部分。无需构建特殊版本的引擎并分发给团队成员,这一过程会自动处理——任何构建和运行项目的团队成员都将获得一个包含所有原生扩展的项目特定引擎可执行文件。

Defold免费提供云构建服务器,没有任何使用限制。服务器托管在欧洲,发送本地代码的URL在编辑器首选项窗口中配置,或通过bob的--build-server命令行选项配置。如果您希望设置自己的服务器,请遵循这些说明。
要创建新扩展,请在项目根目录中创建一个文件夹。此文件夹将包含与扩展相关的所有设置、源代码、库和资源。扩展构建器会识别文件夹结构并收集任何源文件和库。
myextension/
│
├── ext.manifest
│
├── src/
│
├── include/
│
├── lib/
│ └──[platforms]
│
├── manifests/
│ └──[platforms]
│
└── res/
└──[platforms]
platform或architecture-platform命名的子文件夹中,具体取决于您的库支持的架构。
支持的平台有 ios, android, osx, win32, linux, web。
支持的 arc-platform 组合有 arm64-ios, x86_64-ios, armv7-android, arm64-android, arm64-osx, x86_64-osx, x86-win32, x86_64-win32, arm64-linux, x86_64-linux, wasm-web 和 wasm_pthread-web。
platform或architecture-platform命名的子文件夹中。还允许使用common子文件夹,包含所有平台通用的资源文件。扩展的可选manifests文件夹包含构建和打包过程中使用的其他文件。文件应放置在按platform命名的子文件夹中:
android - 此文件夹接受要合并到主应用程序中的清单存根文件(如此处所述)。
build.gradle文件,其中包含要由Gradle解析的依赖项。ios - 此文件夹接受要合并到主应用程序中的清单存根文件(如此处所述)。
Podfile文件,其中包含要由Cocoapods解析的依赖项。osx - 此文件夹接受要合并到主应用程序中的清单存根文件(如此处所述)。web - 此文件夹接受要合并到主应用程序中的清单存根文件(如此处所述)。扩展在项目中被视为与其他资产一样,可以以相同方式共享。如果原生扩展文件夹作为库文件夹添加,它可以作为项目依赖项共享给其他人使用。有关更多信息,请参考库项目手册。
让我们构建一个非常简单的扩展。首先,我们创建一个新的根文件夹myextension并添加一个包含扩展名”MyExtension“的ext.manifest文件。请注意,该名称是一个C++符号,必须与DM_DECLARE_EXTENSION的第一个参数匹配(见下文)。

# C++ symbol in your extension
name: "MyExtension"
该扩展由一个 C++ 文件 myextension.cpp 组成,该文件在 “src” 文件夹中创建。

扩展源文件包含以下代码:
// myextension.cpp
// Extension lib defines
#define LIB_NAME "MyExtension"
#define MODULE_NAME "myextension"
// include the Defold SDK
#include <dmsdk/sdk.h>
static int Reverse(lua_State* L)
{
// The number of expected items to be on the Lua stack
// once this struct goes out of scope
DM_LUA_STACK_CHECK(L, 1);
// Check and get parameter string from stack
char* str = (char*)luaL_checkstring(L, 1);
// Reverse the string
int len = strlen(str);
for(int i = 0; i < len / 2; i++) {
const char a = str[i];
const char b = str[len - i - 1];
str[i] = b;
str[len - i - 1] = a;
}
// Put the reverse string on the stack
lua_pushstring(L, str);
// Return 1 item
return 1;
}
// Functions exposed to Lua
static const luaL_reg Module_methods[] =
{
{"reverse", Reverse},
{0, 0}
};
static void LuaInit(lua_State* L)
{
int top = lua_gettop(L);
// Register lua names
luaL_register(L, MODULE_NAME, Module_methods);
lua_pop(L, 1);
assert(top == lua_gettop(L));
}
dmExtension::Result AppInitializeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result InitializeMyExtension(dmExtension::Params* params)
{
// Init Lua
LuaInit(params->m_L);
printf("Registered %s Extension\n", MODULE_NAME);
return dmExtension::RESULT_OK;
}
dmExtension::Result AppFinalizeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result FinalizeMyExtension(dmExtension::Params* params)
{
return dmExtension::RESULT_OK;
}
// Defold SDK uses a macro for setting up extension entry points:
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
// MyExtension is the C++ symbol that holds all relevant extension data.
// It must match the name field in the `ext.manifest`
DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
请注意用于声明扩展代码中各种入口点的宏 DM_DECLARE_EXTENSION。第一个参数 symbol 必须与 ext.manifest 中指定的名称匹配。对于这个简单的示例,不需要任何 “update” 或 “on_event” 入口点,因此在这些位置向宏提供了 0。
现在只需构建项目(Project ▸ Build)。这将把扩展上传到扩展构建器,构建器将生成一个包含新扩展的自定义引擎。如果构建器遇到任何错误,将显示一个包含构建错误的对话框。
要测试扩展,创建一个游戏对象并添加一个带有一些测试代码的脚本组件:
local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local reverse_s = myextension.reverse(s)
print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
就是这样!我们已经创建了一个完全可用的原生扩展。
如上所述,DM_DECLARE_EXTENSION 宏用于声明扩展代码中的各种入口点:
DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
入口点将允许您在扩展生命周期的各个点运行代码:
app_initinit - 所有Defold API已初始化。这是扩展生命周期中推荐的创建扩展代码Lua绑定的点。init() 函数被调用。updateupdate() 函数被调用。on_eventfinal() 函数被调用。finalapp_final构建器在每个相应平台上定义了以下标识符:
DM_PLATFORM_WINDOWSDM_PLATFORM_OSXDM_PLATFORM_IOSDM_PLATFORM_ANDROIDDM_PLATFORM_LINUXDM_PLATFORM_HTML5当项目使用原生扩展时,构建服务器日志可用。构建服务器日志(log.txt)在项目构建时与自定义引擎一起下载,并存储在项目的 .internal/%platform%/build.zip 文件中,同时也解压到项目的构建文件夹中。
Defold资产门户也包含多个原生扩展。