public void Update() { TimelineInfo timelineInfoToDestroy = null; if (mPlayingTimeline != null) { PlayableDirector playableDirector = mPlayingTimeline.PlayableDirector; if (playableDirector != null && playableDirector.isActiveAndEnabled) { //GameDebug.LogError("playableDirector.state: " + playableDirector.state.ToString() // + ", playableDirector.time: " + playableDirector.time // + ", playableDirector.duration: " + playableDirector.duration); if (playableDirector.state == PlayState.Paused) { if (playableDirector.time > 0f) // 暂停状态下,如果已经走了一段时间则算是播放结束 { timelineInfoToDestroy = mPlayingTimeline; } else // 否则需要恢复播放 { playableDirector.Resume(); } } else if (playableDirector.time >= playableDirector.duration) // 时间大于等于总时间,则算是播放结束 { timelineInfoToDestroy = mPlayingTimeline; } } } if (timelineInfoToDestroy != null) { StopImpl(timelineInfoToDestroy); // 播放缓存下来的动画 if (mCacheTimelineList.Count > 0) { TimelineInfo cacheTimelineInfo = mCacheTimelineList.Dequeue(); PlayImpl(cacheTimelineInfo); } else { if (mAllFinishCallbacks.Count > 0) { foreach (System.Action finishCallback in mAllFinishCallbacks) { if (finishCallback != null) { finishCallback(); } } mAllFinishCallbacks.Clear(); } } } }
/// <summary> /// 加载timeline prefab协程 /// </summary> /// <param name="id"></param> /// <param name="prefabPath"></param> /// <param name="finishCallback"></param> /// <param name="pos"></param> /// <param name="needCameraFollowInterpolationWhenFinished"></param> /// <param name="showLocalPlayer"></param> /// <returns></returns> IEnumerator LoadPrefabCoroutine(TimelineConfig config, System.Action finishCallback, AvatarProperty avatarProperty) { uint id = config.Id; string prefabPath = config.PrefabPath; Vector3 pos = config.Pos; Vector3 rotation = config.Rotation; bool needCameraFollowInterpolationWhenFinished = config.NeedCameraFollowInterpolationWhenFinished; bool showLocalPlayer = config.ShowLocalPlayer; bool noStopLocalPlayer = config.NoStopLocalPlayer; bool showUI = config.ShowUI; bool pauseMusic = config.PauseMusic; bool needGC = config.NeedGC; SGameEngine.PrefabResource pr = new SGameEngine.PrefabResource(); yield return(SGameEngine.ResourceLoader.Instance.StartCoroutine(SGameEngine.ResourceLoader.Instance.load_prefab(string.Format("Assets/Res{0}.prefab", prefabPath), pr))); // 延迟资源的加载,测试用 //yield return new WaitForSeconds(5f); // 恢复玩家操作 GameInput.Instance.EnableInput(true, true); GameObject obj = pr.obj_; if (obj == null) { if (finishCallback != null) { finishCallback(); } if (mLoadingTimelineIdList.Contains(id) == true) { mLoadingTimelineIdList.Remove(id); } GameDebug.LogError("Play timeline " + prefabPath + " error, can not load prefab!"); yield break; } PlayableDirector playableDirector = obj.GetComponent <PlayableDirector>(); if (playableDirector == null) { GameObject.DestroyImmediate(obj); if (finishCallback != null) { finishCallback(); } if (mLoadingTimelineIdList.Contains(id) == true) { mLoadingTimelineIdList.Remove(id); } GameDebug.LogError("Play timeline " + prefabPath + " error, can not find PlayableDirector component!"); yield break; } string relatedPrefabPath = config.RelatedPrefabPath; SGameEngine.PrefabResource relatedPrefabPr = null; if (string.IsNullOrEmpty(relatedPrefabPath) == false) { relatedPrefabPr = new SGameEngine.PrefabResource(); yield return(SGameEngine.ResourceLoader.Instance.StartCoroutine(SGameEngine.ResourceLoader.Instance.load_prefab(string.Format("Assets/Res{0}.prefab", relatedPrefabPath), relatedPrefabPr))); } obj.SetActive(false); obj.transform.position = pos; obj.transform.localScale = Vector3.one; obj.transform.localEulerAngles = rotation; TimelineInfo timelineInfo = new TimelineInfo(); playableDirector.time = 0; timelineInfo.Id = id; timelineInfo.PlayableDirector = playableDirector; timelineInfo.FinishCallback = finishCallback; timelineInfo.AvatarProperty = avatarProperty; timelineInfo.NeedCameraFollowInterpolationWhenFinished = needCameraFollowInterpolationWhenFinished; timelineInfo.ShowLocalPlayer = showLocalPlayer; timelineInfo.NoStopLocalPlayer = noStopLocalPlayer; timelineInfo.ShowUI = showUI; timelineInfo.PauseMusic = pauseMusic; timelineInfo.NeedGC = needGC; // 关联GameObject timelineInfo.RelatedGameObject = null; if (relatedPrefabPr != null) { if (relatedPrefabPr.obj_ != null) { timelineInfo.RelatedGameObject = relatedPrefabPr.obj_; timelineInfo.RelatedGameObject.SetActive(false); timelineInfo.RelatedGameObject.transform.position = config.RelatedPrefabPos; timelineInfo.RelatedGameObject.transform.localScale = Vector3.one; timelineInfo.RelatedGameObject.transform.localEulerAngles = Vector3.zero; } else { GameDebug.LogError("Play timeline " + id + " error, can not load related prefab " + relatedPrefabPath); } } // lua脚本 if (string.IsNullOrEmpty(config.BehaviorScript) == false) { if (LuaScriptMgr.Instance != null && LuaScriptMgr.Instance.IsLuaScriptExist(config.BehaviorScript)) { LuaMonoBehaviour com = obj.AddComponent <LuaMonoBehaviour>(); com.Init(config.BehaviorScript); } else { System.Type t = System.Type.GetType(config.BehaviorScript); if (t != null) { obj.AddComponent(t); } } } // 延迟资源的加载,测试用 //yield return new WaitForSeconds(10f); if (mPlayingTimeline != null) { mCacheTimelineList.Enqueue(timelineInfo); } else { PlayImpl(timelineInfo); } if (mLoadingTimelineIdList.Contains(id) == true) { mLoadingTimelineIdList.Remove(id); } //GameDebug.LogError("TimelineManager.LoadPrefabCoroutine: " + id); }
/// <summary> /// 开始播放剧情 /// </summary> /// <param name="timelineInfo"></param> void PlayImpl(TimelineInfo timelineInfo) { //GameDebug.LogError("TimelineManager.PlayImpl: " + timelineInfo.Id); mPlayingTimeline = timelineInfo; PlayableDirector playableDirector = timelineInfo.PlayableDirector; if (playableDirector == null) { if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } return; } if (playableDirector.playableAsset == null) { if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } GameDebug.LogError("Play timeline " + playableDirector.gameObject.name + " error, playable asset is null!"); mPlayingTimeline = null; GameObject.DestroyImmediate(playableDirector.gameObject); if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } return; } if (Game.Instance.MainCamera == null) { if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } GameDebug.LogError("Play timeline " + playableDirector.gameObject.name + " error, main camera is null!"); mPlayingTimeline = null; GameObject.DestroyImmediate(playableDirector.gameObject); if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } return; } Cinemachine.CinemachineBrain cinemachineBrain = Game.Instance.MainCamera.GetComponent <Cinemachine.CinemachineBrain>(); if (cinemachineBrain == null) { cinemachineBrain = Game.Instance.MainCamera.gameObject.AddComponent <Cinemachine.CinemachineBrain>(); } if (cinemachineBrain != null) { cinemachineBrain.enabled = true; } else { GameDebug.LogError("Play timeline " + playableDirector.gameObject.name + " error, can not find CinemachineBrain component in main camera!"); mPlayingTimeline = null; GameObject.DestroyImmediate(playableDirector.gameObject); if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } return; } // 隐藏所有角色 SetAllActorsVisible(false, timelineInfo.ShowLocalPlayer); // 野外场景中记住正在寻路的任务 if (SceneHelp.Instance.IsInWildInstance() == true) { Task navigatingTask = TaskManager.Instance.NavigatingTask; if (navigatingTask != null) { mNavigatingTaskIdBeforePlay = navigatingTask.Define.Id; } } Actor localPlayer = Game.Instance.GetLocalPlayer(); TimelineAsset asset = playableDirector.playableAsset as TimelineAsset; foreach (TrackAsset track in asset.GetOutputTracks()) { GroupTrack group = track.GetGroup(); if (group != null) { // 绑定主摄像机 if (group.name.StartsWith("Camera") == true) { Camera mainCamera = Game.Instance.MainCamera; if (mainCamera != null) { foreach (PlayableBinding output in track.outputs) { if (output.sourceObject != null) { playableDirector.SetGenericBinding(output.sourceObject, mainCamera.gameObject); } } } } if (group.name.StartsWith("Hero") == true) { if (localPlayer != null) { foreach (PlayableBinding output in track.outputs) { GameObject actorModel = null; if (output.sourceObject != null) { Object binding = playableDirector.GetGenericBinding(output.sourceObject); if (binding == null) { GameDebug.LogError("Player timeline " + timelineInfo.PlayableDirector.name + " error!!! " + output.sourceObject.name + " 's binding object is null!!!"); continue; } GameObject bindingObj = binding as GameObject; if (bindingObj != null) { bindingObj.SetActive(false); } // 根据职业显示主角的模型 if (bindingObj != null && bindingObj.name.StartsWith("Hero_") == true) { uint vocation = uint.Parse(bindingObj.name.Substring(5)); if (vocation == LocalPlayerManager.Instance.LocalActorAttribute.Vocation) { //playableDirector.SetGenericBinding(output.sourceObject, localPlayer.gameObject); CommonTool.SetActive(bindingObj, true); actorModel = bindingObj; } else { CommonTool.SetActive(bindingObj, false); } } } if (actorModel != null && changeSkin) { //changeSkin = false; if (timelineInfo.AvatarProperty != null) { ResourceLoader.Instance.StartCoroutine(AvatarUtils.ChangeModel(actorModel, timelineInfo.AvatarProperty)); } else { AvatarProperty avatarProperty; if (localPlayer.mAvatarCtrl != null && localPlayer.mAvatarCtrl.GetLatestAvatartProperty() != null) { avatarProperty = localPlayer.mAvatarCtrl.GetLatestAvatartProperty(); } else { avatarProperty = mPlayerLastSceneAvatarProperty; } ResourceLoader.Instance.StartCoroutine(AvatarUtils.ChangeModel(actorModel, avatarProperty)); } } } } } } // 音效是否静音 AudioTrack audioTrack = track as AudioTrack; if (audioTrack != null) { audioTrack.muted = GlobalSettings.Instance.SFXMute; } } if (Game.Instance.CameraControl != null) { Game.Instance.CameraControl.Target = null; } // 记住当前状态并暂停主角的自动战斗 mIsAutoFightingWhenPlaying = InstanceManager.Instance.IsAutoFighting; InstanceManager.Instance.IsAutoFighting = false; // 停止主角的寻路 if (timelineInfo.NoStopLocalPlayer == false) { TargetPathManager.Instance.StopPlayerAndReset(); } mCameraRotationBeforePlay = Game.Instance.MainCamera.transform.rotation; mCameraFOVBeforePlay = Game.Instance.MainCamera.fieldOfView; bool setUI = true; if (timelineInfo.ShowUI == true) { setUI = false; } GameInput.Instance.EnableInput(false, setUI); // 暂停CullManager的Update CullManager.Instance.IsEnabled = false; // 隐藏UI if (timelineInfo.ShowUI == false) { xc.ui.ugui.UIManager.Instance.CloseAllWindow(); } if (!GlobalSettings.Instance.MusicMute && timelineInfo.PauseMusic) { AudioManager.Instance.PauseMusic(true); } playableDirector.gameObject.SetActive(true); if (timelineInfo.RelatedGameObject != null) { timelineInfo.RelatedGameObject.SetActive(true); } playableDirector.Play(); ClientEventMgr.Instance.FireEvent((int)ClientEvent.CE_TIMELINE_START, new CEventBaseArgs(timelineInfo.Id)); }
/// <summary> /// 停止播放剧情 /// </summary> /// <param name="timelineInfo"></param> void StopImpl(TimelineInfo timelineInfo) { //GameDebug.LogError("TimelineManager.StopImpl: " + timelineInfo.Id); Actor localPlayer = Game.Instance.GetLocalPlayer(); if (localPlayer != null) { if (Game.Instance.CameraControl != null) { Game.Instance.CameraControl.Target = localPlayer.Trans; Game.Instance.CameraControl.NeedFollowInterpolation = timelineInfo.NeedCameraFollowInterpolationWhenFinished; } else { GameDebug.LogError("Stop timeline error, CameraControl is null!!!"); } } else { // 播放动画的时候有可能还没登录游戏,所以LocalPlayer有可能不存在,这里的报错屏蔽掉 //GameDebug.LogError("Stop timeline error, can not get local player!!!"); } if (Game.Instance.MainCamera != null) { Cinemachine.CinemachineBrain cinemachineBrain = Game.Instance.MainCamera.GetComponent <Cinemachine.CinemachineBrain>(); if (cinemachineBrain != null) { cinemachineBrain.enabled = false; } Game.Instance.MainCamera.transform.rotation = mCameraRotationBeforePlay; Game.Instance.MainCamera.fieldOfView = mCameraFOVBeforePlay; } else { GameDebug.LogError("Stop timeline error, can not get main camera!!!"); } if (timelineInfo.PlayableDirector != null) { timelineInfo.PlayableDirector.time = timelineInfo.PlayableDirector.duration; GameObject.DestroyImmediate(timelineInfo.PlayableDirector.gameObject); } else { GameDebug.LogError("Stop timeline error, PlayableDirector is null!!!"); } if (timelineInfo.RelatedGameObject != null) { GameObject.DestroyImmediate(timelineInfo.RelatedGameObject); } mPlayingTimeline = null; SetAllActorsVisible(true, timelineInfo.ShowLocalPlayer); // 恢复主角的自动战斗 if (InstanceManager.Instance.IsAutoFighting != mIsAutoFightingWhenPlaying) { InstanceManager.Instance.IsAutoFighting = mIsAutoFightingWhenPlaying; } mIsAutoFightingWhenPlaying = false; GameInput.Instance.EnableInput(true, true); // 恢复CullManager的Update CullManager.Instance.IsEnabled = true; // 显示UI if (timelineInfo.ShowUI == false) { xc.ui.ugui.UIManager.Instance.ShowAllWindow(); } // 恢复新手引导 //GuideManager.Instance.Resume(); // 恢复任务寻路 if (mNavigatingTaskIdBeforePlay > 0) { Task task = TaskManager.Instance.GetTask(mNavigatingTaskIdBeforePlay); if (task != null) { TaskHelper.TaskGuide(task); } mNavigatingTaskIdBeforePlay = 0; } // 恢复背景音乐 if (!GlobalSettings.Instance.MusicMute && timelineInfo.PauseMusic) { AudioManager.Instance.PauseMusic(false); } ClientEventMgr.Instance.FireEvent((int)ClientEvent.CE_TIMELINE_FINISH, new CEventBaseArgs(timelineInfo.Id)); if (timelineInfo.FinishCallback != null) { timelineInfo.FinishCallback(); } // 释放预加载的资源 SGameEngine.AssetResource ar = null; if (mPreloadedTimelineReses.TryGetValue(timelineInfo.Id, out ar) == true) { if (ar != null) { ar.destroy(); } mPreloadedTimelineReses.Remove(timelineInfo.Id); } // 如果有待播放的系统开放动画,则重新开放 if (SysConfigManager.Instance.IsWaiting() == true) { if (SceneHelp.Instance.IsInWildInstance()) { TargetPathManager.Instance.StopPlayerAndReset();//有系统开启停止寻路 ClientEventMgr.GetInstance().FireEvent((int)ClientEvent.CE_NEW_WAITING_SYS, new CEventBaseArgs()); } else { ClientEventMgr.GetInstance().PostEvent((int)ClientEvent.CE_NEW_WAITING_SYS, new CEventBaseArgs()); } } // 短时间内播放同一个模型的动画两次,第二个剧情会播放不出来,调用一下ResourceLoader的gc就好了,通过表格配置 if (timelineInfo.NeedGC == true) { ResourceLoader.Instance.gc(); } }