CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
界面UI框架设计

【界面UI】红点系统与面板刷新:UI 状态驱动设计

2026-09-20 07:58 作者:996 技术组 3 阅读 996引擎Lua教程传奇脚本
完整课程入口:996 全套课程体系Lua 学习路径幂尔框架 mirs.cn

红点为什么容易写崩

红点是留存利器,也是 UI 层最容易写乱的功能:每个系统各写一套红点逻辑,按钮点击后忘了通知其他红点,红点闪烁与实际状态对不上。问题的根源是把"红点"当成了各界面自己的私事。正确做法是把红点抽成独立的状态驱动系统:红点只是数据的一种渲染,数据变了红点自然变。

红点树:一个表驱动的实现

把所有红点按界面层级组织成树:根节点"主界面"下挂"背包""任务""商城",背包下又挂"可穿戴""可出售"。叶子节点的红亮条件是一个注册进来的检测函数,父节点红亮 = 任意子节点红亮。数值变化时只重算受影响的一条链:

lua
local RP = { nodes = {} }

function RP.reg(id, parent, check)
    RP.nodes[id] = { parent = parent, check = check, on = false }
end

function RP.refresh(id)
    local n = RP.nodes[id]
    local on = n.check and n.check() or false
    if not on then
        for _, child in pairs(RP.nodes) do
            if child.parent == id and child.on then on = true break end
        end
    end
    if n.on ~= on then
        n.on = on
        UIsetIcon(id, on)            -- 实际点亮/熄灭
        if n.parent then RP.refresh(n.parent) end
    end
end

数据变化处只需调一句 RP.refresh("bag"),整条链自动联动,任何界面都不需要自己维护红点状态。

刷新原则:状态驱动而非事件驱动

面板刷新同理。新手常写"领奖励 → 调刷新背包 → 调刷新任务 → 调刷新主界面",每加一个系统就要往所有相关事件里插刷新调用,漏一处就出"数字不对"的 bug。状态驱动的做法:界面显示时从数据源全量刷新一次,数据层变更后广播"某数据变了"事件,订阅者各自刷新——界面永远反映数据的当前真实状态,不存在"忘了通知谁"。

性能上注意两点:高频数据(血量)的刷新做合并,一帧内多次变更只渲染一次;面板不可见时只更新数据不刷新控件,打开时全量刷一遍。

排查口诀

红点不亮/常亮,按固定顺序查三步:检测函数的输入数据对不对(打印 check 结果)→ refresh 是否被正确触发(在 refresh 加计数日志)→ 父节点聚合逻辑是否覆盖了该子节点。状态驱动的系统里,问题永远落在"数据、订阅、聚合"三点之一,比在十几个界面文件里翻事件调用快得多。

← 返回文章地图返回研学路径