Lua 针对于播放Animator 动画的工具

---@diagnostic disable: undefined-doc-name
---@class AnimatorUtil
AnimatorUtil = {}
local this = AnimatorUtil

---@param animator CS.UnityEngine.Animator
---@param name string
function AnimatorUtil.Play(animator, name)
    if IsNull(animator) or IsNull(animator.gameObject) then
        return
    end
    animator.enabled = true --如果有些对象组件没有 开关没有打开 强制打开
    animator:Play(name, -1, 0)
end

---@param animator UnityEngine.Animator
---@param name string
---@param onComplete fun():void
-- ---@param enable boolean  动画结束后 animator 组件是否启用 有的不启用 因为需要代码会对对象有操作 有的需要启用 在播放动画的过程中切换其他动画
function AnimatorUtil.PlayOnce(animator, name, onComplete, enable)
    if IsNull(animator) or IsNull(animator.gameObject) then
        if onComplete then
            onComplete()
        end
        return
    end
    enable = enable or false;
    animator.enabled = false
    coroutine.start(
        function()
            animator.gameObject:SetActive(true)
            animator.enabled = true
            this.Play(animator, name)
            animator:Update(0); --强制切换状态
            if onComplete then
                --    coroutine.waitforframes(1)
                ---@type UnityEngine.AnimatorStateInfo
                while true do
                    --播放动画时候 如果对象销毁 会引起报错 然后执行回调 但如果有些需求不能满足 比如 只要动画播放完成才执行
                    if IsNull(animator) or IsNull(animator.gameObject) then
                        if onComplete then
                            onComplete()
                        end
                        return
                    end
                    local state = animator:GetCurrentAnimatorStateInfo(0)
                    if not state:IsName(name) or state.normalizedTime >= 1 then
                        ---解决 播放结束后 接触动画对对象的控制
                        animator.enabled = enable;

                        if onComplete then
                            onComplete()
                        end
                        break
                    end
                    coroutine.waitforframes(1)
                end
            end
        end
    )
end

---@param animator UnityEngine.Animator
---@param name string
---@param onComplete fun():void
---@param isMask
function AnimatorUtil.PlayOnceOld(animator, name, onComplete)
    -- if name == "ItemFlyAnimation" then
    --     Logger.LogWarning("0--------------------")
    -- end
    if IsNull(animator) or IsNull(animator.gameObject) then
        if onComplete then
            onComplete()
        end
        return
    end
    animator.enabled = false

    coroutine.start(
        function()
            -- if name == "ItemFlyAnimation" then
            --     Logger.LogWarning("2--------------------")
            -- end
            animator.enabled = true
            this.Play(animator, name)
            ---@type CS.UnityEngine.AnimatorStateInfo
            local state = nil
            local waitTime = 0
            while true do
                if IsNull(animator) or IsNull(animator.gameObject) then
                    if onComplete then
                        onComplete()
                    end
                    -- if name == "ItemFlyAnimation" then
                    --     Logger.LogWarning("3--------------------------")
                    -- end
                    return
                end
                state = animator:GetCurrentAnimatorStateInfo(0)
                if not state:IsName(name) then
                    waitTime = Time.deltaTime
                    coroutine.waitforseconds(0.01)
                else
                    -- if name == "ItemFlyAnimation" then
                    --     Logger.LogWarning("4--------------------------")
                    -- end
                    break
                end
            end
            local playTime = state.length - waitTime
            if playTime > 0 then
                -- if name == "ItemFlyAnimation" then
                --     Logger.LogWarning("5--------------------------" .. playTime)
                -- end
                coroutine.waitforseconds(playTime)
            end
            -- coroutine.waitforseconds(playTime)
            if not IsNull(animator) then
                animator.enabled = false
                -- if name == "ItemFlyAnimation" then
                --     Logger.LogWarning("6--------------------------")
                -- end
                if onComplete then
                    onComplete()
                end
            end
        end
    )
end

----旧版
function AnimatorUtil.PlayOnceByState(animator, name, onComplete)
    if IsNull(animator) or IsNull(animator.gameObject) then
        if onComplete then
            onComplete()
        end
        return
    end
    animator.enabled = false
    coroutine.start(
        function()
            animator.gameObject:SetActive(true)
            animator.enabled = true
            this.Play(animator, name)
            if onComplete then
                coroutine.waitforframes(1)
                ---@type UnityEngine.AnimatorStateInfo

                while true do
                    if IsNull(animator) or IsNull(animator.gameObject) then
                        if onComplete then
                            onComplete()
                        end
                        return
                    end
                    local state = animator:GetCurrentAnimatorStateInfo(0)
                    if not state:IsName(name) or state.normalizedTime >= 1 then
                        if onComplete then
                            onComplete()
                        end
                        break
                    end
                    coroutine.waitforframes(1)
                end
            end
        end
    )
