Files
ft/Client/Assets/Scripts/GampPlay/ChallengeMatch/Road/ChallengeMatchSceneRoad.cs
2026-06-29 21:18:33 +08:00

397 lines
12 KiB
C#

//- 挑战赛- 公路
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<CinemachineVirtualCamera>();
_vCamInit = transform.Find("CameraRoot/CameraInit").GetComponent<CinemachineVirtualCamera>();
_thisEventManager = GContext.container.Resolve<FishingChallengeManager>();
_thisEventData = _thisEventManager.fishingChallengeData;
_curStep = _thisEventData.step;
_playableDirector = transform.Find("road_trucktimeline").GetComponent<PlayableDirector>();
_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<CinemachineBrain>();
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<ChallengeCleanStageEvent>().Subscribe(OnUpdateStage).AddTo(_disposables);
GContext.OnEvent<ChallengeBrokeStepEvent>().Subscribe(OnBrokeStep).AddTo(_disposables);
#if UNITY_EDITOR
GContext.OnEvent<ChallengeInitStepEvent>().Subscribe(OnGMInitStep).AddTo(_disposables);
#endif
GContext.OnEvent<ChallengeShowPlayerEvent>().Subscribe(OnShowPlayer).AddTo(_disposables);
GContext.OnEvent<ChallengeSetAnimationEvent>().Subscribe(OnChallengeTimeEvent).AddTo(_disposables);
GContext.OnEvent<ChallengeMatchPlayEvent>().Subscribe(e => { OnPlay(e.step); }).AddTo(_disposables);
GContext.OnEvent<ChallengeSceneEnterEvent>().Subscribe(e => { OnEnter(); }).AddTo(_disposables);
GContext.OnEvent<ExitMapEvent>().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($"<color=orange>{nameof(ChallengeMatchSceneRoad)} => {message} </color>");
}
private static void ELog(object message)
{
#if UNITY_EDITOR
Debug.Log($"<color=orange> {nameof(ChallengeMatchSceneRoad)} => {message} </color>");
#endif
}
#endregion
}
}