[游戏开发]Unity红点系统

红点系统设计到的内容有哪些

UI界面(例如主界面)、UI上的按钮红点(例如主界面上面有各种玩法的入口)、玩法数据(例如活动玩法的完成比例,它是驱动红点是否显示的关键要素)、红点管理器(修改红点状态,注册红点物体)、树形数据结构。

红点系统的特点

  1. 数据驱动
  2. 树形结构,且数据是从下向上修改的

提问:红点UI何时会亮起

答:当这个UI打开时,树形结构这个节点是亮起状态。

提问:树形结构这个节点如何判断亮起还是熄灭?

红点是显示还是隐藏是由数据驱动的,所以这个问题就是何时会修改数据

答:有3种情况,1、登录时拉取所有功能数据,2、服务器主动推送刷新功能数据(有部分功能在服务器不断Tick计算状态)3、用户操作后刷新功能数据(比如领取邮件奖励)

红点树型脑图

玩法数据是如何与红点显示状态关联的?

以邮件系统举例,

  1. 项目启动时,拉取服务器邮件数据,客户端的邮件管理器判断邮件列表1和2是可领取状态,向红点管理器设置邮件红点的状态为亮起(true)
  2. 进入主城并显示主城UI后,主城UI调用红点管理器的注册红点方法,此方法会拿到邮件对应的红点状态并设置红点UI是否显示。此时邮件按钮亮起
  3. 当用户点击领取邮件,前后端通信一次,服务器推送最新的邮件数据,客户端邮件管理器再次判断是否有可领取邮件,此时列表里还有一个未领取邮件,并再次设置邮件红点的状态为亮起(true)。
  4. 用户再次领取邮件,服务器推送最新的邮件数据,此时邮件已全部领取完毕,设置邮件红点的状态为熄灭(false)。

树形结构的难点在哪里

以脑图为例,夏季活动有两个分支(夏令营和运动),且都是红点亮起状态

当红色链条夏令营篝火晚会完成时,我们既要设置篝火晚会、夏令营的红点状态为熄灭,还不能影响蓝色链条的红点显示状态。因为这两个链条的数据是独立的

我是如何解决这两个链条互不影响的?

--[[
    遍历tab并查找目标
    找到目标后按深度加入列表
]]
local function travTab(tab, target,path)
    local find = false
    for key, subTable in pairs(tab) do
        if type(subTable) == "table" then
            if subTable == target then
                table.insert(path,target)
                return true
            else
                find = travTab(subTable,target,path)
                if find == true then
                    table.insert(path,subTable)
                    return true
                end
            end
        end
    end
    return false
end

核心就是这个深度递归获取路径的方法

tab是活动、target是篝火晚会,通过这个递归可以返回一个深度列表(1篝火晚会、2夏令营、3夏季活动、4活动)

for循环这个列表,由深到浅判断每一级的父亲是否有其他孩子是亮起的

举例:篝火晚会已完成,状态是熄灭,开始逐级设置状态

循环第一次是篝火晚会,篝火晚会的父亲是夏令营,检查夏令营的所有孩子是否有亮起,结果为无

循环第二次是夏令营,夏令营的父亲是夏季活动,检查夏季活动的所有孩子是否有亮起,结果孩子运动是亮起状态,那么只有篝火晚会和夏令营设置熄灭,循环结束

--[[
    检查父节点的所有子节点是否亮起
]]
local function CheckSubRedDot(parent)
    for index, subTab in pairs(parent) do
        if type(subTab) == "table" then
            if subTab.value == true then
                return true
            end
        end
    end
    return false
end

Lua版本红点系统实现

现在的UI业务大多数都是用Lua开发的,那我就写个Lua版本的红点系统

当我们require RedDotDefine.lua文件时,RedDot_Activity全局存在,可直接使用

制作好demo需要的UI,冬季活动的分支没做,夏季的足够演示


 

 下面是RedDotManager的源码