end

--根据时间回调(播放动画然后在动画的播放多长时间后 执行事件)
function AnimatorUtil.PlayTimes(animator, name, onComplete, playTime)
    animator.enabled = false
    coroutine.start(
        function()
            animator.enabled = true
            this.Play(animator, name)
            coroutine.waitforseconds(playTime)
            if not IsNull(animator) then
                animator.enabled = false
                DoCallbackSafe(onComplete)
            end
        end
    )
end

---------------------------------------------------------------timeline------------------------------------------------------------------

local curPlayableDirector

---停止timeLine播放
function AnimatorUtil.StopTimeLine()
    if not IsNull(curPlayableDirector) then
        curPlayableDirector:Stop()
    end
end

---@param fromTrans CS.UnityEngine.Transform
---@param fromPt Vector3
---@param targetTrans CS.UnityEngine.Transform
---@return Vector3
--toip :没有调用也不应该出现再这里
function AnimatorUtil.TranslatePoint(fromTrans, fromPt, targetTrans)
    local gpt = fromTrans:TransformPoint(fromPt)
    return targetTrans:InverseTransformPoint(gpt)
end

---设置timeline里的音效  是不是可以和 PlayTimeLine 结合使用
function AnimatorUtil.SetAudioTrackMuted(playableDirector)
    if not IsNull(playableDirector) then
        local timelineAsset = playableDirector.playableAsset
        if timelineAsset then
            local rootTracks = timelineAsset:GetRootTracks()
            if RunManager:GetInstance():GetPrefsInt(GameEnum.SoundStateKey, GameEnum.CorrectTypeEnum.Yes) ~= GameEnum.CorrectTypeEnum.Yes then
                for i = 0, timelineAsset.rootTrackCount - 1 do
                    if GameUtility.CheckAudioTrack then
                        --tip:多余 判断是否 为 timeline音效轨道
                        --Logger.LogSafe("GameUtility.ISAudioTrackType")
                        if GameUtility.ISAudioTrackType(rootTracks[i]) then
                            rootTracks[i].muted = true
                        else
                            rootTracks[i].muted = false
                        end
                    end
                end
            else
                for i = 0, timelineAsset.rootTrackCount - 1 do
                    rootTracks[i].muted = false
                end
            end
        end
    end
end

---合并
function AnimatorUtil.PlayTimeLine(playableDirector, completeCallBack, speed)
    playableDirector:Play()
    if speed and speed > 0 then
        --摄像机震动频率
        GameUtility.SetTimeLineSpeed(playableDirector, speed)
        local ShakeeCameraList = playableDirector.transform:GetComponentsInChildren(typeof(CS.ShakeCameraControl), true)
        local ShakeList = ListToTable(ShakeeCameraList)
        if ShakeList then
            for _, ShakeeCamera in ipairs(ShakeList) do
                ShakeeCamera:SetShakeTime(speed)
            end
        end
    end
    if completeCallBack then
        local callback
        callback = function()
            playableDirector:stopped("-", callback)
            completeCallBack()
        end
        playableDirector:stopped("+", callback)
    end
    curPlayableDirector = playableDirector
end

-----------------------------------------Spine 动画---------------------------------------------------------------------
---Spine 动画
function AnimatorUtil.PlaySkeletonGraphic(skeletonGraphic, animationName, completeCallBack, loop)
    assert(loop == nil or type(loop) == "boolean")
    skeletonGraphic:ResetAnimationPose()
    local animationState = skeletonGraphic.AnimationState
    animationState:ClearTrack(0)
    if string.IsNilOrEmpty(animationName) then
        animationName = skeletonGraphic.startingAnimation --使用默认的动画
    end
    if loop == nil then
        loop = skeletonGraphic.startingLoop
    end
    skeletonGraphic:PlaySpineAnimation(animationName, loop)
    if completeCallBack then
        animationState:ClearListenerNotifications()
        local callback
        callback = function()
            animationState:Complete("-", callback)
            completeCallBack()
        end
        animationState:Complete("+", callback)
    end
end

function AnimatorUtil.PlaySkeletonGraphicNoReset(skeletonGraphic, animationName, completeCallBack, loop)
    assert(loop == nil or type(loop) == "boolean")
    local animationState = skeletonGraphic.AnimationState
    animationState:ClearTrack(0)
    if string.IsNilOrEmpty(animationName) then
        animationName = skeletonGraphic.startingAnimation --使用默认的动画
    end
    if loop == nil then
        loop = skeletonGraphic.startingLoop
    end
    animationState:SetAnimation(0, animationName, loop)
    if completeCallBack then
        animationState:ClearListenerNotifications()
        local callback
        callback = function()
            animationState:Complete("-", callback)
            completeCallBack()
        end
        animationState:Complete("+", callback)
    end
