//- 挑战赛- 公路 using System; using System.Threading.Tasks; using asap.core; using Cinemachine; using GampPlay.ChallengeMatch.Road; using UniRx; using UnityEditor; using UnityEngine; using UnityEngine.Playables; //Event namespace GampPlay.ChallengeMatch { public class ChallengeMatchSceneRoad : MonoBehaviour { [SerializeField] private ChallengeRegionRoad[] nodeContainer; // [Header("当前每阶段时长")] [SerializeField] private float[] stepTimes; [Header("公式周期参数")] [SerializeField] private float durationArg = 0.2f; [Header("相机位移等待延时")] [SerializeField] private float durationForLocation = 0.25f; [Header("退出延时参数")] [SerializeField] private float exitDelayArg = 0.2f; private Transform _camera; private CinemachineVirtualCamera _vCam; // - 初始化相机 private CinemachineVirtualCamera _vCamInit; private Transform _roadTruck; private PlayableDirector _playableDirector; //- 管理 private FishingChallengeManager _thisEventManager; //- 数据 private FishingChallengeData _thisEventData; //- 当前阶段 private int _curStep; private double _targetTime; private bool _isPlaying; private CompositeDisposable _disposables = new(); //- 当前的时间 // private readonly float _stepTime = 1f; // private Transform _truck; private void Awake() { //- var targetFrameRate = Application.targetFrameRate; Log($"targetFrameRate {targetFrameRate}"); Log($"Time.timeScale: {Time.timeScale}"); Log($"Time.fixedDeltaTime: {Time.fixedDeltaTime}"); _camera = transform.Find("CameraRoot/Camera"); // _vCam = _camera.GetComponent(); _vCamInit = transform.Find("CameraRoot/CameraInit").GetComponent(); _thisEventManager = GContext.container.Resolve(); _thisEventData = _thisEventManager.fishingChallengeData; _curStep = _thisEventData.step; _playableDirector = transform.Find("road_trucktimeline").GetComponent(); _roadTruck = transform.Find("road_truck"); // InitCamera(); //- 添加事件 OnAddEvents(); } private async void Start() { ELog("Start-> "); _playableDirector.played += OnTimelinePlayed; _playableDirector.paused += OnTimelinePaused; _playableDirector.stopped += OnTimelineStopped; InitCurStep(); await Awaiters.Seconds(0.2f); GContext.Publish(new EventSceneLoadComplete()); ELog("Start-> End"); } private void InitCamera() { _vCamInit.gameObject.SetActive(true); } private void OnEnable() { _isPlaying = false; } private void OnDisable() { if (_vCam) { if (Camera.main) { var brain = Camera.main.GetComponent(); brain?.ManualUpdate(); } } } private void OnDestroy() { _disposables?.Dispose(); _disposables = null; } private void Update() { #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.N)) { // _curStep = (_curStep + 1) % (_thisEventManager.GetFullStep() + 1); // InitCurStep(); } if (Input.GetKeyDown(KeyCode.V)) { var e = new ChallengeCleanStageEvent { stage = 1, }; OnUpdateStage(e); } #endif if (_isPlaying) { if (_playableDirector.time >= _targetTime) { _playableDirector.Pause(); } } } #if UNITY_EDITOR private void OnGMInitStep(ChallengeInitStepEvent evt) { _curStep = evt.step; InitCurStep(); } #endif #region Game Logic private void InitCurStep() { Log($"InitCurStep -> _curStep = {_curStep}"); UpdateCurEnv(_curStep); // LocationCarStep(_curStep); //-> } private async void UpdateCurCamera() { GContext.Publish(new EventUpdateCamera()); // if (_curStep < 4) { await LocationCamera(); } // await Awaiters.Seconds(0.2f); GContext.Publish(new EventUpdateCameraComplete()); } private async Task LocationCamera() { ELog("LocationCamera-> "); await Awaiters.Seconds(durationForLocation); await SwitchToFollow(); ELog("LocationCamera-> Finished"); //- 5, 2.26,- 50; } private async Task SwitchToFollow() { _vCam.transform.position = _vCamInit.transform.position; _vCam.transform.rotation = _vCamInit.transform.rotation; // 提高优先级触发 Blend _vCam.Priority = 15; _vCamInit.gameObject.SetActive(false); var deltaY = Math.Abs(_vCamInit.transform.position.y - _roadTruck.position.y); ELog($"SwitchToFollow deltaY -> {deltaY} {durationArg * deltaY}"); await Awaiters.Seconds(durationArg * deltaY); // 禁用旧的 _vCam.Priority = 5; } // -等待退出 private async Task SwitchToExit() { await Awaiters.NextFrame; _vCamInit.gameObject.SetActive(true); var deltaY = Math.Abs(_vCamInit.transform.position.y - _roadTruck.position.y); await Awaiters.Seconds(durationArg * deltaY + exitDelayArg); ELog($"SwitchToExit deltaY -> {deltaY}"); } private void UpdateCurEnv(int step) { ELog($"UpdateCurEnv -> {step}"); var curIndex = step - 1; var maxNum = nodeContainer.Length; for (var i = curIndex + 1; i < maxNum; ++i) { _ = nodeContainer[i].UpdateState(CBoxState.Locked); } if (step > maxNum) return; if (step == 0) { nodeContainer[0].Prepare(); return; } for (var i = 0; i <= curIndex; ++i) { _ = nodeContainer[i].UpdateState(CBoxState.Broken); } _ = nodeContainer[curIndex].UpdateState(CBoxState.UnLocked); } private void LocationCarStep(int step) { ELog($"LocationCarStep -> {step}"); // var stepTime = stepTimes[step]; var stepTime = GetStepTime(step); _playableDirector.time = stepTime; // _playableDirector.time = step * _stepTime; _playableDirector.Evaluate(); } private float GetStepTime(int step) { var stepTime = 0f; for (var i = 0; i < step; ++i) { stepTime += stepTimes[i]; } ELog($"{step}: stepTime -> {stepTime} {_playableDirector.duration} {Math.Min(stepTime, (float)_playableDirector.duration)}"); return Math.Min(stepTime, (float)_playableDirector.duration); } //- private void OnPlay(int step) { ELog($"OnPlay -> {step} {_targetTime}"); _playableDirector.Play(); _targetTime = GetStepTime(step); // _targetTime = step * _stepTime; } private void OnEnter() { ELog("OnEnter-> "); UpdateCurCamera(); ELog("OnEnter-> Finished"); } // private async void OnLeave() // { // await SwitchToFollow(); // } private void OnAddEvents() { GContext.OnEvent().Subscribe(OnUpdateStage).AddTo(_disposables); GContext.OnEvent().Subscribe(OnBrokeStep).AddTo(_disposables); #if UNITY_EDITOR GContext.OnEvent().Subscribe(OnGMInitStep).AddTo(_disposables); #endif GContext.OnEvent().Subscribe(OnShowPlayer).AddTo(_disposables); GContext.OnEvent().Subscribe(OnChallengeTimeEvent).AddTo(_disposables); GContext.OnEvent().Subscribe(e => { OnPlay(e.step); }).AddTo(_disposables); GContext.OnEvent().Subscribe(e => { OnEnter(); }).AddTo(_disposables); GContext.OnEvent().Subscribe(OnExitMap).AddTo(_disposables); } private async void OnExitMap(ExitMapEvent e) { ELog("OnExitMap"); await SwitchToExit(); e.Tcs.TrySetResult(true); } private void OnChallengeTimeEvent(ChallengeSetAnimationEvent e) { foreach (var box in nodeContainer) { box.UpdateTimeController(e); } } private async void OnUpdateStage(ChallengeCleanStageEvent upStepEvent) { ELog("OnUpdateStage"); var stageIndex = upStepEvent.stage - 1; if (stageIndex >= 0) { await nodeContainer[stageIndex].UpdateState(CBoxState.UnLocking); } upStepEvent.Tcs.SetResult(true); } private async void OnBrokeStep(ChallengeBrokeStepEvent brokeEvent) { ELog($"OnBrokeStep -> {brokeEvent.step}"); var step = brokeEvent.step - 1; if (step >= 0 && step < nodeContainer.Length) { await nodeContainer[step].UpdateState(CBoxState.Attacking); await Awaiters.Seconds(brokeEvent.dealyTime); } brokeEvent.Tcs.SetResult(true); } public void OnShowPlayer(ChallengeShowPlayerEvent evt) { LocationCarStep(evt.oldStep); } #endregion #region TimeLine void OnTimelinePlayed(PlayableDirector director) { _isPlaying = true; } void OnTimelinePaused(PlayableDirector director) { _isPlaying = false; } void OnTimelineStopped(PlayableDirector director) { _isPlaying = false; } #endregion #region Log private static void Log(object message) { Debug.Log($"{nameof(ChallengeMatchSceneRoad)} => {message} "); } private static void ELog(object message) { #if UNITY_EDITOR Debug.Log($" {nameof(ChallengeMatchSceneRoad)} => {message} "); #endif } #endregion } }