[关闭]
@sssunny 2018-09-10T08:05:17.000000Z 字数 4638 阅读 297

ui config 配置指南

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

脚本配置主要负责:UI脚本与FairyUI资源关联的配置

UI脚本配置

  • 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=""})

EXCEL配置主要负责:UI层级,灯光,声音等表现为主

EXCEL配置


UI脚本

界面脚本被闭包括起来,可以读取全局环境,但不可以直接修改全局环境,所有的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),这样写将会有更友好的提示给非技术人员
  1. -- 初始化界面
  2. function initcom()
  3. herobtn = getchild("pannel/herobtn") --mainview:GetChild("pannel"):GetChild("herobtn")
  4. herobtn.onClick:Add(function() -- 为按钮添加监听
  5. ui.open("hero", 1) -- 打开hero界面,并且传一个参数 1
  6. end)
  7. pvebtn = mainview:GetChild("pvebtn")
  8. end
  9. -- 界面显示出来时候调用,会接到透穿参数
  10. function show(p1, p2)
  11. print("open params", p1, p2)
  12. end
  13. -- 被关闭时调用,可选,mainview已经被释放
  14. function onclose()
  15. print("home ui closed")
  16. end
  17. -- 自定义方法
  18. function customfunc(...)
  19. end

UI管理接口

  • 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)
    关闭指定名字的单例界面

UI脚本的一些内置方法

  • 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变成空方法
    用来解决界面关闭时的引用释放问题

UI对象的释放说明

  • 产生原因
    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类型的属性

  1. -- supermobs/ui/fairygui.lua
  2. -- [[
  3. 显式强转delegate类型时,为luafunction添加一层包装 tocfunc
  4. 界面关闭时,释放tocfunc与实际的luafunction之间的关联,将循环引用的闭环打破
  5. ]]
  6. -- ui auto release delegate
  7. local delegates = {"EventCallback1", "PlayCompleteCallback"}
  8. for _,dname in ipairs(delegates) do
  9. local raw = FairyGUI[dname]
  10. FairyGUI[dname] = function(func, obj)
  11. local env = getfenv(func)
  12. local tocfunc = func
  13. if env ~= _G and env.__releasefuncs then
  14. table.insert(env.__releasefuncs, function()
  15. func = nil
  16. obj = nil
  17. env = nil
  18. end)
  19. tocfunc = function(...) if func then func(...) end end
  20. end
  21. return obj == nil and raw(tocfunc) or raw(tocfunc, obj)
  22. end
  23. end
  24. -- [[
  25. 这里是一些直接赋值luafunctionc#的包装
  26. 原理与delegate相同
  27. ]]
  28. -- lua function to c#
  29. local setkey, getkey
  30. do
  31. local lud = {}
  32. for k,v in pairs(getmetatable(GLabel)) do
  33. if type(k) == "userdata" and type(v) == "table" then
  34. table.insert(lud, k)
  35. end
  36. end
  37. -- 内存地址值较小的是setkey,较大的是getkey
  38. if tonumber(tostring(lud[1]):sub(10)) < tonumber(tostring(lud[2]):sub(10)) then
  39. setkey, getkey = lud[1], lud[2]
  40. else
  41. setkey, getkey = lud[2], lud[1]
  42. end
  43. end
  44. local funcpropertys = {{GList, "itemRenderer"}, {GList, "itemProvider"}}
  45. for _,item in ipairs(funcpropertys) do
  46. local tab = getmetatable(item[1])[setkey]
  47. local rawfunc = tab[item[2]]
  48. tab[item[2]] = function(self, func)
  49. local env = getfenv(func)
  50. local tocfunc = func
  51. if env ~= _G and env.__releasefuncs then
  52. table.insert(env.__releasefuncs, function()
  53. func = nil
  54. env = nil
  55. end)
  56. tocfunc = function(...) if func then func(...) end end
  57. end
  58. return rawfunc(self, tocfunc)
  59. end
  60. end
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注