end

---添加事件 tip: 没调用
function AnimatorUtil.PlayEventSkeletonGraphic(skeletonGraphic, animationName, loop, Event, completeCallBack)
    assert(loop == nil or type(loop) == "boolean")
    skeletonGraphic:ResetAnimationPose()
    local animationState = skeletonGraphic.AnimationState
    animationState:ClearTrack(0)
    if string.IsNilOrEmpty(animationName) then
        animationName = skeletonGraphic.startingAnimation --使用默认的动画
    end
    if loop == nil then
        loop = skeletonGraphic.startingLoop
    end
    skeletonGraphic:PlaySpineAnimation(animationName, loop)
    local eventCallback
    if Event then
        animationState:ClearListenerNotifications()
        eventCallback = function(trackIndex, e)
            DoCallbackSafe(Event, trackIndex, e)
        end
        animationState:Event("+", eventCallback)
    end
    if completeCallBack then
        animationState:ClearListenerNotifications()
        local callback
        callback = function()
            if eventCallback then
                animationState:Event("-", eventCallback)
            end
            animationState:Complete("-", callback)
            completeCallBack()
        end
        animationState:Complete("+", callback)
    end
end

function AnimatorUtil.PlaySkeletonAnimation(skeletonAnimation, animationName, completeCallBack)
    skeletonAnimation:ResetAnimationPose()
    local animationState = skeletonAnimation.AnimationState
    animationState:ClearTrack(0)
    if string.IsNilOrEmpty(animationName) then
        animationName = skeletonAnimation.startingAnimation --使用默认的动画
    end
    animationState:SetAnimation(0, animationName, skeletonAnimation.loop)
    if completeCallBack then
        animationState:ClearListenerNotifications()
        local callback = nil
        callback = function()
            completeCallBack()
            animationState:Complete("-", callback)
        end
        animationState:Complete("+", callback)
    end
end

--- 针对播放攻击 Spine 动画 慢镜的接口
--- 注意速度更改后为永久性的 所有spine 结束后 要恢复
--- InvokeTime 为 设置速度的节点
---
function AnimatorUtil.PlaySkeletonSpeedAnimation(skeletonAnimation, animationName, InvokeTime, Speed, completeCallBack)
    skeletonAnimation:ResetAnimationPose()
    local animationState = skeletonAnimation.AnimationState
    animationState:ClearTrack(0)
    if string.IsNilOrEmpty(animationName) then
        animationName = skeletonAnimation.startingAnimation --使用默认的动画
    end

    animationState:SetAnimation(0, animationName, skeletonAnimation.loop)
    DelayInvoke(InvokeTime, function()
        if skeletonAnimation then
            animationState.timeScale = Speed
        end
    end)
    if completeCallBack then
        animationState:ClearListenerNotifications()
        local callback = nil
        callback = function()
            animationState.timeScale = 1
            completeCallBack()
            animationState:Complete("-", callback)
        end
        animationState:Complete("+", callback)
    end
end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
luac转lua工具是用于将Lua源代码从编译过的二进制格式(.luac文件)转换为可读的文本格式(.lua文件)的工具。通常,在编写Lua代码时,我们使用文本编辑器来编写和修改代码。但有时,为了加密和保护代码的安全性,我们需要将代码编译为.luac文件,这样代码将以二进制形式存储,并且只能被luavm解释执行。然而,这种编译的代码不易于阅读和修改。 使用luac转lua工具,我们可以将.luac文件转换为易读的.lua文件。这对于理解、修改和维护代码非常有用。此工具解析.luac文件,并将其反编译为文本形式,使开发人员能够查看代码的实际内容和结构。一旦转换完成,我们就可以使用任何文本编辑器来修改代码,并将其保存为.lua文件。 通常,使用此工具的主要步骤如下: 1. 下载并安装luac转lua工具到你的计算机上。 2. 打开工具,选择要转换的.luac文件。 3. 设置目标文件名和保存位置。 4. 点击转换按钮,等待工具完成转换过程。 5. 一旦转换完成,你就可以使用任何文本编辑器打开保存的.lua文件并进行修改。 需要注意的是,由于.luac文件是编译的二进制文件,转换后的.lua文件可能不会与原始的.lua文件完全相同。某些元信息,如行号和注释,可能会丢失。此外,由于代码的解释执行也可能有所不同,因此在修改代码之前,你应该先进行适当的测试和验证。 总而言之,luac转lua工具是帮助开发人员将编译的.luac文件转换为可读的.lua源代码文件的实用工具,以方便代码的理解、修改和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值