Skip to main content

Migrating from SLua to ZLua

Feature background: compare/FEATURES.md SLua is similar to toLua, emphasizing export config / auto-binding and LuaSvr; the migration path overlaps heavily with toLua—this page highlights SLua-specific items. Type-path adaptor (optional): Spec 12 · slua adaptor · Migration index


1. Concept mapping

SLuaZLua
LuaSvr / LuaSvrGameObjectLuaAppDomain.Initialize
LuaStateBuilt into the ZLua host; not exposed directly
[CustomLuaClass] / export XMLNo access-control whitelist; public lazy Bind (adaptor list is migration-only)
LuaFunction / LuaTableGetFunction, implicit param marshal, require modules (adaptor does not cover)
SLua.LuaObject bindingObjectRegistry + marshal
UnityEngine.GameObject namespace chainNative: CSharp[asm][full]; or slua adaptor keeps _G.UnityEngine.*
Value-type GC opts (version-dependent)ByVal / Opaque / ObjectRegistry (see compare/GC.md)

2. Step-by-step migration

Step 1: Remove SLua runtime and generated code

  1. Delete the SLua plugin directory and Slua namespace references.
  2. Delete auto-generated Assets/Slua/ or Generated/ binding code.
  3. Remove LuaSvr / LuaSvrMain components from scenes.

Step 2: Initialization mapping

Before (SLua):

LuaSvr.mainState.doString("require 'Main'");
// 或 LuaSvrGameObject 启动

After (ZLua):

LuaAppDomain.Initialize(moduleLoader);
// Lua: require 'Main'

Call once from RuntimeInitializeOnLoadMethod or the game entry.

Step 3: Type access (pick one)

In package: ZLua~/adaptors/slua/ExportTypes.cs + shared ZLua~/adaptors/adaptor.lua. Contract: Spec 12.

  1. In a project that still has SLua, copy ExportTypes.cs → Editor, menu ZLua/ExportTypes
  2. Generate slua_export_types.lua from [CustomLuaClass] and existing export marks
  3. Put the list and adaptor.lua where the ZLua project can require them
  4. Entry:
local export_types = require "slua_export_types"
local adaptor = require "adaptor"
adaptor.init(export_types)
-- 此后 UnityEngine.GameObject 等命名空间链可用(清单内;无 CS 前缀)

Still must hand-edit: generic construction, GetFunction, Event, ref/Opaque, etc. (adaptor only solves type-table entry).

3B. Rewrite to native CSharp

SLua often uses namespace chains directly:

Before:

local GameObject = UnityEngine.GameObject
local obj = GameObject.Find("Root")
local list = System.Collections.Generic.List_int()() -- 视 SLua 导出命名

After:

local GameObject = CSharp['UnityEngine.CoreModule']['UnityEngine.GameObject']
local obj = GameObject.Find("Root")

local ListDef = CSharp.mscorlib['System.Collections.Generic.List`1']
local List_int = zlua.make_generic_type(ListDef, zlua.types.int32)
local list = List_int()

Step 4: SLua export config → visibility

Before: CustomExport.cs, [CustomLuaClass], static export lists

After:

  • Delete export config.
  • APIs Lua must not see → internal / private.
  • Note: without a whitelist, Il2Cpp still links public metadata; sensitive surface is C# visibility, not SLua-style export trimming.

Step 5: LuaFunction and delegates

Before:

LuaFunction laf = (LuaFunction)lua["callback"];
laf.call(1, 2);

or SLua’s LuaDelegation generation.

After:

static readonly Action<int, int> InvokeCallback =
LuaAppDomain.GetFunction<Action<int, int>>("mod", "callback");
InvokeCallback(1, 2);

// 或 Lua function 作参数
public static void SetHandler(Action<int,int> h) { ... }

// 或把 Lua 函数拿回 C#(替代长期持有 LuaFunction)
static readonly Func<Action<int, int>> GetCallback =
LuaAppDomain.GetFunction<Func<Action<int, int>>>("mod", "get_callback");
mod.SetHandler(function(a,b) end)

