@sssunny
2018-09-10T08:05:17.000000Z
字数 4638
阅读 297
pokemon
配置
UI
使用FairyGUI引擎 http://www.fairygui.com/
使用配置表和 ui.uiconfig.lua 协作配置
- 优点:1.参数配置更加灵活
- 2.程序和策划只关心自己的配置部分,减少excel配置表冲突
ui界面配置表目录: trunk\Desginer\Plan\10数据表\UI配置.xlsx
lua脚本UI配置目录:Project_Pokemon\Assets\Lua\pkm\ui\uiconfig
lua脚本Package配置目录(自动生成,不需要关心):Project_Pokemon\Assets\Lua\pkm\config\uipkg
- com string 组件名 (fairygui component)
- spt string 脚本路径 (script path)
- ecsexplicit string 明确 ecs component;示例:["town.*"];有命名相同时,需要明确是哪个命名系统下的;例如 town.level pet.level 需要指出是哪个
single int" 单例界面,可以缺省,缺省默认是单例界面,值为 0;其他值为非单例
EXCEL 配置主要负责:UI的层级以上4个属性,全部已lua脚本配置为准,其他属性,已配置表为准,
示例:ui.getpackage("package_name"):add("uiname", {com="", spt="", sigle=""})
界面脚本被闭包括起来,可以读取全局环境,但不可以直接修改全局环境,所有的global写操作都会卸载ui逻辑对象上
- __开头的变量或方法,uimanager保留内部使用
- 在编辑器模式下,ui脚本可以热更新,界面关闭重新打开会自动重新载入
- mainview 管理自动为界面创建的显示对象
- close() 关闭当前界面的方法,ui管理器自动为界面实现
- function initcom() end 初始化界面的组件
只可以获取com、control、trans 和 添加按钮监听之类的事情
mainview新建、重建、复用 时会调用
这个方法必须被实现- function show(...) end 打开界面的方法
可以实现界面逻辑
界面被打开、作为子界面加载到其他界面上 时会被调用,并透传参数
这个方法必须被实现- function onclose() end 当界面被关闭时会被调用
调用时mainview已经被释放,不可以再操作与ui组件相关内容
这个方法可选实现- getchild("name1/name2/name3")
- getcontroller("name1/name2/name3")
- gettransition("name1/name2/name3")
在界面的ui组件上查找子组件,相当于mainview:GetChild(name1):GetChild(name2):GetChild(name3),这样写将会有更友好的提示给非技术人员
-- 初始化界面
function initcom()
herobtn = getchild("pannel/herobtn") --mainview:GetChild("pannel"):GetChild("herobtn")
herobtn.onClick:Add(function() -- 为按钮添加监听
ui.open("hero", 1) -- 打开hero界面,并且传一个参数 1
end)
pvebtn = mainview:GetChild("pvebtn")
end
-- 界面显示出来时候调用,会接到透穿参数
function show(p1, p2)
print("open params", p1, p2)
end
-- 被关闭时调用,可选,mainview已经被释放
function onclose()
print("home ui closed")
end
-- 自定义方法
function customfunc(...)
end
- ui.open(name, ...)
打开指定名字的界面,并传参数给ui脚本的show方法
返回值是ui逻辑对象,可以用 uiobj.customfunc(...) 去调用ui脚本中的自定义方法- ui.add(name, com, ...)
以子界面的方式打开指定名字界面,并传参数{...}
com,父界面中的一个组件,子界面将会适配到这个com上
返回值是ui逻辑对象,与ui.open相同- ui.load(name, com, dispose, ...)
比ui.add多了删除com上原有子组件的逻辑
dispose,com上移除掉的组件是否销毁,默认值true;如果不销毁一定要自行管理好,避免泄露
返回值是ui逻辑对象,与ui.open相同- ui.apply(name, com, ...)
将com当做指定名字的界面来对待
一般用于不同界面上有一块完全一样的东西,这样可以共用逻辑,更方便维护
如果一个界面上的逻辑太多,也可以用这样的方式区分成为多个ui脚本- ui.tryapply(name, com, ...)
与ui.apply类似,额外增加了com上是否已经apply过脚本的判定
没有apply过的会新建uiobj并记录下来
已经apply过的将会直接调用uiobj的show方法- ui.get(name)
获取已经打开的指定名字的单例界面的ui逻辑对象- ui.close(name)
关闭指定名字的单例界面
- switch(name, com, ...)
在ui脚本内可使用的方法,在com上切换指定名字的子界面
比ui.load多了缓存管理,使用更方便
一般情况下,com上显示的东西不会变用ui.load,需要切换就用switch- settimeout、settimeinterval
对应接口是utils.time.xxxxx,功能相同,多了界面关闭时自动释放- **listen **
对应接口是utils.event.listen,功能相同,多了界面关闭时自动释放- close()
关闭自己- ecsgroup(poolname, matcher, func(group))
监控指定名字的pool中,matcher对应的group,每当group中的entity发生变化,执行func
界面关闭时自动删除监控
创建监控后,会自动立即回调一次刷新- ecstrigger(poolname)
在指定的pool中创建一个侦听器,界面关闭时自动删除侦听器
侦听器相当于一个触发式的system,system的以下接口可用addtrigger、setignoreselftriger、setensurematcher、setexcludematcher
使用方法on(callback(entities, count))来为侦听器添加触发执行的回调方法
可以通过off()暂停,on()重新打开;暂停时,trigger不会执行entity收集
使用接口destroy()销毁侦听器,一般等待界面关闭时自动销毁即可- weak(func)
返回一个跟func功能完全一样的function,当界面关闭时,返回的function变成空方法
用来解决界面关闭时的引用释放问题
产生原因
lua和c#都是高级语言,有自动gc机制存在
自动gc的判断规则都是从全局变量开始递归,查找被引用的对象
最终没有被递归进来的对象就是垃圾,被gc掉
在lua+tolua+c#的模式下,c#可能会引用luafunction,luafunction也可能引用c#Object
在fairygui的ui对象,往往会添加侦听函数luafunction,界面关闭时,ui对象引用了luafunction,luafunction引用了uiobj,uiobj中又引用了ui对象,就这样形成了一个循环**解决方案
打破导致循环引用中的任何一个点,所有的东西都会被自动gc掉
现在采用隐式的方案来解决这个问题(只在ui脚本中有效,不在ui脚本中时,需要自行理解来处理)
可以扩展delegate类型和fairyguiObject的function类型的属性
-- supermobs/ui/fairygui.lua
-- [[
显式强转delegate类型时,为luafunction添加一层包装 tocfunc
界面关闭时,释放tocfunc与实际的luafunction之间的关联,将循环引用的闭环打破
]]
-- ui auto release delegate
local delegates = {"EventCallback1", "PlayCompleteCallback"}
for _,dname in ipairs(delegates) do
local raw = FairyGUI[dname]
FairyGUI[dname] = function(func, obj)
local env = getfenv(func)
local tocfunc = func
if env ~= _G and env.__releasefuncs then
table.insert(env.__releasefuncs, function()
func = nil
obj = nil
env = nil
end)
tocfunc = function(...) if func then func(...) end end
end
return obj == nil and raw(tocfunc) or raw(tocfunc, obj)
end
end
-- [[
这里是一些直接赋值luafunction到c#的包装
原理与delegate相同
]]
-- lua function to c#
local setkey, getkey
do
local lud = {}
for k,v in pairs(getmetatable(GLabel)) do
if type(k) == "userdata" and type(v) == "table" then
table.insert(lud, k)
end
end
-- 内存地址值较小的是setkey,较大的是getkey
if tonumber(tostring(lud[1]):sub(10)) < tonumber(tostring(lud[2]):sub(10)) then
setkey, getkey = lud[1], lud[2]
else
setkey, getkey = lud[2], lud[1]
end
end
local funcpropertys = {{GList, "itemRenderer"}, {GList, "itemProvider"}}
for _,item in ipairs(funcpropertys) do
local tab = getmetatable(item[1])[setkey]
local rawfunc = tab[item[2]]
tab[item[2]] = function(self, func)
local env = getfenv(func)
local tocfunc = func
if env ~= _G and env.__releasefuncs then
table.insert(env.__releasefuncs, function()
func = nil
env = nil
end)
tocfunc = function(...) if func then func(...) end end
end
return rawfunc(self, tocfunc)
end
end