讲解xLua中lua侧判空问题,这点挺重要的,面试中问xLua问题大概率会问
一.代码展示
下面代码关键位置都有注释
cs
using UnityEngine;
using XLua;
namespace XLuaTest
{
// 扩展:走 UnityEngine.Object 重载的 ==,用于识别 Destroy 后的"假 null"
[LuaCallCSharp]
[ReflectionUse]
public static class UnityEngineObjectExtention
{
public static bool IsNull(this UnityEngine.Object o)
{
return o == null;
}
}
public class HotfixTest : MonoBehaviour
{
public GameObject obj;
LuaEnv luaenv = new LuaEnv();
void OnGUI()
{
if (GUI.Button(new Rect(10, 10, 420, 80), "Destroy后对比 C#/Lua 判空"))
{
if (obj == null)
{
Debug.LogWarning("请先在 Inspector 给 obj 赋值一个 GameObject");
return;
}
// 立即销毁,便于同帧对比(Destroy 会拖到帧末才真正销毁)
DestroyImmediate(obj);
// C#:== 为 true,但引用往往还在(假 null)
// → true:走 UnityEngine.Object 重载的 ==,已销毁就算"空"
Debug.Log("[C#] obj == null = " + (obj == null));
// → true:UnityEngine.Object.Equals 与重载 == 一致,已销毁则视为与 null 相等
Debug.Log("[C#] Equals(null, obj) = " + obj.Equals(null));
// → false:不走重载,只比引用;变量里对象还在,不是真正的 null
Debug.Log("[C#] ReferenceEquals(null, obj) = " + ReferenceEquals(null, obj));
// Lua:== nil 不可靠,IsNull / Equals(nil) 才正确
luaenv.Global.Set("host", this);
luaenv.DoString(@"
local o = host.obj
-- → false:userdata 还在,Lua 的 == nil 认不出 Unity 假 null
print('[Lua] o == nil =', o == nil)
-- → true:Equals 会走到 C#/Unity 判空,已销毁则为 true(o 为真 nil 时跳过调用)
print('[Lua] o:Equals(nil) =', o ~= nil and o:Equals(nil))
-- → true:扩展内部是 o == null,与 C# 的 obj == null 一致
print('[Lua] o:IsNull() =', o:IsNull())
print('结论: Destroy 后不要只用 == nil,应使用 IsNull() 或 Equals(nil)')
");
}
string chHint = @"Inspector 指定 obj 后点按钮。对比 Destroy 后 C#/Lua 判空差异。IsNull 需先 XLua > Generate Code。";
GUIStyle style = GUI.skin.textArea;
style.normal.textColor = Color.red;
style.fontSize = 16;
GUI.TextArea(new Rect(10, 100, 500, 220), chHint, style);
}
}
}
二.Demo演示

三.结论
1.当调用DestroyImmediate(obj)销毁对象后,C#侧走obj == null会走重载函数 与 obj.Equals(null)都为true,走的是判断对象是否实际销毁的逻辑
2.ReferenceEquals(null, obj)为false,执行的是引用检测,不看有没有Destroy
3.Lua侧的o == nil为false,也是引用判断
4.Lua侧可以用o ~= nil and o:Equals(nil),返回true
5.可以写个IsNull然后在lua侧用o:IsNull(),返回true
cs
public static bool IsNull(this UnityEngine.Object o)
{
return o == null;
}