-- get_callback 返回 function,由返回值 Marshal 为 Action
local function get_callback()
return function(a, b) print(a, b) end
end

Dynamic by-name / arbitrary delegate types: see Function and Delegate.

Step 6: Replace SLua-specific APIs

SLuaZLua
LuaVar / LuaArrayNative Lua table or C# array marshal
checkVar / manual type checksMarshal errors thrown by ZLua
Slua.CreateClassNone; use C# types + constructors
LuaSvr.doUpdateDelegate from GetFunction inside C# Update

Step 7: Value types

Some SLua versions optimize Vector3 etc.; on ZLua:

-- Unity Vector3 经程序集类型表
local Vector3 = CSharp['UnityEngine.CoreModule']['UnityEngine.Vector3']
local v = Vector3(1, 2, 3)
-- struct ByVal;见 tc_marshal_unity_vector

ref / out / C#→Lua Opaque rules match from-xlua.md §Step 7.

Step 8: Testing

  • Move critical SLua cases into Tests/Lua/cases/
  • Run dual-end manifest per TESTING.md

3. Common pitfalls

PitfallNotes
Global UnityEngine.X missingUse slua adaptor, or CSharp[assembly]['UnityEngine.X']
Depend on SLua auto-export orderZLua lazy Bind; no order dependency
[CustomLuaClass] subclass exportUse public inheritance + normal type access
Multiple LuaSvr statesZLua defaults to a single main lua_State
Hotfix DLL + SLuaRebuild ZLua Codegen / assembly load strategy
Editor vs Player differencesSLua is more uniform; ZLua must verify Player
Assume “no export = no package cost”See compare/BRIDGE.md trimming section

4. Before / After examples

4.1 Component script (Lua calling Unity)

Before (SLua):

function OnEnable()
self.transform = self.gameObject.transform
self.timer = 0
end

function Update()
self.timer = self.timer + UnityEngine.Time.deltaTime
end

After (ZLua):

local Time = CSharp['UnityEngine.CoreModule']['UnityEngine.Time']

function OnEnable()
self.transform = self.gameObject.transform
self.timer = 0
end

function Update()
self.timer = self.timer + Time.deltaTime
end

(If MonoBehaviour scripts are still driven by SLua, switch to the ZLua host + module loading first; exact host integration varies by project.)

4.2 Static utility class

Before:

local util = Slua.CreateClass("MyUtil")
function util.foo() return 1 end

After: define public static class MyUtil in C#, Lua:

local MyUtil = CSharp['Assembly-CSharp']['MyUtil']
MyUtil.Foo()

4.3 Events (no SLua/xLua sugar)

Before (if using SLua delegate binding):

// SLua 生成或手动 Bind

After:

obj:add_Click(function() end)
obj:remove_Click(fn)

5. API quick reference

CapabilitySLuaZLua
Start VMLuaSvr.initLuaAppDomain.Initialize
Run filedoFilerequire + loader
Call C# staticExported classCSharp[asm][type].Method
Call C# instance:: (same Lua semantics)
C# call LuaLuaFunctionGetFunction<T>
Create delegateSLua gen / LuaFunctionImplicit param marshal, or GetFunction / to_delegate
Generic ListExport closed typezlua.make_generic_type
ArraysExportzlua.make_szarray_type / new_*array*
ReflectionPartial SLua supportzlua.typeof / CSharp lazy Bind

6. Relation to the toLua migration doc

TopicSee
Delete Wrap, global classesfrom-tolua.md
GetFunction, Opaquefrom-xlua.md
Performance/GCcompare/

7. Acceptance checklist

  • No Slua / LuaSvr references
  • No SLua generated binding directories
  • Type entry: adaptor.init or scripts use CSharp[asm][full] (no surprise global pollution)
  • Il2Cpp Player full tests pass
  • Performance profiling (if migrating from SLua for perf) — see PERFORMANCE

DocContents
migration/Shared checklist and adaptor overview
spec/12-MIGRATION-ADAPTORS.mdslua adaptor contract
spec/02-TYPE-SYSTEM.mdType naming
compare/GC.mdGC boundaries