Skip to content

UI 表现优化 ​

客户端卡顿八成出在 UI 上。UI 从注册到显示要经历几个阶段,把它们拆开、错峰执行,是避免卡顿的核心思路。

UI 的四个阶段 ​

阶段API耗时特征
注册RegisterUI与界面复杂度无关,稳定均值,同一 UI 只注册一次
创建CreateUI受控件数量、图片总尺寸影响大,一般 10~40ms
显示SetScreenVisible已创建的界面显示只要 ~1ms
销毁SetRemove1~3ms,销毁后需重新 CreateUI

关键洞察:显示很快,创建很慢。把"创建"提前或错峰,只在需要时"显示",就不会卡。

用 UI 管理器分离各阶段 ​

基于 Create On Use 原则封装一个 UIMgr:初始化时统一注册所有 UI(客户端启动本来就要几秒,多花百来毫秒无感);首次 GetUI 时才创建并缓存;之后重复显示直接命中缓存。

python
class UIMgr(object):
    def __init__(self):
        self.mUIDict = {}

    def Init(self, system):
        self.mClientSystem = system
        for uiKey, config in UIData.iteritems():  # 启动时统一注册
            clientApi.RegisterUI(self.mModName, uiKey, config["cls"], config["screen"])

    def GetUI(self, uiKey):
        ui = self.mUIDict.get(uiKey)      # 优先命中缓存
        return ui if ui else self.CreateSingleUI(uiKey)  # 没有才创建

    def ShowUI(self, uiKey):
        ui = self.GetUI(uiKey)
        if ui: ui.Show()

    def CleanCacheUI(self):               # 合适时机释放内存
        for ui in self.mUIDict.values():
            ui.SetRemove()
        self.mUIDict.clear()

这样能保证同一时间只创建一个 UI、每个 UI 只创建一次,避免同时大量创建导致的卡顿。

其他关键技巧 ​

  • pushScreen 异步创建:整合创建+显示且分时完成,最大限度防卡顿。但只能同时显示一个界面,别与 CreateUI 混用。
  • 九宫贴图代替大图:一张 32×64 小图九宫拉伸即可铺出 297×198 背景,省内存。
  • 拆分复杂分页界面:控件总数越多创建越慢。像领地插件那样,把每个分页做成独立子界面,切分页=隐藏一个/显示另一个。
  • 分时执行 Clone:Clone 100 个组合控件要 867ms(而普通界面才 36ms)。先显示空界面,再每帧 Clone 5~10 个,几十帧内建完。
  • 过渡加载界面预建 UI:进游戏时用带进度条的全屏界面,每帧注册+创建一个后续要用的 UI,游戏中就只剩秒开的显示/隐藏。

性能红线 ​

项建议上限
单界面控件总数超过 1000 个明显卡顿
ScrollView 中 Clone 单元不超过 50 个
贴图分辨率1024×1024 是 512×512 的 4 倍开销,能小则小

不可见 ≠ 不消耗

SetVisible(False) 只是隐藏,控件仍占 UI 性能。ScrollView 里滚出视窗的控件才是重灾区——从数量上控制它。


下一篇多账号协同与控制台调试。回到基岩版网络游戏首页。