PGRData/Script/matrix/xui/xuispecialtrainbreakthrough/XSpecialTrainActionRandom.lua

154 lines
5.1 KiB
Lua
Raw Normal View History

---@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