水果机,夺宝动画实现
效果(动画不流畅是gif帧率低造成的)

入口代码
Assets/FruitMachine/FruitMachineDemo.cs
这个脚本挂在Layer节点上
public class FruitMachineDemo : MonoBehaviour { private LuaEnv m_LuaEnv; private RectTransform m_Layer; private List<Action> m_Actions = new List<Action>(); void Awake() { m_Layer = (RectTransform)transform; } void Start() { m_LuaEnv = new LuaEnv(); m_LuaEnv.AddLoader((ref string filePath) => { filePath = filePath.Replace('.', '/'); var assetFilePath = $"Assets/{filePath}.lua.txt"; #if UNITY_EDITOR filePath = Path.GetFullPath(assetFilePath); #endif var txtAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetFilePath); return Encoding.UTF8.GetBytes(txtAsset.text); }); m_LuaEnv.Global.Set("FruitMachineDemoInst", this); //在lua中增加一个全局变量,可以在lua中用FruitMachineDemoInst来访问c#对象 m_LuaEnv.DoString("require('FruitMachine.Main')"); } void OnDestroy() { m_Actions.Clear(); m_Actions = null; if (null != m_LuaEnv) { m_LuaEnv.Dispose(); m_LuaEnv = null; } } public RectTransform GetLayerRoot() { return m_Layer; } public void AddAction(Action action) { if (null != action) m_Actions.Add(action); } public void RemoveAction(Action action) { if (null != action) m_Actions.Remove(action); } void Update() { if (m_Actions.Count > 0) { foreach (var act in m_Actions) { act(); } } } }
Assets/FruitMachine/Main.lua.txt
require("Lua.LuaCoMgr") local Type_Button = typeof(CS.UnityEngine.UI.Button) ---@type FruitMachineAnim local m_FruitMachineAnim = require("FruitMachine.FruitMachineAnim").new() -- ////////// local Inner = {} local m_RootTrans = FruitMachineDemoInst:GetLayerRoot() local m_ItemUIs = {} local m_CurItemIndex = 1 local m_BlinkCoId = 0 -- ////////// m_RootTrans:Find("btn_Start"):GetComponent(Type_Button).onClick:AddListener(function() if 0 == m_BlinkCoId then m_FruitMachineAnim:StartForResult(5) end end) for i=1,8 do local itemTrans = m_RootTrans:Find("item_"..i) m_ItemUIs[i] = { selFrame = itemTrans:Find("selFrame").gameObject, } end m_FruitMachineAnim:Prepare(8, function(flag, sender) local oldItemIndex = m_CurItemIndex m_CurItemIndex = m_FruitMachineAnim:GetCurIndex() m_ItemUIs[oldItemIndex].selFrame:SetActive(false) m_ItemUIs[m_CurItemIndex].selFrame:SetActive(true) if "ItemChange" == flag then elseif "ShowResult" == flag then m_BlinkCoId = LuaCoMgr.Start(function() for i=1,3 do LuaCoMgr.WaitForSeconds(0.1) m_ItemUIs[m_CurItemIndex].selFrame:SetActive(false) LuaCoMgr.WaitForSeconds(0.1) m_ItemUIs[m_CurItemIndex].selFrame:SetActive(true) end LuaCoMgr.WaitForSeconds(1) m_BlinkCoId = 0 m_FruitMachineAnim:StartForIdle() end) end end) m_FruitMachineAnim:StartForIdle() function Inner.Update() LuaCoMgr.OnUpdate() m_FruitMachineAnim:OnUpdate() end FruitMachineDemoInst:AddAction(Inner.Update)
LuaCoMgr看这边:xlua - lua协程模拟Unity协程
动画代码
Assets/FruitMachine/FruitMachineAnim.lua.txt
local _Time = CS.UnityEngine.Time ---@class FruitMachineAnim local FruitMachineAnim = {} FruitMachineAnim.__index = FruitMachineAnim local Inner = {} function FruitMachineAnim.new() local obj = {} setmetatable(obj, FruitMachineAnim) obj:ctor() return obj end function FruitMachineAnim:ctor() self.m_RunningFlag = 0 end function FruitMachineAnim:GetCurIndex() return self.m_CurIndex end function FruitMachineAnim:Prepare(cnt, cb) if 0 ~= self.m_RunningFlag then --要在运行前调用 return end self.m_Cnt = cnt self.m_Callback = cb self.m_ElapseTime = 0 self.m_CurIndex = 0 end function FruitMachineAnim:StartForIdle() if 0 ~= self.m_RunningFlag then --播放动画中 return end self.m_RunningFlag = 1 self.m_ResultIndex = -1 self.m_ItemChangeInterval = 0.7 end function FruitMachineAnim:StartForResult(resultIndex) if 2 == self.m_RunningFlag then --播放抽奖动画中 return end self.m_RunningFlag = 2 self.m_ResultIndex = resultIndex self.m_ShowResultFlag = false LuaCoMgr.Start(Inner.DoSpeedUpAndDown, self) end function FruitMachineAnim:StopForIdle() if 2 == self.m_RunningFlag then --播放抽奖动画中, 不能强制停止 return end self.m_RunningFlag = 0 end function FruitMachineAnim:IsPlayIdle() return 1 == self.m_RunningFlag end function FruitMachineAnim:IsPlayResult() return 2 == self.m_RunningFlag end ---@param self FruitMachineAnim function Inner.DoSpeedUpAndDown(self) self.m_ItemChangeInterval = 0.7 -- ///// 加速 local initInterval = 0.7 --初始切换间隔 local speedUpInterval = 0.03 --加速到最快时的切换间隔 local speedUpCnt = 10 -- 加速次数 local speedUpTotalTime = 0.5 --加速总共用时 local speedUpStep = (initInterval - speedUpInterval) / speedUpCnt local speedUpPerTime = speedUpTotalTime / speedUpCnt for i=1,speedUpCnt do LuaCoMgr.WaitForSeconds(speedUpPerTime) self.m_ItemChangeInterval = self.m_ItemChangeInterval - speedUpStep end local speedUpDur = 2 --达到最快后持续时长 LuaCoMgr.WaitForSeconds(speedUpDur) -- ///// -- ///// 减速 local speedDownInterval = 0.2 --减速到最慢时的切换间隔 local speedDownCnt = 10 --减速次数 local speedDownTotalTime = 2 --减速总共用时 local speedDownStep = (speedDownInterval - speedUpInterval) / speedDownCnt local speedDownPerTime = speedDownTotalTime / speedDownCnt for i=1,speedDownCnt do LuaCoMgr.WaitForSeconds(speedDownPerTime) self.m_ItemChangeInterval = self.m_ItemChangeInterval + speedDownStep end local speedDownDur = 0.5 LuaCoMgr.WaitForSeconds(speedDownDur) -- ///// self.m_ShowResultFlag = true end function FruitMachineAnim:OnUpdate() if 0 == self.m_RunningFlag then return end self.m_ElapseTime = self.m_ElapseTime + _Time.unscaledDeltaTime if self.m_ElapseTime >= self.m_ItemChangeInterval then self.m_ElapseTime = self.m_ElapseTime - self.m_ItemChangeInterval self.m_CurIndex = self.m_CurIndex + 1 if self.m_CurIndex > self.m_Cnt then self.m_CurIndex = 1 end if self.m_ShowResultFlag then --结果出来了 if self.m_CurIndex == self.m_ResultIndex then self.m_RunningFlag = 0 self.m_ShowResultFlag = false if self.m_Callback then self.m_Callback("ShowResult", self) end else if self.m_Callback then self.m_Callback("ItemChange", self) end end else --结果还没出来 if self.m_Callback then self.m_Callback("ItemChange", self) end end end end return FruitMachineAnim

浙公网安备 33010602011771号