require 'Framework/RedDot/RedDotDefine'

--UI音频管理类--
RedDotManager = {
	IsRootLoaded = false
}
local this = RedDotManager

local RedDotDatas = {}

--[[
    遍历tab并查找目标
    找到目标后按深度加入列表
]]
local function travTab(tab, target,path)
    local find = false
    for key, subTable in pairs(tab) do
        if type(subTable) == "table" then
            if subTable == target then
                table.insert(path,target)
                return true
            else
                find = travTab(subTable,target,path)
                if find == true then
                    table.insert(path,subTable)
                    return true
                end
            end
        end
    end
    return false
end

--[[
    注册红点UI
]]
function RedDotManager.RegisterRedDotUI(target,redDotUI)
	target.RedDotUI = redDotUI
    redDotUI:SetActive(target.value == true)
end

function RedDotManager.UnRegisterRedDot() end

--[[
    检查父节点的所有子节点是否亮起
]]
local function CheckSubRedDot(parent)
    for index, subTab in pairs(parent) do
        if type(subTab) == "table" then
            if subTab.value == true then
                return true
            end
        end
    end
    return false
end

--[[
    设置红点状态
]]
function RedDotManager.SetRedDotState(tab,target,value)
    target.value = value
    if target.RedDotUI ~= nil then
        target.RedDotUI:SetActive(value)
    end

    --[[
        获取目标到根的深度路径
        tab是根,target是最深的节点
    ]]
    local path = {}
    travTab(tab,target,path)
    table.insert(path,tab)

    for index = 1, #path do--body 
        if index == #path then
            return
        end
        local parent = path[index + 1]
        parent.value = CheckSubRedDot(parent)
        if parent.RedDotUI ~= nil then
            parent.RedDotUI:SetActive(parent.value)
        end
    end
end

function RedDotManager.GetRedDotState(target)
    return target.value == true
end

 项目启动后,设置脑图中的篝火晚会和游泳节点设置为亮起

当主界面显示时,注册主界面的红点,其他所有界面启动后,注册红点都相同,就不挨个展示了

 
这个Demo中实现的玩法和上面的脑图保持一致,但只做了活动玩法的红点展示

红点系统其他实现方式

除了用Table来存储树形结构关系外,还有很多方式可以实现红点系统,例如直接用int值来存储,子节点都用根节点的值做加法,或者是乘法。所以说,只要你能找到一个方式能实现从下到上的节点索引,即可解决自下而上驱动树型结构数据的问题。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity系统是一种常用的游戏UI设计,主要用于提醒玩家当前有新的任务、奖励或其他未读信息需要处理。下面是一个简单的Unity系统设计: 1. 定义点控件:在UI界面中添加一个点控件,通常是一个小圆点或小数字。该控件需要有一个唯一的名称,用于后续的操作。 2. 定义点数据结构:为每个需要点提醒的功能定义一个点数据结构,包含以下信息: - 功能名称:用于标识该功能。 - 点控件名称:与UI界面中的点控件名称对应。 - 是否需要点提醒:标识该功能是否需要点提醒。 - 点数量:如果需要显示数字点,则需要记录具体的数量。 3. 定义点管理类:创建一个点管理类,用于管理所有的点数据和UI界面上的点控件。该类需要提供以下功能: - 添加点数据:向点管理类中添加新的点数据。 - 更新点状态:根据点数据中的信息,更新UI界面上对应的点控件状态。 - 监听点变化:提供回调函数,当某个点数据的状态发生变化时,通知相应的UI界面进行更新。 4. 使用系统:在需要使用系统的地方,调用点管理类的方法添加点数据和监听点变化。当点数据的状态发生变化时,点管理类会自动更新UI界面上的点控件状态。 通过以上步骤,就可以实现一个简单的Unity系统。当玩家有新的任务或奖励时,点控件会自动提醒玩家,增强了游戏的交互性和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Little丶Seven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值