using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RewindManager : MonoBehaviour { [Header("Îá'ºêòè ñöåíè")] public GameObject david; public GameObject drone; public ParticleSystem wave1PS; public ParticleSystem wave2PS; [Header("UI")] public Slider rewindSlider; private bool _recording = false; private bool _rewinding = false; private bool _animating = false; private Vector3 _davidStartPos; private Vector3 _droneStartPos; private Vector3 _davidFinalPos; private Vector3 _droneFinalPos; private HeroMovement _heroMovement; private DroneMovement _droneMovement; private Animator _davidAnimator; private int _stopFrameIndex = -1; private struct FrameState { public float wave1Time; public float wave2Time; public bool wave1Active; public bool wave2Active; public int animStateHash; public float animNormalizedTime; } private List _frames = new List(); void Awake() { if (david != null) { _davidStartPos = david.transform.position; _heroMovement = david.GetComponentInChildren(); _davidAnimator = david.GetComponent(); } if (drone != null) { _droneStartPos = drone.transform.position; _droneMovement = drone.GetComponentInChildren(); } if (rewindSlider != null) { rewindSlider.gameObject.SetActive(false); rewindSlider.onValueChanged.AddListener(OnSliderChanged); } _recording = true; } public void ShowSlider() { _recording = false; _stopFrameIndex = _frames.Count - 1; if (david != null) _davidFinalPos = david.transform.position; if (drone != null) _droneFinalPos = drone.transform.position; if (rewindSlider != null) { rewindSlider.maxValue = _frames.Count - 1; rewindSlider.onValueChanged.RemoveListener(OnSliderChanged); rewindSlider.value = _frames.Count - 1; rewindSlider.onValueChanged.AddListener(OnSliderChanged); rewindSlider.gameObject.SetActive(true); } } void Update() { if (!_recording || _rewinding) return; FrameState frame = new FrameState(); frame.wave1Active = wave1PS != null && wave1PS.gameObject.activeSelf; frame.wave2Active = wave2PS != null && wave2PS.gameObject.activeSelf; frame.wave1Time = frame.wave1Active ? wave1PS.time : 0f; frame.wave2Time = frame.wave2Active ? wave2PS.time : 0f; if (_davidAnimator != null && david != null && david.activeInHierarchy) { AnimatorStateInfo info = _davidAnimator.GetCurrentAnimatorStateInfo(0); frame.animStateHash = info.fullPathHash; frame.animNormalizedTime = info.normalizedTime; } _frames.Add(frame); } void OnSliderChanged(float value) { if (_animating) return; if (_frames.Count == 0) return; _rewinding = true; Time.timeScale = 0f; int index = Mathf.RoundToInt(value); index = Mathf.Clamp(index, 0, _frames.Count - 1); float t = _frames.Count > 1 ? (float)index / (_frames.Count - 1) : 1f; if (david != null) david.transform.position = Vector3.Lerp(_davidStartPos, _davidFinalPos, t); if (drone != null) drone.transform.position = Vector3.Lerp(_droneStartPos, _droneFinalPos, t); FrameState frame = _frames[index]; if (_davidAnimator != null && frame.animStateHash != 0 && david != null && david.activeInHierarchy) { _davidAnimator.Play(frame.animStateHash, 0, frame.animNormalizedTime); _davidAnimator.Update(0f); } if (wave1PS != null && frame.wave1Active) { wave1PS.gameObject.SetActive(true); wave1PS.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); wave1PS.Simulate(frame.wave1Time, true, true); } if (wave2PS != null && frame.wave2Active) { wave2PS.gameObject.SetActive(true); wave2PS.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); wave2PS.Simulate(frame.wave2Time, true, true); } } public void OnSliderReleased(float savedValue) { if (_animating) return; _animating = true; _rewinding = false; Time.timeScale = 1f; int index = Mathf.RoundToInt(savedValue); index = Mathf.Clamp(index, 0, _frames.Count - 1); float animateTo = rewindSlider.maxValue; if (_stopFrameIndex >= 0 && index < _stopFrameIndex) { GameManager.Instance?.GenerateSimV(); if (_heroMovement != null) _heroMovement.ResumeMoving(); if (_droneMovement != null) _droneMovement.ResumeMoving(); FindObjectOfType()?.Reset(); FindObjectOfType()?.Reset(); FindObjectOfType()?.HideRestart(); _stopFrameIndex = -1; if (_davidAnimator != null && david != null && david.activeInHierarchy) { _davidAnimator.Rebind(); _davidAnimator.Play("FastRun", 0, 0f); _davidAnimator.Update(0f); } } if (wave1PS != null && !_frames[index].wave1Active) { wave1PS.Stop(); wave1PS.gameObject.SetActive(false); wave1PS.GetComponent()?.ResetText(); } if (wave2PS != null && !_frames[index].wave2Active) { wave2PS.Stop(); wave2PS.gameObject.SetActive(false); wave2PS.GetComponent()?.ResetText(); } if (wave1PS != null && wave1PS.gameObject.activeSelf) wave1PS.Play(); if (wave2PS != null && wave2PS.gameObject.activeSelf) wave2PS.Play(); StartCoroutine(AnimateSlider(savedValue, animateTo)); } public void FullReset() { StopAllCoroutines(); Time.timeScale = 1f; _frames.Clear(); _stopFrameIndex = -1; _rewinding = false; _animating = false; _recording = true; if (rewindSlider != null) { rewindSlider.gameObject.SetActive(false); rewindSlider.onValueChanged.RemoveListener(OnSliderChanged); rewindSlider.value = 0f; rewindSlider.onValueChanged.AddListener(OnSliderChanged); } } private IEnumerator AnimateSlider(float from, float to) { rewindSlider.onValueChanged.RemoveListener(OnSliderChanged); rewindSlider.maxValue = to; float current = from; while (current < to) { current += 60f * Time.unscaledDeltaTime; current = Mathf.Min(current, to); rewindSlider.value = current; yield return null; } rewindSlider.onValueChanged.AddListener(OnSliderChanged); _animating = false; } }