using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; public class SpawnManager : MonoBehaviour { public static SpawnManager instance; [SerializeField] private GameObject playerPrefab; [SerializeField] private GameObject ghostPrefab; [SerializeField] private Transform spawnPoint; private List> allRecordedFrames; private List activeGhostList; private int currentReplayIndex; private InputRecorder currentPlayerRecorder; private GameObject currentPlayer; private void Awake() { if (instance == null) { instance = this; allRecordedFrames = new List>(); activeGhostList = new List(); currentReplayIndex = 0; SpawnPlayer(); } else { Destroy(gameObject); } } private void FixedUpdate() { if (activeGhostList.Count == 0) { return; } for (int i = 0; i < activeGhostList.Count; i++) { ActiveGhost ghost = activeGhostList[i]; if (currentReplayIndex < ghost.recordedFrames.Count) { ghost.controller.GhostRunInput(ghost.recordedFrames[currentReplayIndex]); } else { ghost.controller.StopGhost(); } } currentReplayIndex++; } private void SpawnPlayer() { if (spawnPoint == null) { Debug.LogError("spawnPoint is null"); return; } currentPlayer = Instantiate(playerPrefab, spawnPoint.position, Quaternion.identity); AlignToGround(currentPlayer); currentPlayerRecorder = currentPlayer.GetComponent(); currentPlayerRecorder.StartRecording(); } private void AlignToGround(GameObject player) { Rigidbody2D _rigidbody = player.GetComponent(); if (_rigidbody != null) { _rigidbody.linearVelocity = Vector2.zero; _rigidbody.angularVelocity = 0f; } Physics2D.SyncTransforms(); BoxCollider2D col = player.GetComponent(); float halfHeight = 0f; if (col != null) { halfHeight = (col.size.y * player.transform.localScale.y) * 0.5f; halfHeight -= col.offset.y; } RaycastHit2D hit = Physics2D.Raycast(player.transform.position, Vector2.down, 10f, LayerMask.GetMask("Ground")); if (hit.collider != null) { Vector3 finalPos = new Vector3(hit.point.x, hit.point.y + halfHeight, player.transform.position.z); player.transform.position = finalPos; } } public void StopRecordingAndReStart() { currentPlayerRecorder.StopRecording(); List inputFrames = currentPlayerRecorder.GetInputFrames(); allRecordedFrames.Add(inputFrames); foreach (var ghost in activeGhostList) { Destroy(ghost.controller.gameObject); } activeGhostList.Clear(); currentPlayer.GetComponent().StartRecording(); CameraEffect cameraEffect = FindFirstObjectByType(); if (cameraEffect != null) { cameraEffect.SetTarget(currentPlayer.transform); } currentReplayIndex = 0; SoundManager.instance.PlaySFX(SfxType.Replay); for (int i = 0; i < 1; i++) { foreach (var record in allRecordedFrames) { GameObject ghost = Instantiate(ghostPrefab, spawnPoint.position, Quaternion.identity); GhostController ghostController = ghost.GetComponent(); ActiveGhost addedGhost = new ActiveGhost { controller = ghostController, recordedFrames = record }; activeGhostList.Add(addedGhost); } } } } [System.Serializable] public class ActiveGhost { public GhostController controller; public List recordedFrames; }