GDNative + PluginScript library that adds support for Lua as a scripting language in Godot.
Being a GDNative library, recompiling the engine is not required, so anyone with a built release copied to their project can use it. Being a PluginScript language, Lua can seamlessly communicate with scripts written in GDScript / C# / Visual Script and vice-versa. This way, one can use the language that best suits the implementation for each script and all of them can understand each other.
This plugin is available in the Asset Library as Lua PluginScript and has online documentation.
For some usage examples, check out lps_coroutine.lua and plugin/lua_repl.lua.
Currently, only LuaJIT is supported, since the implementation is based on its FFI library.
Either:
- In Godot Editor, open the Asset Library tab, search for the Lua PluginScript asset, download and install it.
- Put a built release of the library into the project folder and restart Godot.
Make sure the
lua_pluginscript.gdnlib
file is located at theres://addons/godot-lua-pluginscript
folder. - Clone this repository as the project's
res://addons/godot-lua-pluginscript
folder and build for the desired platforms.
In the Project -> Project Settings...
window, some settings are available:
- Lua PluginScript/Package Path/Behavior: Whether templates will replace
package.path,
be appended to it or prepended to it.
Default behavior:
replace
. - Lua PluginScript/Package Path/Templates: String array of templates to be
injected into
package.path
. Default templates:res://?.lua
andres://?/init.lua
. - Lua PluginScript/Package C Path/Behavior: Whether templates will replace
package.cpath,
be appended to it or prepended to it.
Default behavior:
replace
. - Lua PluginScript/Package C Path/Templates: String array of templates to be
injected into
package.cpath
. Default templates:!/?.dll
and!/loadall.dll
on Windows,!/?.so
and!/loadall.so
elsewhere. - Lua PluginScript/Export/Minify On Release Export: Whether Lua scritps
should be minified on release exports.
Defaults to
true
.
Also, an editor plugin is included, currently with a barebones REPL for Lua
expressions, located in the bottom panel of the editor.
Enable the Lua PluginScript
plugin in the Plugins
tab of the Project Settings window.
Lua modules available at LuaRocks can be installed locally to the project:
luarocks install --lua-version 5.1 --tree <local modules folder name> <module name>
Adjust the package paths using the settings described above and Lua PluginScript
should be able to require
the installed modules.
- Provide support for Lua as a scripting language in Godot in a way that does not require compiling the engine from scratch
- Be able to seamlessly communicate with any other language supported by Godot, like GDScript, Visual Script and C#, in an idiomatic way
- Simple script description interface that doesn't need
require
ing anything - Support for LuaJIT and Lua 5.2+
- Support paths relative to
res://*
and exported game/app executable path forrequire
ing Lua modules - Have a simple build process, where anyone with the cloned source code and installed build system + toolchain can build the project in a single step
- Provide calls to all core Godot classes' methods via native method bindings
- Support multithreading on the Lua side
- Designing Godot Lua PluginScript
- Implementing the library's skeleton
- Integrating LuaJIT and FFI
- Initializing and finalizing scripts (TODO)
This is an example of how a Lua script looks like.
-- Class definitions are regular Lua tables, to be returned from the script
local MyClass = {}
-- Optional: set class as tool, defaults to false
MyClass.is_tool = true
-- Optional: set base class by name, defaults to 'Reference'
MyClass.extends = 'Node'
-- Optional: give your class a name
MyClass.class_name = 'MyClass'
-- Declare signals
MyClass.something_happened = signal()
MyClass.something_happened_with_args = signal("arg1", "arg2")
-- Values defined in table are registered as properties of the class
-- By default, properties are not exported to the editor
MyClass.some_prop = 42
-- The `property` function adds metadata to defined properties,
-- like setter and getter functions
MyClass.some_prop_with_details = property {
-- ["default_value"] or ["default"] or [1] = property default value
5,
-- ["type"] or [2] = variant type, optional, inferred from default value
-- All Godot variant type names are defined globally as written in
-- GDScript, like bool, int, float, String, Array, Vector2, etc...
-- Notice that Lua <= 5.2 does not differentiate integers from float
-- numbers, so we should always specify `int` where appropriate
-- or use `int(5)` in the default value instead
type = int,
-- ["get"] or ["getter"] = getter function or method name, optional
get = function(self)
return self.some_prop_with_details
end,
-- ["set"] or ["setter"] = setter function or method name, optional
set = 'set_some_prop_with_details',
-- ["usage"] = property usage, from `enum godot_property_usage_flags`
-- optional, default to `PropertyUsage.NOEDITOR`
usage = PropertyUsage.NOEDITOR,
-- ["hint"] = property hint, from `enum godot_property_hint`
-- optional, default to `PropertyHint.NONE`
hint = PropertyHint.RANGE,
-- ["hint_string"] = property hint text, only required for some hints
hint_string = '1,10',
-- ["rset_mode"] = property remote set mode, from `enum godot_method_rpc_mode`
-- optional, default to `RPCMode.DISABLED`
rset_mode = RPCMode.MASTER,
}
-- The `export` function is an alias for `property` that always exports
-- properties to the editor
MyClass.exported_prop = export { "This property appears in the editor" }
MyClass.another_exported_prop = export {
[[This one also appears in the editor,
now with a multiline TextArea for edition]],
hint = PropertyHint.MULTILINE_TEXT,
}
-- Functions defined in table are public methods
function MyClass:_ready() -- `function t:f(...)` is an alias for `function t.f(self, ...)`
-- Singletons are available globally
local os_name = OS:get_name()
print("MyClass instance is ready! Running on a " .. os_name .. " system")
end
function MyClass:set_some_prop_with_details(value)
self.some_prop_with_details = value
-- Indexing `self` with keys undefined in script will search base
-- class for methods and properties
self:emit_signal("something_happened_with_args", "some_prop_with_details", value)
end
function MyClass:get_some_prop_doubled()
return self.some_prop * 2
end
-- In the end, table with class declaration must be returned from script
return MyClass
- LuaJIT support
- Lua 5.2+ support
- Useful definitions for all GDNative objects, with methods and metamethods
- A
yield
function similar to GDScript's, to resume after a signal is emitted (GD.yield
) - Working PluginScript language definition
- PluginScript script validation and template source code
- PluginScript code editor callbacks
- PluginScript debug callbacks
- PluginScript profiling callbacks
- Package searcher for Lua and C modules that work with paths relative to
the
res://
folder and/or exported games' executable path - Lua REPL
- API documentation
- Unit tests
- Example projects
- Export plugin to minify Lua scripts
- Drop-in binary release in GitHub
- Submit to Asset Library
The API is documented using LDoc. Documentation may be generated with the following command:
make docs
This project uses git submodules for its dependencies, so be sure to activate submodules before building.
# clone this repository and activate submodules in a single command
git clone --recurse-submodules https://github.com/gilzoide/godot-lua-pluginscript.git
# or clone it normally and then activate submodules
git clone https://github.com/gilzoide/godot-lua-pluginscript.git
cd godot-lua-pluginscript
git submodule init
git submodule update
Build using make from project root, specifying the system as target:
# Choose one of the supported platforms, based on your operating system
make windows64 # x86_64
make windows32 # x86
make linux64 # x86_64
make linux32 # x86
make osx64 \ # "universal" multiarch x86_64 + amd64 dylib
# Optional: deployment target. If absent, uses 10.7 for x86_64 and 11.0 for arm64
MACOSX_DEPLOYMENT_TARGET=XX.YY \
# Optional: code sign identity. If absent, `codesign` is not performed
CODE_SIGN_IDENTITY=<identity> \
# Optional: additional flags passed to `codesign`
OTHER_CODE_SIGN_FLAGS=<flags>
# Cross-compiling for Windows using MinGW
make mingw-windows64 # x86_64
make mingw-windows32 # x86
# Cross-compiling for Android using NDK
make android-armv7a \ # Android ARMv7
NDK_TOOLCHAIN_BIN=/path/to/ndk/toolchains/llvm/prebuild/host_os-arch/bin
make android-aarch64 \ # Android ARM64
NDK_TOOLCHAIN_BIN=/path/to/ndk/toolchains/llvm/prebuild/host_os-arch/bin
make android-x86 \ # Android x86
NDK_TOOLCHAIN_BIN=/path/to/ndk/toolchains/llvm/prebuild/host_os-arch/bin
make android-x86_64 \ # Android x86_64
NDK_TOOLCHAIN_BIN=/path/to/ndk/toolchains/llvm/prebuild/host_os-arch/bin
# Cross-compiling for iOS in a OSX environment
make ios64 \ # Dylibs for iOS arm64 and simulator arm64 + x86_64
# Optional: minimum iOS version to target. If absent, uses 8.0
IOS_VERSION_MIN=X.Y
# Optional: code sign identity. If absent, `codesign` is not performed
CODE_SIGN_IDENTITY=<identity> \
# Optional: additional flags passed to `codesign`
OTHER_CODE_SIGN_FLAGS=<flags>
If you plan in using the export plugin, the following is also required:
make plugin
The GDNativeLibrary file lua_pluginscript.gdnlib
is already configured to use
the built files stored in the build
folder, so that one can use this
repository directly inside a Godot project under the folder addons/godot-lua-pluginscript
.
After building the desired libraries, a distribution zip can be built with:
make dist
This project uses the following software:
- godot-headers: headers for GDNative, released under the MIT license
- LuaJIT: Just-In-Time Compiler (JIT) for the Lua programming language, released under the MIT license
- High Level GDNative (HGDN): higher level GDNative API header, released to the Public Domain
- LuaSrcDiet: compresses Lua source code by removing unnecessary characters, released under the MIT license