GameManager.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using TMPro;
  4. using UnityEngine;
  5. using UnityEngine.SceneManagement;
  6. using StarterAssets;
  7. public class GameManager : MonoBehaviour
  8. {
  9. public static GameManager Instance;
  10. public GameObject GameOverUI;
  11. public GameObject VictoryUI;
  12. [Header("Orb Settings")]
  13. public int totalOrbs = 20;
  14. private int collectedOrbs = 0;
  15. public List<EnergyOrb> allOrbs = new List<EnergyOrb>();
  16. [Header("UI")]
  17. public TMP_Text orbsCounter;
  18. public TMP_Text timertext;
  19. [Header("Nightfall Timer")]
  20. public float timeRemaining = 60f;
  21. private bool gameOver = false;
  22. //public EnergyOrb[] allOrbs;
  23. [Header("References")]
  24. public ThirdPersonController player;
  25. public TimeChanger timeManager;
  26. [Header("Procedural")]
  27. public int worldSeed;
  28. [HideInInspector] public SaveData inMemorySave = null;
  29. public bool HasInMemorySave => inMemorySave != null;
  30. void Awake()
  31. {
  32. if (Instance == null)
  33. {
  34. Instance = this;
  35. } else
  36. {
  37. Destroy(gameObject);
  38. }
  39. }
  40. void Start()
  41. {
  42. //allOrbs = FindObjectsOfType<EnergyOrb>();
  43. Cursor.lockState = CursorLockMode.Locked;
  44. Cursor.visible = false;
  45. UpdateOrbUI();
  46. UpdateTimerUI();
  47. }
  48. void Update()
  49. {
  50. if (gameOver) return;
  51. timeRemaining -= Time.deltaTime;
  52. if (timeRemaining <= 0f)
  53. {
  54. timeRemaining = 0f;
  55. GameOver();
  56. }
  57. UpdateTimerUI();
  58. if (Input.GetKeyDown(KeyCode.F5))
  59. {
  60. SaveSystem.Save(CreateSaveData());
  61. }
  62. if (Input.GetKeyDown(KeyCode.F9))
  63. {
  64. LoadGame(SaveSystem.Load());
  65. }
  66. }
  67. public void CollectOrb()
  68. {
  69. if (gameOver) return;
  70. collectedOrbs++;
  71. UpdateOrbUI();
  72. if (collectedOrbs >= totalOrbs)
  73. {
  74. Victory();
  75. }
  76. }
  77. void UpdateOrbUI()
  78. {
  79. if (orbsCounter != null)
  80. {
  81. orbsCounter.text = $"{collectedOrbs} / {totalOrbs}";
  82. }
  83. }
  84. void UpdateTimerUI()
  85. {
  86. if (timertext != null)
  87. {
  88. timertext.text = Mathf.Ceil(timeRemaining).ToString(); ;
  89. }
  90. }
  91. void Victory()
  92. {
  93. VictoryUI.SetActive(true);
  94. gameOver = true;
  95. Time.timeScale = 0f;
  96. if (player != null)
  97. player.enabled = false;
  98. Cursor.lockState = CursorLockMode.None;
  99. Cursor.visible = true;
  100. Debug.Log("YOU WIN!");
  101. }
  102. void GameOver()
  103. {
  104. GameOverUI.SetActive(true);
  105. gameOver = true;
  106. Time.timeScale = 0f;
  107. if (player != null)
  108. player.enabled = false;
  109. Cursor.lockState = CursorLockMode.None;
  110. Cursor.visible = true;
  111. Debug.Log("YOU LOSE!");
  112. }
  113. public void RegisterOrbs(List<EnergyOrb> newOrbs)
  114. {
  115. allOrbs.AddRange(newOrbs);
  116. totalOrbs = allOrbs.Count; // Sync the total count
  117. UpdateOrbUI();
  118. }
  119. public void StartNewGame()
  120. {
  121. gameOver = false;
  122. timeRemaining = 60f;
  123. UpdateTimerUI();
  124. foreach (var orb in allOrbs)
  125. {
  126. orb.Collected = false;
  127. orb.gameObject.SetActive(true);
  128. }
  129. collectedOrbs = 0;
  130. UpdateOrbUI();
  131. if (player != null)
  132. {
  133. player.transform.position = Vector3.zero;
  134. player.transform.rotation = Quaternion.identity;
  135. player.Stamina = player.maxStamina;
  136. }
  137. }
  138. /* Saving works
  139. * Loading works too, both ingame. sometimes.
  140. */
  141. public void RestartGame()
  142. {
  143. Time.timeScale = 1f;
  144. SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
  145. Cursor.lockState = CursorLockMode.Locked;
  146. Cursor.visible = false;
  147. }
  148. public SaveData CreateSaveData()
  149. {
  150. SaveData data = new SaveData();
  151. // Player
  152. data.playerPosition = player.transform.position;
  153. data.playerRotation = player.transform.rotation;
  154. data.stamina = player.Stamina;
  155. // Time / orbs
  156. data.orbsCollected = collectedOrbs;
  157. data.remainingTime = timeRemaining;
  158. // Orbs
  159. data.orbs.Clear();
  160. foreach (var orb in allOrbs)
  161. {
  162. data.orbs.Add(new OrbData
  163. {
  164. id = orb.ID,
  165. collected = orb.Collected
  166. });
  167. }
  168. // ENEMIES (THIS IS WHERE IT GOES)
  169. data.enemies.Clear();
  170. foreach (EnemyAI enemy in FindObjectsOfType<EnemyAI>())
  171. {
  172. data.enemies.Add(enemy.GetSaveData());
  173. }
  174. return data;
  175. }
  176. public void SaveInMemory()
  177. {
  178. inMemorySave = CreateSaveData();
  179. Debug.Log("Game saved in memory!");
  180. }
  181. public void LoadGame(SaveData data)
  182. {
  183. if (data == null) return;
  184. StartCoroutine(LoadGameNextFrame(data));
  185. }
  186. public void LoadFromMemory()
  187. {
  188. if (inMemorySave != null)
  189. {
  190. StartCoroutine(LoadGameNextFrame(inMemorySave));
  191. Debug.Log("Loaded game from memory!");
  192. }
  193. else
  194. {
  195. Debug.LogWarning("No in-memory save found!");
  196. }
  197. }
  198. public IEnumerator LoadGameNextFrame(SaveData data)
  199. {
  200. yield return new WaitForEndOfFrame(); // wait for scene & map to generate
  201. // Restore procedural map seed
  202. WorldSettings.seed = data.worldSeed;
  203. WorldSettings.generateNewWorld = false;
  204. // In LoadGameNextFrame or directly in PauseMenu
  205. Rigidbody rb = player.GetComponent<Rigidbody>();
  206. if (rb != null)
  207. {
  208. rb.position = data.playerPosition; // directly sets physics position
  209. rb.rotation = data.playerRotation;
  210. rb.linearVelocity = Vector3.zero; // reset velocity
  211. }
  212. else
  213. {
  214. player.transform.position = data.playerPosition;
  215. player.transform.rotation = data.playerRotation;
  216. }
  217. player.Stamina = data.stamina;
  218. // Player
  219. player.transform.position = data.playerPosition;
  220. player.transform.rotation = data.playerRotation;
  221. player.Stamina = data.stamina;
  222. // Timer
  223. timeRemaining = data.remainingTime;
  224. UpdateTimerUI();
  225. // Orbs
  226. collectedOrbs = data.orbsCollected;
  227. for (int i = 0; i < allOrbs.Count; i++)
  228. {
  229. if (i >= data.orbs.Count) break;
  230. allOrbs[i].Collected = data.orbs[i].collected;
  231. allOrbs[i].gameObject.SetActive(!data.orbs[i].collected);
  232. }
  233. UpdateOrbUI();
  234. Debug.Log("Game Loaded!");
  235. }
  236. }