153 lines
5.1 KiB
Lua
153 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
|