local XMoeWarAnimationRole = XClass(nil, "XMoeWarAnimationRole") local Vector3 = CS.UnityEngine.Vector3 local VForward = Vector3.forward local CSXResourceManagerLoad = CS.XResourceManager.Load local PLAY_END_ANIM_DISTANCE = CS.XGame.ClientConfig:GetFloat("MoeWarSceneAnimationPlayEndAnimDistance")--当镜头跟随者到达此位置后播放结束镜头动画和慢镜头动作 local PLAY_GOAL_ANIM_DISTANCE = CS.XGame.ClientConfig:GetFloat("MoeWarSceneAnimationGoalDistance")--当镜头跟随者到达此位置后播放冲线特效 local PLAY_RESTORE_ANIM_DISTANCE = CS.XGame.ClientConfig:GetFloat("MoeWarSceneAnimationRestoreDistance")--当镜头跟随者到达此位置后恢复慢镜头动作 local SLOW_DOWN_PERCENT = 0.01 * CS.XGame.ClientConfig:GetInt("MoeWarSceneAnimationSlowdownPercent")--慢动作速度百分比 local END_ANIM_TOTAL_TIME = CS.XGame.ClientConfig:GetInt("MoeWarSceneAnimationTotalTime")--整个终场动画持续时间/s local ADD_SUPPORT_DISTANCE_POS = CS.XGame.ClientConfig:GetFloat("MoeWarSceneAnimationAddSupportDistance")--增加投票数间隔,数值越大,间隔时间越长,增加的投票数越多 local SynPlaySlowDownAnim = nil--同步播放慢动作 local SynPlayRestoreAnim = nil--同步恢复原始速度 function XMoeWarAnimationRole:Ctor(data) self.Index = data.Index--赛道Index self.GroupId = data.GroupId--动画组Id self.ModelParent = data.Parent--角色模型父节点 self.UiName = data.UiName self.Scene = data.Scene self.SwitchCameraCb = data.SwitchCameraCb--切换相机回调 self.EndAnimCb = data.EndAnimCb--终场场景动画回调 self.GoalAnimCb = data.GoalAnimCb--冲线场景动画回调 self.Ui = data.Ui --ui节点 self.PlayerId = data.PlayerId --角色Id self.RunwayIndex = data.RunwayIndex --场景的跑道下标 self.Match = data.Match --XMoeWarMatch self:Init() end function XMoeWarAnimationRole:Dispose() self:DestroyTimer() for _, effectRoot in pairs(self.SceneEffectRoots) do effectRoot.gameObject:SetActiveEx(false) end self.SceneEffectRoots = {} self:ReleaseResource() end function XMoeWarAnimationRole:ReleaseResource() if self.Resource then self.Resource:Release() self.Resource = nil end if self.Model then XUiHelper.Destroy(self.Model) self.Model = nil end end function XMoeWarAnimationRole:Init() local groupId = self.GroupId local player = XDataCenter.MoeWarManager.GetPlayer(self.PlayerId) local matchId = self.Match and self.Match:GetId() or XDataCenter.MoeWarManager.GetCurMatchId() self.AnimationIds = XMoeWarConfig.GetAnimationIds(groupId)--动画节点组 self.CurrentAnimationIndex = 0--当前播放动画Index self.CurrentModelName = nil--当前加载角色模型名称 self.Model = nil--当前加载角色模型 self.Animator = nil--动画控制器 self.FollowCameras = {}--跟随相机 self.SceneEffectRoots = {}--已加载场景特效根节点 self._IsEnd = nil--全部动画节点是否播放完毕 self._IsFocus = nil--是否是相机跟随者 self.PlaySlowDownAnim = nil--播放慢动作 self.PlayRestoreAnim = nil--恢复原始速度 self.TotalSupportCount = player and player:GetSupportCount(matchId) or 0 --拥有的总投票数 self.TotalDistance = XMoeWarConfig.GetAnimationTotalDistance(groupId) --总距离 self.OnceAddSupportCount = self.TotalSupportCount / self.TotalDistance * (ADD_SUPPORT_DISTANCE_POS + 0.5) --每次增加的投票数 self.CurSupportCount = 0 --当前票数 SynPlaySlowDownAnim = nil SynPlayRestoreAnim = nil self:InitUi() local modelName = XMoeWarConfig.GetAnimationGroupInitModelName(groupId) self:ChangeModel(modelName) if player then self.Head:SetRawImage(player:GetCircleHead()) end self.RImgIcon:SetRawImage(CS.XGame.ClientConfig:GetString("MoeWarScheduleSupportIcon")) self.TxtScore.text = self.CurSupportCount self.TxtAddScore.text = "" end function XMoeWarAnimationRole:InitUi() local rootUiTransform = self.Ui.transform self.Head = XUiHelper.TryGetComponent(rootUiTransform, "Head1/StandIcon", "RawImage") self.TxtScore = XUiHelper.TryGetComponent(rootUiTransform, "PanelRolePoll/TxtScore", "Text") self.RImgIcon = XUiHelper.TryGetComponent(rootUiTransform, "PanelRolePoll/RImgIcon", "RawImage") self.TxtAddScore = XUiHelper.TryGetComponent(rootUiTransform, "TxtAddScore", "Text") self.TxtAddScoreEnable = XUiHelper.TryGetComponent(rootUiTransform, "Animation/TxtAddScoreEnable", "PlayableDirector") end --替换模型 function XMoeWarAnimationRole:ChangeModel(modelName) if not modelName or modelName == self.CurrentModelName then return end --记录旧模型位置 local oldPos = self.Model and self.Model.transform.localPosition --加载新模型 local prefabPath = XModelManager.GetUiModelPath(modelName) local resource = CSXResourceManagerLoad(prefabPath) if resource == nil or not resource.Asset then XLog.Error(string.format("XMoeWarAnimationRole:ChangeModel加载资源失败,路径:%s", prefabPath)) return end self:ReleaseResource() self.Resource = resource local model = XUiHelper.Instantiate(resource.Asset, self.ModelParent) model.gameObject:SetLayerRecursively(CS.UnityEngine.LayerMask.NameToLayer("UiNear")) self.Model = model if oldPos then self.Model.transform.localPosition = oldPos end --加载controller local controllerPath = XModelManager.GetUiControllerPath(modelName) local runtimeController = CS.LoadHelper.LoadUiController(controllerPath, self.UiName) self.Animator = model.transform:GetComponent("Animator") self.Animator.runtimeAnimatorController = runtimeController --播放初始动画 local initAnim = XMoeWarConfig.GetAnimationGroupInitAnim(self.GroupId) if not string.IsNilOrEmpty(initAnim) then self.Animator:Play(initAnim) end --切换模型时换一个相机跟随保证平滑,否则会延迟回拉 if self.CurrentModelName and modelName ~= self.CurrentModelName then self.SwitchCameraCb(self.Index) end self.CurrentModelName = modelName end --设置跟随虚拟相机 function XMoeWarAnimationRole:SetFollowCamera(virtualCamera) if self.FollowCameras[virtualCamera] then return end self._IsFocus = true self.FollowCameras = {} self.FollowCameras[virtualCamera] = virtualCamera self:UpdateFollowCameras() end function XMoeWarAnimationRole:UpdateFollowCameras() for virtualCamera in pairs(self.FollowCameras) do virtualCamera.Follow = self.Model.transform end end --执行动画节点 function XMoeWarAnimationRole:Run() local animationIndex = self.CurrentAnimationIndex + 1 local animationId = self.AnimationIds[animationIndex] local isLastAnimation = animationIndex >= #self.AnimationIds - 1 --最后一个动画到达终点,-1来判断是否为终点前的最后一个动画 if not XTool.IsNumberValid(animationId) then self:OnExit() return end self.CurrentAnimationIndex = animationIndex self._IsEnd = false --替换动画模型 local modelName = XMoeWarConfig.GetAnimationModelName(animationId) self:ChangeModel(modelName) --角色动作 local animName = XMoeWarConfig.GetAnimationAnimName(animationId) self.Animator:Play(animName) --角色特效 local roleEffect, roleEffectRoot = XMoeWarConfig.GetAnimationRoleEffect(animationId) if not string.IsNilOrEmpty(roleEffect) and not string.IsNilOrEmpty(roleEffectRoot) then local effectRoot = self.Model.transform:FindTransform(roleEffectRoot) if XTool.UObjIsNil(effectRoot) then XLog.Error(string.format("XMoeWarAnimationRole:Run error: 角色特效父节点找不到, roleEffectRoot: %s;animationId: %s", roleEffectRoot, animationId)) else effectRoot:LoadPrefab(roleEffect, false) effectRoot.gameObject:SetActiveEx(false) effectRoot.gameObject:SetActiveEx(true) end end --场景特效 local sceneEffect, sceneEffectRoot = XMoeWarConfig.GetAnimationSceneEffect(animationId, self.RunwayIndex) if not string.IsNilOrEmpty(sceneEffect) and not string.IsNilOrEmpty(sceneEffectRoot) then local effectRoot = self.SceneEffectRoots[sceneEffectRoot] if not effectRoot then effectRoot = self.Scene:FindTransform(sceneEffectRoot) self.SceneEffectRoots[sceneEffectRoot] = effectRoot end if XTool.UObjIsNil(effectRoot) then XLog.Error("XMoeWarAnimationRole:Run error: 场景特效父节点找不到, sceneEffectRoot: " .. sceneEffectRoot) else effectRoot.gameObject:SetLayerRecursively(CS.UnityEngine.LayerMask.NameToLayer("UiNear")) effectRoot:LoadPrefab(sceneEffect, false) effectRoot.gameObject:SetActiveEx(false) effectRoot.gameObject:SetActiveEx(true) end end --速度 local speed = XMoeWarConfig.GetAnimationSpeed(animationId) --目标点 local distance = XMoeWarConfig.GetAnimationDistance(animationId) local transform = self.Model.transform local start = transform.localPosition.z local target = start + distance --触发动画 local playEndAnim = nil local playGoalAnim = nil --终点前加满至拥有的投票数 if isLastAnimation then self:AddScore(self.TotalSupportCount) end --角色移动 local position = nil local curPosition = nil self:DestroyTimer() self.Timer = XScheduleManager.ScheduleForever(function() if XTool.UObjIsNil(transform) then self:DestroyTimer() return end position = transform.localPosition.z --增加当前的投票数 if not isLastAnimation then if not curPosition then curPosition = position elseif math.abs(curPosition - position) >= ADD_SUPPORT_DISTANCE_POS then curPosition = position self.CurSupportCount = math.min(self.TotalSupportCount, self.CurSupportCount + self.OnceAddSupportCount) self:AddScore(self.CurSupportCount) end end --到达目标位置后执行下一动画节点 if position >= target then self:DestroyTimer() self:Run() return end --终场镜头动画 if self._IsFocus and position >= PLAY_END_ANIM_DISTANCE then if not playEndAnim then playEndAnim = true --播放场景动画 self.EndAnimCb(END_ANIM_TOTAL_TIME) end if not SynPlaySlowDownAnim then SynPlaySlowDownAnim = true end end --慢动作 if SynPlaySlowDownAnim and not self.PlaySlowDownAnim then self.PlaySlowDownAnim = true speed = speed * SLOW_DOWN_PERCENT self.Animator.speed = self.Animator.speed * SLOW_DOWN_PERCENT end --冲线动画 if not playGoalAnim and self._IsFocus and position >= PLAY_GOAL_ANIM_DISTANCE then playGoalAnim = true --播放冲线特效 self.GoalAnimCb() end --恢复原始速度 if self._IsFocus and not SynPlayRestoreAnim and position >= PLAY_RESTORE_ANIM_DISTANCE then SynPlayRestoreAnim = true end if SynPlayRestoreAnim and not self.PlayRestoreAnim then self.PlayRestoreAnim = true speed = speed / SLOW_DOWN_PERCENT self.Animator.speed = self.Animator.speed / SLOW_DOWN_PERCENT end --角色移动 transform:Translate(speed * VForward * CS.UnityEngine.Time.deltaTime) end, 0, 0) end --增加积分动画 function XMoeWarAnimationRole:AddScore(newSupportCount) local oldSupportCount = tonumber(self.TxtScore.text) if oldSupportCount == newSupportCount or newSupportCount - oldSupportCount < 1 then return end local curShowSupportCount = self.TxtScore.text self.TxtScore.text = math.min(self.TotalSupportCount, math.floor(newSupportCount)) self.TxtAddScore.text = "+" .. math.floor(newSupportCount - oldSupportCount) self.TxtAddScoreEnable:Stop() self.TxtAddScoreEnable:Play() end --动画全部执行完毕 function XMoeWarAnimationRole:OnExit() self._IsEnd = true self:DestroyTimer() end function XMoeWarAnimationRole:DestroyTimer() if self.Timer then XScheduleManager.UnSchedule(self.Timer) self.Timer = nil end end function XMoeWarAnimationRole:IsEnd() return self._IsEnd or false end return XMoeWarAnimationRole