在玩游戏的时候,尤其是手游的时候,经常会看到那些小红点,让你不断点进去,总有种逼死强迫症的感觉!从玩家的角度来说,很讨厌,其实程序员也比较讨厌的。虽然红点就2个状态,显示和不显示,但如果红点逻辑没写好,对性能的影响非常大。
先简单来说几个原因:
1.读表
没法避免的要素,几乎所有的红点逻辑都需要读表,这个就不说了。
2.监听事件太多
举个简单的例子:商城上的红点,比如一个商品购买最基本的必须要有钱(游戏币),那就需要监听货币事件,有人物等级限制,需要监听人物等级事件,有vip限制,需要监听vip等级事件,有够买限制,需要监听商店事件等等。导致的结果就是有时候事件频发的时候执行了很多遍红点逻辑。一般的做法就是做延迟,到现在也没遇到什么好的解决方案。不知道有大神知道吗?
3.子页签
其实一开始我认为要写红点逻辑一般会采用树结构,直到我看到了神一般大代码后,我服了!举个简单的例子:还是商店,主界面会有商店Icon,商店里有页签,页签里有很多商品,这些全部都是分开的,比如执行一大串红点逻辑后,显示商店Icon红点,再执行一大串几乎一样的逻辑后,显示页签红点,再执行一大串几乎一样的逻辑后,显示商品红点。这个我就不太多说了。
先来幅自己画的树结构,不错,符合程序美。树结构具体什么就不解释了,网上一堆,看数据结构也绕不过去。只要明白叶节点决定父节点,父节点的父节点,父节点的父节点的父节点。。。是否显示红点就好了,这应该很清楚了。
直接上代码,因为项目是lua,所以红点也是lua写的,易于以后热更。
require "Manager/RedDotStateMgr"
local RedDot = {}
RedDot.__index = RedDot
function RedDot:New()
local new_ins = {}
setmetatable(new_ins, RedDot)
new_ins.m_dotName = 0
new_ins.m_bIsShow = false
new_ins.m_childDotList = {}
return new_ins
end
-- 从叶节点往根节点递归
function RedDot:GetIsShowRedDot()
if self.m_childDotList == nil or next(self.m_childDotList) == nil then
return self.m_bIsShow
end
local bIsShow = false
for childDotName, childDot in pairs(self.m_childDotList) do
if childDot:GetIsShowRedDot() then
bIsShow = true
break
end
end
return bIsShow
end
-- 获取红点数量
function RedDot:GetRedDotNum()
if self.m_childDotList == nil or #self.m_childDotList == 0 then
return 0
end
local redDotNum = 0
for childDotName, childDot in pairs(self.m_childDotList) do
if childDot:GetIsShowRedDot() then
redDotNum = redDotNum + 1
end
end
return redDotNum
end
--刷新叶节点数据
function RedDot:UpdateLeafData(bIsShow)
self.m_bIsShow = bIsShow
end
--获取子节点数据
function RedDot:GetChildDot(childDotName)
return self.m_childDotList[childDotName]
end
--添加子节点数据
function RedDot:AddChildDot(childDotName, childDot)
self.m_childDotList[childDotName] = childDot
end
RedDotMgr = {}
RedDotMgr.m_DotDataList = {}--红点数据
RedDotMgr.m_DotUIList = {}--红点UI
--设置红点状态,树结构
--childDotName:子节点,parentDotName:根节点
--bIsShow:只需要设置叶节点状态
function RedDotMgr:SetRedDotState(childDotName, parentDotName, bIsShow)
local childDot = self:GetRedDot(childDotName)
if bIsShow ~= nil then
childDot:UpdateLeafData(bIsShow)
end
local parentDot = self:GetRedDot(parentDotName)
if parentDot:GetChildDot(childDotName) == nil then
parentDot:AddChildDot(childDotName, childDot)
end
end
--显示红点(从池里取)
function RedDotMgr:ShowRedDotUI(dotName, parentTran, pos)
if self:GetRedDotIsShow(dotName) then
local redDotUI = self:GetRedDotUI(dotName, parentTran)
if redDotUI == nil then
self:CreateRedDotUI(dotName, parentTran, pos)
end
else
self:RemoveRedDotUI(dotName)
end
end
--删除红点(放回池里)
function RedDotMgr:RemoveRedDotUI(dotName)
if self.m_DotUIList[dotName] ~= nil then
// 放回池里
self.m_DotUIList[dotName] = nil
end
end
function RedDotMgr:GetRedDotUI(dotName)
return self.m_DotUIList[dotName]
end
function RedDotMgr:CreateRedDotUI(dotName, parentTran, pos)
// 动态创建红点GamObject
// 再挂到parentTran节点下
end
function RedDotMgr:GetRedDot(dotName)
if dotName == nil then return end
if self.m_DotDataList[dotName] == nil then
local tempDot = RedDot:New()
self.m_DotDataList[dotName] = tempDot
end
return self.m_DotDataList[dotName]
end
--获取红点状态:true:显示 false:不显示
function RedDotMgr:GetRedDotIsShow(dotName)
local dot = self:GetRedDot(dotName)
return dot:GetIsShowRedDot()
end
--获取子节点红点数量
function RedDotMgr:GetChildRedDotNum(dotName)
local dot = self:GetRedDot(dotName)
return dot:GetRedDotNum()
end
逻辑很简单就不解释了,具体使用就这样,也很简单
function UUpdateDotState()
local isShow = false
// 一系列判断
RedDotMgr:SetRedDotState(叶节点, 子节点1, isShow)
RedDotMgr:SetRedDotState(子节点1, 子节点2)
//。。。
RedDotMgr:SetRedDotState(子节点n, 根节点)
end
function UpdateRedDotUI()
RedDotMgr:ShowRedDotUI(叶节点, 叶节点transform)
RedDotMgr:ShowRedDotUI(子节点1, 子节点1transform)
//。。。
RedDotMgr:ShowRedDotUI(根节点, 根节点transform)
end
function UIHero:RemoveRedDotUI()
RedDotMgr:RemoveRedDotUI(叶节点)
RedDotMgr:RemoveRedDotUI(子节点1)
//。。。
RedDotMgr:RemoveRedDotUI(根节点)
end