哈喽大家好!本篇文章是用时间戳做一个倒计时,效果如下(模糊点儿,大家半脑补食用吧!):
相信大家通过教学视频和一些项目,都已经了解过Lua里面的协程(coroutine),简单的等待触发是用wait()来控制一段时间后再继续执行的。下面是用协程的例子:
function TestFun() print("我是重小启") end Players.PlayerAdded:Connect(function(Uid) coroutine.start(function() print("角色生成了") wait(3) TestFun() end) end)
上面的Players里面有一个PlayerAdded事件,是角色生成的时候调用执行,整体逻辑就是在角色生成后输出“角色生成了”,3秒钟以后,执行TestFun方法,输出:我是重小启。
但是当程序中出现多个携程的时候,停止协程可能会导致程序错误。所以上面的计时器适用于时间较短,周期短的倒计时。那么我就引入了时间戳倒计时。
一、介绍时间戳
时间戳是什么呢?在写制作步骤之前,先简短介绍一下时间戳:百度给的定义是:“一个能表示一份数据在某个特定时间之前已经存在的、 完整的、 可验证的数据,通常是一个字符序列,唯一地标识某一刻的时间。”
那么时间戳是一个字符序列,下面我们一起探究时间戳!首先我打印一下时间戳:
Players.PlayerAdded:Connect(function(Uid) player = Players:GetPlayerByUserId(Uid) print(os.time()) --本地系统的时间戳 end)
下面是编辑器运行的结果:
没接触过时间戳的人会有疑问,(1560501534)这串数字是什么?代表了什么时间?其实我们可以通过百度搜索“时间戳在线转换工具”进行转换(打开转换工具——>输入时间戳——>得到具体时间日期)。
上面就是时间戳转换为具体时间的流程。1560501534 = 2019-06-14 16:38:54
如此一来,大家都明白了吧!但是每次都通过浏览器获得时间,那也太麻烦了!我告诉大家通过代码获取时间戳里面的日期:
Players.PlayerAdded:Connect(function(Uid) player = Players:GetPlayerByUserId(Uid) print("这是年: " .. os.date("%y",os.time()) .. "这是月: " .. os.date("%m",os.time()).. "这是日: " .. os.date("%d",os.time())) print("这是时: " .. os.date("%H",os.time()) .. "这是分: " .. os.date("%M",os.time()).. "这是秒: " .. os.date("%S",os.time())) end)
上面代码里,os.date()函数是时间戳转换日期方法,下面是运行结果:
将详细的日期打印了下来,那么知道了现在的时间戳如何获得明天的时间戳呢?想必大家已经知道了,就是通过将日期+1,得到的就是明天的时间戳。下面进行测试:
Players.PlayerAdded:Connect(function(Uid) player = Players:GetPlayerByUserId(Uid) print(os.date("%d",os.time())) local CurrentTimer = os.time({day=os.date("%d",os.time())+1, --日期+1操作 month=os.date("%m",os.time()), year=os.date("%Y",os.time()), hour=os.date("%H",os.time()), min=os.date("%M",os.time()), sec=os.date("%S",os.time())}); print(os.date("%d",CurrentTimer)) end)
下面是运行结果:
可以看到,两个日期相差一天。所以终于给倒计时提供了一个思路:用时间戳的差值得到相差的时间戳,再转换为具体时间。
好了时间戳介绍完了,下面是时间戳倒计时的具体步骤:
二、创建服务器脚本并定义变量
首先在服务器逻辑里面创建服务器脚本:
然后打开脚本,创建倒计时所需要的变量:
local workMin = 0 --分钟 local workSec = 0 --秒钟 local CurrentTimer = 0 --未来时间的倒计时 local TotalTime = 5 --CD总时间 local StartTimeCount = 0 --开始计时的时间戳 local Hero --角色 PlayerInfo = {} PlayerInfo.PlayerID = 0 --角色Id Players.PlayerAdded:Connect(function(Uid) PlayerInfo.PlayerID = Uid Hero = Players:GetPlayerByUserId(PlayerInfo.PlayerID) end)
三、编写倒计时逻辑
倒计时是需要实时去执行的,所以写在update里面,下面是代码:
GameRun.Update:Connect(function() --判断时间戳是否已经赋值 if StartTimeCount ~= 0 then --设置将来的时间 CurrentTimer = os.time({day=os.date("%d",StartTimeCount), month=os.date("%m",StartTimeCount), year=os.date("%Y",StartTimeCount), hour=os.date("%H",StartTimeCount), min=os.date("%M",StartTimeCount), sec=os.date("%S",StartTimeCount)+TotalTime}); local PeriordTimer = CurrentTimer - StartTimeCount workMin = os.date("%M",CurrentTimer - os.time()) workSec = os.date("%S",CurrentTimer - os.time()) --做差值,得到要倒计时的时间与现在时间戳的差 local alltime = PeriordTimer - ( os.time()-StartTimeCount) if alltime <= 0 then alltime = 0 a = 0 a = a+1 if a == 1 then PlayerInfo.MatchState = false PlayerInfo.HideState = true end if a == 2 then PlayerInfo.HideState = false PlayerInfo.StartGame = true end if a == 3 then PlayerInfo.StartGame = false end if a == 4 then print("----end----") end end --将时间戳格式化为时间格式 local second = tonumber(workSec) local mint = tonumber(workMin) local hour = math.floor(alltime / 60 /60); if alltime <= 0 then hour = 0; mint = 0; second = 0; end if mint < 10 then mint = '0'..mint end if hour < 10 then hour = '0'..hour end if second < 10 then second = '0'..second end --得到时间格式的倒计时(我们要显示的倒计时文字) local temptime = tostring(hour).. ":" ..tostring(mint).. ":" ..tostring(second) if PlayerInfo.MatchState then --发送消息给客户端进行显示 MessageEvent.FireClient(PlayerInfo.PlayerID,"Timer",temptime) end end end) --匹配设置开始时间 MessageEvent.ServerEventCallBack("StartMatch"):Connect(function() StartTimeCount = os.time() PlayerInfo.MatchState = true end)
上面的时间戳倒计时中 temptime就是一串字符:00:00:05 ,可以直接赋值到Text文本中。当然如果想让倒计时更加的精准,不受本地时间的影响就要获取到服务器的时间戳,这样就能保证客户端与服务器的计时是一致的。
四、创建客户端脚本,给UI赋值
我用到的UI是编辑器上给定的UI,下面是我的UI层级逻辑和客户端脚本创建位置:
UI的“具体时间”文本框就是我们要显示的倒计时文字,刚刚在服务器脚本已经得到倒计时的文字了,只要在客户端脚本中接收然后给文本复制就可以了,下面是代码:
local MoonPic = GameUI.时间显示.时间.月亮 local SunPic = GameUI.时间显示.时间.太阳 --匹配倒计时 MessageEvent.ClientEventCallBack("Timer"):Connect(function(time) GameUI.时间显示.IsVisable = true if tonumber(os.date("%H",os.time())) >= 17 then MoonPic.IsVisable = true SunPic.IsVisable = false else MoonPic.IsVisable = false SunPic.IsVisable = true end GameUI.时间显示.时间.时间文字.具体时间.Text = time GameUI.时间显示.时间.时间文字.文本控件.Text = "匹配倒计时" end)
所以,只要把temptime赋值给具体时间的文本控件即可。
五、设置开始倒计时的时间
我们是点击匹配按钮,开始倒计时,所以只要在点击按钮的时候,把StartTimeCount赋值为当前时间的时间戳即可,下面是匹配按钮UI层级和客户端脚本的代码:
local MatchBtn = GameUI.MatchingPanel.MatchBtn --点击匹配 MatchBtn.OnClick:Connect(function() --发送给服务器消息 MessageEvent.FireServer("StartMatch") MatchBtn.IsVisable = false GameUI.跳跃.IsVisable = false end)
大功告成,运行后显示结果如下:
上面的月亮图片是根据时间的小时来判断的,如果当前时间的小时>17,也就是晚于晚上5点,我就判断为晚上,显示月亮反之则显示太阳。“00:00:04”就是我们要得到的倒计时,很精准。
如果想重置计时时间可以把StartTimeCount重新赋值为os.time(),这样就能重新去CD了。改动CD时间的话就改动TotalTime。
本帖最后由 松烟入墨 于 2020-05-12 15:34 编辑
请登录后评论~