Godot Lua API C# Examples
All future examples will be in the Wiki.
Getting Started Example (In C#)
In this example, we recreate the main GDScript example from the README.md file. I have fully commented this
example, to explain what each part does. Specific differences and a special note on this example: In C# you
cannot assign a Method to a Variant
for use with LuaAPI.PushVariant
. So, to get around that, and make the
example work, we will first wrap our called function in a Callable
variable (wrapper). Please note the line
Callable print = new Callable(this, MethodName.LuaPrint);
in the example below.
- Notes on Using
LuaFunctionRef
: It is the preferred way to call functions from within your Lua code base, if you do not know the function name ahead of time, or if the function is not global.LuaFunctionRef
will still be invokable if it is a global function, and that global function was overwritten, as it is copied into the lua state, and then referenced inside of C#. Removing all references to the LuaFunctionRef will release it out of the lua state and free up the state's memory. This means thatLuaAPI.CallFunction()
uses less resources in the lua state, so keep that in mind.
This example also shows how to use the newly added LuaFunctionRef
class to invoke
a lua function. This allows
for creating a call back function to respond to things like events. Note how we use .As<LuaFunctionRef>()
to cast
the Variant val
into a LuaFunctionRef
variable (get_message
). Additionally, we do not need to use the nullable
invoke style common to most event firing, as the get_message
variable is not null. The .Invoke()
method takes a
Godot.Collections.Array
as its only parameter. In this example, we make use of the shorthand to create a new
object
for the Godot Array class. This shorthand is only possible because of the way that Godot defines the Array
class, and
is not a normal C# new Object()
creation style.
using Godot;
public partial class Node2D : Godot.Node2D {
private LuaApi lua = new LuaApi();
public void LuaPrint(string message) {
GD.Print(message);
}
public override void _Ready() {
GD.Print("Starting Node2D.cs.");
// All builtin libraries are available to bind with. Use OS and IO at your own risk.
// BindLibraries requires a "Godot Array" so, let's build one.
Godot.Collections.Array libraries = new() {
"base", // Base Lua commands
"table", // Table functionality.
"string" // String Specific functionality.
};
lua.BindLibraries(libraries); // Assign the specified libraries to the LuaAPI object.
// In C#, .PushVariant does not work with Methods, so we use Callable to wrap our function.
Callable print = new Callable(this, MethodName.LuaPrint);
// Assign the Callable, so that the API can call our function.
// Note, the lua function "cs_print" is now callable within Lua script.
lua.PushVariant("cs_print", print);
// Assign a Lua Variable named "message" and give it a value.
lua.PushVariant("message", "Hello lua!");
// Use .DoString() to execute our Lua code.
LuaError error = lua.DoString("cs_print(message)");
// Check for errors, and if there are any, Print them to the Godot Console.
if (error != null && error.Message != "") {
GD.Print("An error occurred calling DoString.");
GD.Print("ERROR %d: %s", error.Type, error.Message);
}
error = lua.DoString(@"
for i=1,10,1 do
cs_print(message)
end
function get_message()
return ""This message was sent from 'get_message()'""
end
");
// Check for errors, and if there are any, Print them to the Godot Console.
if (error != null && error.Message != "") {
GD.Print("An error occurred calling DoString.");
GD.Print("ERROR %d: %s", error.Type, error.Message);
}
// Let's pull our lua function from the lua code.
var val = lua.PullVariant("get_message");
// Check to see if it returned an error, or a value.
if (val.GetType() == typeof(LuaError)) {
GD.Print("ERROR %d: %s", error.Type, error.Message);
return;
}
// We create a LuaFunctionRef as our reference to the Lua code's function,
// then we use .As<LuaFunctionRef>() to cast it as a LuaFunctionRef.
LuaFunctionRef get_message = val.As<LuaFunctionRef>();
if (get_message == null) {
GD.Print("ERROR: get_message is null.");
return;
}
// Calling Lua (code) functions requires a Godot.Collections.Array as the container
// for the parameters passed in.
Godot.Collections.Array Params = new();
// We use .Invoke to actually call the lua function within the Lua State.
// And, finally, we log the output of the function to Godot Output Console.
GD.Print(get_message.Invoke(Params));
}
}