Unity 之 ToLua框架中UI.Dropdown组件动态添加Options
前言
最近使用ToLua框架使用Unity中的Dropdown组件,其他属性都还好和在C#中使用的形式差不多,只是修改成了Lua的语法习惯就可以了,但是我有个需求,是要需要实现动态添加Dropdown中的Options,这个就很做起来废了半天劲,后来发现是被坑了,本文就说说在ToLua框架中使用Dropdown动态添加Options。
Unity 之 ToLua框架中使用Dropdown
一,在C#中动态添加Options
1.获取Dropdown组件,然后动态添加options:
//创建Dropdown自定义预制体,并获取其组件
Dropdown dropDown= GetPoolItem(rowRoot, "CreateRoom_Dropdown").GetComponent<Dropdown>();
Dropdown.OptionData data = new Dropdown.OptionData();
data.text = "下拉选项1";
dropDown.options.Add(data);
或者你也可以这么写:
List<Dropdown.OptionData> listOptions = new List<Dropdown.OptionData>();
listOptions.Add(new Dropdown.OptionData("下拉选项2"));
listOptions.Add(new Dropdown.OptionData("下拉选项3"));
dropDown.AddOptions(listOptions);
2.其他属性获取简介推荐查看:
Unity 之 UGUI Dropdown组件使用简析
二,在Lua中动态添加Options
1.首先要在CustomSettings中添加_GT(typeof(Dropdown.OptionData))
2.在工程中点击Lua --> Generate All 重新打出Warp包
3.然后你在工程LuaFramework --> Source --> Generate 目录下可以找到名字为UnityEngine_UI_Dropdown_OptionDataWrap的C#文件,然后看下Register方法,开始使用:
public static void Register(LuaState L)
{
L.BeginClass(typeof(UnityEngine.UI.Dropdown.OptionData), typeof(System.Object));
L.RegFunction("New", _CreateUnityEngine_UI_Dropdown_OptionData);
L.RegFunction("__tostring", ToLua.op_ToString);
L.RegVar("text", get_text, set_text);
L.RegVar("image", get_image, set_image);
L.EndClass();
}
4.使用Lua动态添加添加Options
在文件头做个引用
local OptionData = UnityEngine.UI.Dropdown.OptionData
按照C#中写的步骤使用Lua的形势写:
function CreateDropdown(ctrlNodel,rowParent)
-- 这里改成你自己的获取组件的方式
local newDorpDown = resMgr:LoadPrefab(PrefabsPath.."CreateRoom_Dropdown",rowParent):GetComponent("Dropdown");
-- 这是一个错误写法 正确需要用.调用
local data = OptionData:New();
data.text = "下拉选项1";
newDorpDown.options:Add(data);
end
按照这个流程写是没有问题的,如果你这时候运行后成功设置了options属性了,那么你就不用往下看了;如果你没有运行成功,请你断点调试或者在代码中间打几个日志。经查:我发现代码是在local data = OptionData:New();这行就执行出了问题,就没有向下执行了。
三,在Lua中使用需要注意的点
不知道为什么在New的时候执行逻辑会有问题,上面介绍过了,在UnityEngine_UI_Dropdown_OptionDataWrap
这个类里面,Lua中调用的New方法实际上走的是C#中的_CreateUnityEngine_UI_Dropdown_OptionData这个方法,看上面Register这个方法这样写的:
L.RegFunction("New", _CreateUnityEngine_UI_Dropdown_OptionData);
所以我去查看这个方法:
[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
static int _CreateUnityEngine_UI_Dropdown_OptionData(IntPtr L)
{
try
{
int count = LuaDLL.lua_gettop(L);
if (count == 0)
{
UnityEngine.UI.Dropdown.OptionData obj = new UnityEngine.UI.Dropdown.OptionData();
ToLua.PushObject(L, obj);
return 1;
}
else if (count == 1 && TypeChecker.CheckTypes<UnityEngine.Sprite>(L, 1))
{
UnityEngine.Sprite arg0 = (UnityEngine.Sprite)ToLua.ToObject(L, 1);
UnityEngine.UI.Dropdown.OptionData obj = new UnityEngine.UI.Dropdown.OptionData(arg0);
ToLua.PushObject(L, obj);
return 1;
}
else if (count == 1 && TypeChecker.CheckTypes<string>(L, 1))
{
string arg0 = ToLua.ToString(L, 1);
UnityEngine.UI.Dropdown.OptionData obj = new UnityEngine.UI.Dropdown.OptionData(arg0);
ToLua.PushObject(L, obj);
return 1;
}
else if (count == 2)
{
string arg0 = ToLua.CheckString(L, 1);
UnityEngine.Sprite arg1 = (UnityEngine.Sprite)ToLua.CheckObject(L, 2, typeof(UnityEngine.Sprite));
UnityEngine.UI.Dropdown.OptionData obj = new UnityEngine.UI.Dropdown.OptionData(arg0, arg1);
ToLua.PushObject(L, obj);
return 1;
}
else
{
return LuaDLL.luaL_throw(L, "invalid arguments to ctor method: UnityEngine.UI.Dropdown.OptionData.New");
}
}
catch (Exception e)
{
return LuaDLL.toluaL_exception(L, e);
}
}
这是框架个自动生成的方法啊,看起来没问啊,,,有不带参数的,一个参数的,两个参数的校验,并且有异常校验,简直是完美啊。然而为什么我上面的调用不好用呢,有些想不明白。
我尝试使用一个参数的形式调用:
function CreateDropdown(ctrlNodel,rowParent)
-- 这里改成你自己的获取组件的方式
local newDorpDown = resMgr:LoadPrefab(PrefabsPath.."CreateRoom_Dropdown",rowParent):GetComponent("Dropdown");
local data = OptionData:New("下拉选项1");
newDorpDown.options:Add(data);
end
结果运行起来还是不好使,两个参数的我也尝试了,结果当然还是不行。
我开始怀疑这个自动生成的这Warp文件执行的有问题啊,我在下图位置加了个日志:
运行起来果然有问题,我写的调用的无参数的然而输出的参数个数却是1个:
local data = OptionData:New();
同理我尝试了传一个参数调用,输出的参数个数是2个,事实证明当我使用OptionData:New();这种形式调用的时候,会默认传递一个参数,,,
默认参数,,,嗯,,,思考了下,学习Lua的时候使用冒号(:)调用的时候就会传递一个self啊,,,然后我尝试使用点(.)来调用,,,结果就真的没问题了,真是坑啊,,,还是自己没有使用明白啊,,,以此来博文,来加深下印象,希望可以帮到遇到相关问题的你。
修改后调用代码如下:
function CreateDropdown(ctrlNodel,rowParent)
-- 这里改成你自己的获取组件的方式
local newDorpDown = resMgr:LoadPrefab(PrefabsPath.."CreateRoom_Dropdown",rowParent):GetComponent("Dropdown");
local data = OptionData.New("下拉选项1");
newDorpDown.options:Add(data);
end