154 lines
5.1 KiB
Lua
154 lines
5.1 KiB
Lua
|
---@class XSpecialTrainActionRandom
|
|||
|
local XSpecialTrainActionRandom = XClass(nil, "XSpecialTrainActionRandom")
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:Ctor()
|
|||
|
self._Animator = false
|
|||
|
self._ActionArray = false
|
|||
|
self._RandomActionArray = false
|
|||
|
self._PanelRoleModel = false
|
|||
|
self._LastIndex = false
|
|||
|
self._AnimatorTimer = false
|
|||
|
self._IdleTime = 0
|
|||
|
self._IdleActionName = false
|
|||
|
-- 随机播放动作的间隔
|
|||
|
self._TimeToPlayAction = 0
|
|||
|
self._CrossFadeTime = 0.2
|
|||
|
self._CrossFadeConflictProtectTime = 1
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:SetAnimator(animator, actionArray, panelRoleModel)
|
|||
|
self._Animator = animator
|
|||
|
self._ActionArray = actionArray
|
|||
|
self._PanelRoleModel = panelRoleModel
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:Play()
|
|||
|
self:RandomIdleDuration()
|
|||
|
self:PlayRandomAnimation()
|
|||
|
self._IdleActionName = self:GetRunningActionName(self._Animator)
|
|||
|
-- 第一次播放,间隔总是1秒
|
|||
|
self._IdleTime = self._TimeToPlayAction - 1
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:Stop()
|
|||
|
if self._AnimatorTimer then
|
|||
|
XScheduleManager.UnSchedule(self._AnimatorTimer)
|
|||
|
end
|
|||
|
self._Animator = false
|
|||
|
self._ActionArray = false
|
|||
|
self._RandomActionArray = false
|
|||
|
self._PanelRoleModel = false
|
|||
|
self._LastIndex = false
|
|||
|
self._AnimatorTimer = false
|
|||
|
self._IdleTime = 0
|
|||
|
self._IdleActionName = false
|
|||
|
self._TimeToPlayAction = 0
|
|||
|
end
|
|||
|
|
|||
|
-- 策划做了状态机,里面放了要使用的多组动作
|
|||
|
function XSpecialTrainActionRandom:PlayRandomAnimation()
|
|||
|
if self._AnimatorTimer then
|
|||
|
return
|
|||
|
end
|
|||
|
local animator = self._Animator
|
|||
|
self._AnimatorTimer = XScheduleManager.ScheduleForever(function()
|
|||
|
local currentName, animatorClipInfo = self:GetRunningActionName(animator)
|
|||
|
if currentName == self._IdleActionName then
|
|||
|
self._IdleTime = self._IdleTime + CS.UnityEngine.Time.deltaTime
|
|||
|
if self._IdleTime > self._TimeToPlayAction then
|
|||
|
-- 融合时间内有事件冲突
|
|||
|
if not self:IsAnimatorEventConflict(animator, animatorClipInfo) or
|
|||
|
-- 冲突时间过久,强制播放
|
|||
|
(self._IdleTime > self._TimeToPlayAction + self._CrossFadeConflictProtectTime) then
|
|||
|
self._IdleTime = 0
|
|||
|
self:PlayNextAction()
|
|||
|
self:RandomIdleDuration()
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end, 0)
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:PlayNextAction()
|
|||
|
local nextActionName = self:GetNextAction()
|
|||
|
if not nextActionName then
|
|||
|
return false
|
|||
|
end
|
|||
|
if self._PanelRoleModel then
|
|||
|
self._PanelRoleModel:CrossFadeAnim(nextActionName, self._CrossFadeTime)
|
|||
|
end
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:GetNextAction()
|
|||
|
local length = #self._ActionArray
|
|||
|
if length == 1 then
|
|||
|
return self._ActionArray[1]
|
|||
|
end
|
|||
|
if length == 0 then
|
|||
|
return false
|
|||
|
end
|
|||
|
self._LastIndex = self:GetDifferentIndex()
|
|||
|
return self._ActionArray[self._LastIndex]
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:GetDifferentIndex()
|
|||
|
local index = math.random(1, #self._ActionArray)
|
|||
|
if index == self._LastIndex then
|
|||
|
return self:GetDifferentIndex()
|
|||
|
end
|
|||
|
return index
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:GetRunningActionName(animator)
|
|||
|
local animatorClipInfo, name = self:GetRunningActionClipInfo(animator)
|
|||
|
return name, animatorClipInfo
|
|||
|
end
|
|||
|
|
|||
|
-- 由于使用了crossFade,融合时会同时触发两个动作的事件,导致之前动作的表情,覆盖了之后动作的表情
|
|||
|
-- 检查动画事件是否在两个动作融合时间内触发
|
|||
|
function XSpecialTrainActionRandom:IsAnimatorEventConflict(animator, animatorClipInfo)
|
|||
|
if not animatorClipInfo then
|
|||
|
return false
|
|||
|
end
|
|||
|
local passedActionTime = self:GetPassedActionTime(animator)
|
|||
|
for i = 0, animatorClipInfo.clip.events.Length - 1 do
|
|||
|
local animationEvent = animatorClipInfo.clip.events[i]
|
|||
|
local animationEventTime = animationEvent.time
|
|||
|
if passedActionTime + self._CrossFadeTime > animationEventTime and passedActionTime < animationEventTime then
|
|||
|
return true
|
|||
|
end
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- 当前动作已播放时间
|
|||
|
function XSpecialTrainActionRandom:GetPassedActionTime(animator)
|
|||
|
local layer = 0
|
|||
|
local stateInfo = animator:GetCurrentAnimatorStateInfo(layer)
|
|||
|
return stateInfo.normalizedTime * stateInfo.length
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:RandomIdleDuration()
|
|||
|
self._TimeToPlayAction = math.random(30, 50) / 10
|
|||
|
end
|
|||
|
|
|||
|
function XSpecialTrainActionRandom:GetRunningActionClipInfo(animator)
|
|||
|
local layer = 0
|
|||
|
local stateInfo = animator:GetCurrentAnimatorStateInfo(layer)
|
|||
|
local animatorClipInfos = animator:GetCurrentAnimatorClipInfo(layer)
|
|||
|
if animatorClipInfos.Length <= 0 then
|
|||
|
return nil
|
|||
|
end
|
|||
|
for i = 0, animatorClipInfos.Length - 1 do
|
|||
|
local animatorClipInfo = animatorClipInfos[i]
|
|||
|
local name = animatorClipInfo.clip.name
|
|||
|
if CS.UnityEngine.Animator.StringToHash(name) == stateInfo.shortNameHash then
|
|||
|
return animatorClipInfo, name
|
|||
|
end
|
|||
|
end
|
|||
|
return nil
|
|||
|
end
|
|||
|
|
|||
|
return XSpecialTrainActionRandom
|