2023-07-14 19:35:33 +00:00
|
|
|
|
---@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
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
---@param animator UnityEngine.Animator
|
|
|
|
|
---@param actionArray string[]|nil 当状态机配置好Parameters时可不传, By zlb
|
2023-07-14 19:35:33 +00:00
|
|
|
|
function XSpecialTrainActionRandom:SetAnimator(animator, actionArray, panelRoleModel)
|
|
|
|
|
self._Animator = animator
|
2024-09-01 20:49:41 +00:00
|
|
|
|
local actionArrayFromParam = self:_GetActionArrayByParam(animator)
|
|
|
|
|
if #actionArrayFromParam > 0 then
|
|
|
|
|
self._ActionArray = actionArrayFromParam
|
|
|
|
|
else
|
|
|
|
|
self._ActionArray = actionArray
|
|
|
|
|
end
|
2023-07-14 19:35:33 +00:00
|
|
|
|
self._PanelRoleModel = panelRoleModel
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function XSpecialTrainActionRandom:Play()
|
2024-09-01 20:49:41 +00:00
|
|
|
|
self:_RandomIdleDuration()
|
|
|
|
|
self:_PlayRandomAnimation()
|
|
|
|
|
self._IdleActionName = self:_GetRunningActionName(self._Animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
-- 第一次播放,间隔总是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
|
|
|
|
|
|
|
|
|
|
-- 策划做了状态机,里面放了要使用的多组动作
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_PlayRandomAnimation()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
if self._AnimatorTimer then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
local animator = self._Animator
|
|
|
|
|
self._AnimatorTimer = XScheduleManager.ScheduleForever(function()
|
2024-09-01 20:49:41 +00:00
|
|
|
|
if not animator or XTool.UObjIsNil(animator) then
|
|
|
|
|
self:Stop()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local currentName, animatorClipInfo = self:_GetRunningActionName(animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
if currentName == self._IdleActionName then
|
|
|
|
|
self._IdleTime = self._IdleTime + CS.UnityEngine.Time.deltaTime
|
|
|
|
|
if self._IdleTime > self._TimeToPlayAction then
|
|
|
|
|
-- 融合时间内有事件冲突
|
2024-09-01 20:49:41 +00:00
|
|
|
|
if not self:_IsAnimatorEventConflict(animator, animatorClipInfo) or
|
2023-07-14 19:35:33 +00:00
|
|
|
|
-- 冲突时间过久,强制播放
|
|
|
|
|
(self._IdleTime > self._TimeToPlayAction + self._CrossFadeConflictProtectTime) then
|
|
|
|
|
self._IdleTime = 0
|
2024-09-01 20:49:41 +00:00
|
|
|
|
self:_PlayNextAction()
|
|
|
|
|
self:_RandomIdleDuration()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end, 0)
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_PlayNextAction()
|
|
|
|
|
local nextActionName = self:_GetNextAction()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
if not nextActionName then
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
if self._PanelRoleModel then
|
|
|
|
|
self._PanelRoleModel:CrossFadeAnim(nextActionName, self._CrossFadeTime)
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetNextAction()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
local length = #self._ActionArray
|
|
|
|
|
if length == 1 then
|
|
|
|
|
return self._ActionArray[1]
|
|
|
|
|
end
|
|
|
|
|
if length == 0 then
|
|
|
|
|
return false
|
|
|
|
|
end
|
2024-09-01 20:49:41 +00:00
|
|
|
|
self._LastIndex = self:_GetDifferentIndex()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
return self._ActionArray[self._LastIndex]
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetDifferentIndex()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
local index = math.random(1, #self._ActionArray)
|
|
|
|
|
if index == self._LastIndex then
|
2024-09-01 20:49:41 +00:00
|
|
|
|
return self:_GetDifferentIndex()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
end
|
|
|
|
|
return index
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetRunningActionName(animator)
|
|
|
|
|
local animatorClipInfo, name = self:_GetRunningActionClipInfo(animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
return name, animatorClipInfo
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- 由于使用了crossFade,融合时会同时触发两个动作的事件,导致之前动作的表情,覆盖了之后动作的表情
|
|
|
|
|
-- 检查动画事件是否在两个动作融合时间内触发
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_IsAnimatorEventConflict(animator, animatorClipInfo)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
if not animatorClipInfo then
|
|
|
|
|
return false
|
|
|
|
|
end
|
2024-09-01 20:49:41 +00:00
|
|
|
|
local passedActionTime = self:_GetPassedActionTime(animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
-- 当前动作已播放时间
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetPassedActionTime(animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
local layer = 0
|
|
|
|
|
local stateInfo = animator:GetCurrentAnimatorStateInfo(layer)
|
|
|
|
|
return stateInfo.normalizedTime * stateInfo.length
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_RandomIdleDuration()
|
2023-07-14 19:35:33 +00:00
|
|
|
|
self._TimeToPlayAction = math.random(30, 50) / 10
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetRunningActionClipInfo(animator)
|
2023-07-14 19:35:33 +00:00
|
|
|
|
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
|
|
|
|
|
|
2024-09-01 20:49:41 +00:00
|
|
|
|
function XSpecialTrainActionRandom:_GetActionArrayByParam(animator)
|
|
|
|
|
local actionArray = {}
|
|
|
|
|
local parameters = animator.parameters
|
|
|
|
|
for i = 0, parameters.Length - 1 do
|
|
|
|
|
local param = parameters[i]
|
|
|
|
|
local name = param.name
|
|
|
|
|
actionArray[#actionArray + 1] = name
|
|
|
|
|
end
|
|
|
|
|
return actionArray
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-14 19:35:33 +00:00
|
|
|
|
return XSpecialTrainActionRandom
|