让数字滚动起来
上周我的策划又提了样需求,当玩家评分发生变动时,屏幕出现人物评分浮层UI,播放评分数字滚动动画。这类数字滚动需求非常常见,我就按一般思路,将startvalue与endvalue每隔一点时间做插值变化并显示,从而实现数字滚动的效果,这也是大部分app及游戏采取的实现,效果如下:
几行代码写完给策划看效果,策划说不是这样的效果,跟XX游戏做得不一样,得像lao虎机数字一样,有真实的数字滚动效果,好吧,此滚动非彼滚动,期望效果应该是下面这样,看起来更确实炫酷:
Unity中的样式:
代码实现
Module_Tql_Award_Reels = LuaBaseClass("Module_Tql_Award_Reels")
local Tweening = DG.Tweening
function Module_Tql_Award_Reels:ctor(gameObject,numberSize,numLength,aniTime,numSpName, grid, symbolLenth)
self.gameObject = gameObject;
self.transform = gameObject.transform;
self.grid = grid;
self.numberSize = numberSize;
self.aniTime = aniTime;
self.numLength = numLength;
self.symbolLenth = symbolLenth;
self.activeInHierarchyLenth = numLength;
self.rollerTable = {};
self.symbolTable = {};
for i = 1, self.numLength do
self.rollerTable[i] = ModuleTqlAwardRoller.new(self.transform:FindChild("numbers/rollerNum" .. i).gameObject,numberSize,aniTime,numSpName);
end
for i = 1, self.symbolLenth do
self.symbolTable[i] = self.grid.transform:FindChild("rollerSymbol" .. i).gameObject;
end
end
-----------------------------
function Module_Tql_Award_Reels:split(str)
local list = {};
local len = string.len(str);
str = string.reverse(str);
for i=1,len do
list[i]=string.sub(str,i,i);
end
return list;
end
function Module_Tql_Award_Reels:change(to,isTween)
if to == nil or to == "Null" then
for i = #(self.rollerTable), 1, -1 do
self.rollerTable[i]:StopTween();
end
return;
end
local splitstr = Module_Tql_Award_Reels:split(tostring(to));
local intsplitstr = 1;
local lensplitstr = #splitstr;
for i = #(self.rollerTable), 1, -1 do
if intsplitstr <= lensplitstr then
self.rollerTable[i].gameObject:SetActive(true);
self.rollerTable[i]:setNumber(splitstr[intsplitstr], isTween);
else
self.rollerTable[i]:setNumber("0", isTween);
self.rollerTable[i].gameObject:SetActive(false);
end
intsplitstr = intsplitstr+1;
end
if self:activeInHierarchy() ~= self.activeInHierarchyLenth then
self.activeInHierarchyLenth = self:activeInHierarchy();
self:number_format(to)
self.grid:Reposition();
end
end
function Module_Tql_Award_Reels:activeInHierarchy()
local num = 0;
for i = 1, #(self.rollerTable) do
if self.rollerTable[i].gameObject.activeInHierarchy then
num = num + 1;
end
end
return num;
end
function Module_Tql_Award_Reels:number_format(num)
local str1 = "";
local str = tostring(math.floor(num));
local strLen = string.len(str);
for i = 1, #(self.symbolTable) do
self.symbolTable[i].gameObject:SetActive(false);
end
local index = #(self.symbolTable);
for i=1,strLen do
str1 = string.char(string.byte(str,strLen+1 - i)) .. str1
if math.mod(i,3) == 0 then
--下一个数 还有
if strLen - i ~= 0 then
self.symbolTable[index].gameObject:SetActive(true);
index = index - 1;
end
end
end
return str1;
end
--单一位动画
ModuleTqlAwardRoller = LuaBaseClass("ModuleTqlAwardRoller")
function ModuleTqlAwardRoller:ctor(gameObject,numberSize,aniTime,numSpName)
self.gameObject = gameObject;
self.transform = gameObject.transform;
self.numTable = {};
self.numSpName=numSpName;
self.rollingDuration =aniTime; --数字每次滚动时长
self.currentrollingTime = aniTime;
self.numberSize =numberSize; --图片高
self.tweener = {}; --各位数字的缓动实例
self.isTweening = false;
self.curNumber = nil; --当前数字
self.toNumber = 0; --最终数字;
for i = 1, 3 do
self.numTable[i] = self.transform:FindChild("Symbol" .. i):GetComponent("UISprite");
end
self.currentnumTable = 2;
end
function ModuleTqlAwardRoller:setNumber(value, isTween)
self.toNumber = tonumber(value);
if self.curNumber == nil then
self.curNumber = self.toNumber;
isTween = false;
end
local numberLocal = self.toNumber-self.curNumber;
if self.toNumber < self.curNumber then
numberLocal = 10-self.curNumber+self.toNumber;
end
if numberLocal <= 0 then
numberLocal = 1;
end
self.currentrollingTime = self.rollingDuration/numberLocal
if isTween then
if not self.isTweening then
if self.toNumber ~= self.curNumber then
self:StartTween();
end
end
else
self:StopTween();
self.toNumber = tonumber(value);
self.curNumber = self.toNumber;
local abovenum = self:currentnumTableAbove();
local belownum = self:currentnumTableBelow();
self.numTable[abovenum].spriteName = self.numSpName..self:curNumberAdd();
self.numTable[abovenum].transform.localPosition = Vector3.New(0,self.numberSize,0);
self.numTable[self.currentnumTable].spriteName = self.numSpName .. self.curNumber;
self.numTable[self.currentnumTable].transform.localPosition = Vector3.New(0,0,0);
self.numTable[belownum].spriteName = self.numSpName..self:curNumberReduction();
self.numTable[belownum].transform.localPosition = Vector3.New(0,-self.numberSize,0);
end
end
function ModuleTqlAwardRoller:TweenOnComplete()
if self.toNumber ~= self.curNumber then
self:StartTween();
else
self.isTweening = false;
for i = 1, 3 do
self.tweener[i] = nil
end
end
end
function ModuleTqlAwardRoller:StartTween()
self.isTweening = true;
local abovenum = self:currentnumTableAbove();
local belownum = self:currentnumTableBelow();
self.numTable[belownum].transform.localPosition = Vector3.New(0,self.numberSize*2,0);
self:doTween(belownum,Vector3.New(0,self.numberSize,0))
self:doTween(self.currentnumTable,Vector3.New(0,-self.numberSize,0))
self:doTween(abovenum,Vector3.New(0,0,0))
self.tweener[abovenum]:OnStepComplete(Utils.ActionToTween(self.TweenOnComplete,self))
self.currentnumTable = abovenum
self.curNumber = self:curNumberAdd()
self.numTable[belownum].spriteName = self.numSpName..self:curNumberAdd();
end
function ModuleTqlAwardRoller:StopTween()
self.curNumber = nil
self.toNumber = nil
for i = 1, 3 do
self.numTable[i].spriteName = "";
if self.tweener[i] then
self.tweener[i]:Complete();
self.tweener[i] = nil
end
end
self.isTweening = false;
end
function ModuleTqlAwardRoller:doTween(tablenum,localPosition)
if self.tweener[tablenum] then
self.tweener[tablenum]:Complete();
self.tweener[tablenum] = nil
end
tween = self.numTable[tablenum].transform:DOLocalMove(localPosition, self.currentrollingTime, true);
tween:SetEase(DG.Tweening.Ease.Linear)
self.tweener[tablenum] = tween;
end
function ModuleTqlAwardRoller:curNumberAdd()
local temopnum = self.curNumber+1
if temopnum > 9 then
temopnum = 0;
end
return temopnum;
end
function ModuleTqlAwardRoller:curNumberReduction()
local temopnum = self.curNumber-1
if temopnum < 0 then
temopnum = 9;
end
return temopnum;
end
function ModuleTqlAwardRoller:currentnumTableAbove()
local temopnumTable = self.currentnumTable-1
if temopnumTable < 1 then
temopnumTable = 3;
end
return temopnumTable;
end
function ModuleTqlAwardRoller:currentnumTableBelow()
local temopnumTable = self.currentnumTable+1
if temopnumTable > 3 then
temopnumTable = 1;
end
return temopnumTable;
end
使用:
this.people_award_reels = this:InitModuleAwardReels(this.room_4.transform:FindChild("type2/room4_TQL/PeopleReelPanel").gameObject, 12, "room4_tql_add_", 3);
function this:InitModuleAwardReels(awardtrans, numLength, numSpName, symbolLenth)
local grid = awardtrans.transform:FindChild("numbers"):GetComponent("UIGrid");
local awardreels = Module_Tql_Award_Reels.new(awardtrans, 30, numLength, 0.7, numSpName, grid, symbolLenth);
return awardreels;
end
this.people_award_reels:change(100, true); --true是需要播放动画,false为不播放动画,直接到这个数据