Unity实战之类爬塔功能
Posted 爱上游戏开发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity实战之类爬塔功能相关的知识,希望对你有一定的参考价值。
推荐阅读:
前言
首先,小编在这里给大家道个歉。由于最近被生活折磨得不成人形,在文章输出方面明显能感觉到水的成分,虽然也在持续输出,但是大部分都是转载。
“盼来盼去盼不尽 天涯何处是归鸿”,终于有时间写文章了,来之不易的空闲时间,打算来介绍一下最近做的功能,先来看看成品吧!
功能简介
元朝圣殿,说白了就是一个类爬塔功能。根据星期开启对应类型的爬塔,爬塔按照一层一层的通关要求进行挑战。不可挑战已挑战的,不可跨层挑战。
首先看看主界面:包含帮助按钮,排行榜按钮和中间的5个圣殿。
创建对象,拼接界面如下:
可以发现,main下面的5个对象颜色与其他对象颜色不同,这就是传说中的预制体。
什么是预制体?
简单来说,预制体就是一个模板,你可以使用这个模板来快速生成一个相同的游戏对象,包括游戏对象的所有组件以及其下的所有子游戏对象。像上图中主界面场景那样,
这个预置体包括背景,名字,倒计时。他们长相一样却又有差异,就像双胞胎一样,名字不同,衣服(背景)不同,喜好(倒计时)不同一样。那么,怎么修改他们之间的区别呢?这时候我们
有两种解决办法:
1.直接在功能中替换名字背景
2.代码动态修改
由于策划的需求变幻莫测,推荐大家代码可以控制的表现,都用代码实现,手动在工程中修改真的很辛苦~
那么,接下来介绍一下如何代码动态修改。
首先创建一个table来存储这5个对象的信息:名字,背景,倒计时等
ui.relicsAdven =
ui.relicsAdven.Item = --RelicsAdvenItem
ui.relicsAdven.ItemTxt = --名字
ui.relicsAdven.ItemBg = --背景
ui.relicsAdven.openTm = --倒计时
ui.isOpen = --标识该神殿是否开启
for i = 1 , 6 do
ui.relicsAdven.Item[i] = base:findobj("Main/RelicsAdvenItem"..i)
ui.relicsAdven.ItemTxt[i] = utils.findtext(ui.relicsAdven.Item[i],"relicsName/Text")
ui.relicsAdven.ItemBg[i] = utils.findimage(ui.relicsAdven.Item[i],"bg")
ui.relicsAdven.openTm[i] = utils.findtext(ui.relicsAdven.Item[i],"openTm")
utils.addclickevent(ui.relicsAdven.Item[i],base.ClickPoint,i)
ui.isOpen[i] = false
end
接下来便是数据填充阶段了
local testData =
[1] = name = "光之圣殿",bgImg = "1",openTime = 1,,
[2] = name = "暗之圣殿",bgImg = "2",openTime = 2,,
[3] = name = "水之圣殿",bgImg = "3",openTime = 3,,
[4] = name = "火之圣殿",bgImg = "4",openTime = 4,,
[5] = name = "风之圣殿",bgImg = "5",openTime = 5,,
local function InitData()
local tm = os.time()
GetWeek(tm)
for i,v in ipairs(testData) do
ui.relicsAdven.ItemTxt[i].text = v.name
ui.relicsAdven.ItemBg[i].sprite = utils.loadsprite("relicsadven","relicsadven_00"..v.icon)
local temp = ""
for a,b in ipairs(v.openTime) do
if wday ~= b then
--未开启
if temp == "" then
temp = b
else
temp = string.format("%s,%s",temp,b)
end
end
end
if temp == "" then
--已经开启,倒计时
isOpen[i] = true
ui.relicsAdven.ItemBg[i].material = nil
local tm = GetReaminSecondsTo24()
if this.coroutine == nil then
settime(tm,i)
end
else
isOpen[i] = false
ui.endTm[i] = nil
ui.relicsAdven.ItemBg[i].material = Asset:LoadAsset(asseturi.getshaderpath("UIGray_Material"))
ui.relicsAdven.openTm[i].text = string.format("<color=#FF0000>周%s开启</color>",temp)
end
end
end
上述代码中有些功能,接下来做简单介绍:
获取当前星期几
1.通过时间戳获取当前是星期几的方法:
local function GetWeek(tm)
local temp = os.date("*t", tm)
local wday = temp.wday - 1
end
该方法返回的数据与星期的对应关系如下,因此需要减一:
1:星期天
2:星期一
3:星期二
4:星期三
5:星期四
6:星期五
7:星期六
接下来就是未开启的显示文本处理:
因为测试数据中openTime字段是一个table表,里面可能配有多个星期,需要处理一下数据:
首先创建一个temp变量,用来存储周几开启,如果temp值变了,代表未开启;没变,代表当前已开启
已开启需要显示关闭倒计时:显示倒计时,需要知道剩余时间,剩余时间=结束时间-当前时间。当前时间使用os.time()获取,结束时间为当天晚上13:59:59,那么如何获取当钱距离当天结束的剩余呢?请看下面代码:
距离当前结束倒计时
--获取到当日凌晨的剩余时间 返回秒数
function GetReaminSecondsTo24()
local toYear=os.date("*t").year
local toMonth=os.date("*t").month
local toDay=os.date("*t").day
local toTime = os.time(year =toYear, month = toMonth, day =toDay, hour =23, min =59, sec = 59)
local time=os.time()
return toTime-time
end
-- 获取到了剩余时时间戳,接下来就是倒计时计时器了,使用协程等待1秒的方式来实现:
local function settime(tm,index) --设置剩余时间
this.coroutine = coroutine.start(function ()
while true do
if this.gameObject == nil then
return
end
if tm < 1 then
--结束
ui.openTm[index].text = ui.openTxt[k]
coroutine.stop(this.coroutine)
this.coroutine = nil
else
tm = tm - 1
local timedata = FormatTime(tm)
ui.openTm[index].text = string.format("<color=#00FF00>%s 后关闭</color>",(timedata))
end
coroutine.wait(1)
end
end)
end
说明:当剩余时间<=0时,结束倒计时,协程停止并刷新界面;否则继续倒计时,显示剩余时间。
FormatTime函数:将时间戳转换为xx填xx小时XX分钟XX秒,具体实现如下:
local function second2DHMS(second)
if second <= 0 then
return 0,0,0,0
end
local d = math.floor(second / 86400)
second = second - d * 86400
local h = math.floor(second / 3600)
second = second - h * 3600
local m = math.floor(second / 60)
second = second - m * 60
local s = second
return d, h, m, s
end
local function FormatTime(_ls)
local _d, _h, _m, _s = second2DHMS(_ls)
local timedata = ""
if _h < 10 then
_h = "0".._h
end
if _m < 10 then
_m = "0".._m
end
if _s < 10 then
_s = "0".._s
end
if _d > 0 then
timedata = _d.."天".._h..":".._m..":".._s
else
timedata = _h..":".._m..":".._s
end
return timedata
end
至此,终于把主界面的显示搞定了,讲得有点详细,具体到了每个小功能的实现。
界面显示完成了,不容易啊。接下来就是界面的点击时间,点击神殿跳转到挑战界面。
选择圣殿
function view.ClickPoint(go,index)
if not isOpen[index] then
--未开启
print(“未开启)
return
end
local data =
data.type = index
--当前已经通过的层数,测试数据
local currLayer = 0
data.layerNum = currLayer + 1
--传数据给挑战界面并打开挑战界面
relicschallenge:setdata(data)
relicschallenge:open(nil,true)
end
说明:这两行代码是传数据并打开挑战界面。具体实现方法是由项目框架决定了,读者可以根据自己的实际项目调用自己的方法哦~
挑战界面
relicschallenge:setdata(data)
relicschallenge:open(nil,true)
挑战界面示意图如下:
功能第一版:使用循环列表来实现滑动列表,首先拼UI如下:
该界面为一个活动界面,显示每层的奖励信息及对应可操作按钮
(1)使用循环列表,需在content添加循环列表的计算脚本。如下图:如需使用循环列表脚本,可加群下载,csdn积分下载或者联系小编下载。
使用步骤如下:
1.创建Scroll View组件,在content上添加对应脚本。上下滑动:添加UILayoutVertical脚本;左右滑动:添加UILayoutHorizontal脚本
2.代码控制
ui.list = base:findcom("bot/Viewport/Content", "UILayout")
ui.list.onCreate = base.createrender
ui.list.onUpdate = base.updaterender
ui.list.ItemRenderer = Asset:LoadAsset(asseturi.getassetpath(base.module, "Item"))
ui.list.DataCount = #data--item总个数
ui.list:InvalidateData()
--创建item
local itemRender =
function base.createrender(go)
local render =
render.num = utils.findtext(go,"num")--层
itemRender[go] = render
end
--刷新item
function base.updaterender(go, index)
local config = data[index] --data中放着每个item的数据
local render = itemRender[go]
render.num.text = index
end
功能第二版:使用滑动列表
1、创建Scroll View组件,在content上添加对应脚本组件。上下滑动:添加VerticalLayoutGroup脚本;左右滑动:添加HorizontalLayoutGroup脚本
2.代码控制:
ui.content = base:findobj("list/Viewport/Content")
ui.ItemRenderer = Asset:LoadAsset(asseturi.getassetpath(base.module, "Item"))
--生成之前先全部清空再生成
Util.DestroyAllChild(ui.content)
for i=1,#data do
local go = utils.addchild(ui.content, ui.ItemRenderer)
local dataInfo = data[i]
utils.findtext(go,"num").text = i
end
到此为止,列表滑动已经实现,接下来就是事件的点击了
local function ClickChalleng()
-- TODO
--打开布阵界面
end
utils.addclickevent(go,ClickChalleng,i)
后面的功能流程就是:点击挑战,打开布阵界面,布阵完毕,挑战结算等。
排行榜
最后来介绍一下主界面的排行榜功能:
首先拼接ui层级如下:两个按钮对应两个界面。第一个界面为排行榜,第二个界面是对应排名的奖励预览。
最终呈现给用户的效果如下:
界面搭建完了,就开始我们的功能开发吧。
由于排行榜数据瞬息万变,我们不能一上游戏或者是进入该系统时获取排行榜数据,而是在需要显示的时候拿去,这样才能保证以最少的获取次数取到最新的数据。
因此,我们在该系统主界面点击排行榜时,向服务器请求数据,拿到数据我们再显示排行榜界面。
network.request("rankData")
if 返回成功 then
打开排行榜界面
end
打开排行榜时,除了需要传入排行榜数据,还需要传入一个下标index,标志着打开哪一个标签,传1则代表打开排行榜界面,传2代表打开奖励预览界面。
for k,v in ipairs(ui.tabs)do
SetActive(ui.pages[k],index == k)
SetActive(ui.pages[k],index == k)
end
接下来便是显示对应打开页签的数据了。注意,这里的列表,我是用的是前面介绍的循环列表,用法不再累叙
if index == 1 then
ui.rankRoot.DataCount = #base.data.rankList
ui.rankRoot:InvalidateData()
elseif index == 2 then
ui.rewardRoot.DataCount = utils.tablelen(base.data.rewardList)
ui.rewardRoot:InvalidateData()
end
以上是关于Unity实战之类爬塔功能的主要内容,如果未能解决你的问题,请参考以下文章