using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using static InputActionMaps; public enum GameState { Starting, Match, End, Paused } public class GameManager : MonoBehaviour { public static GameManager GM { get; private set; } [SerializeField] ZoneRules zone; [SerializeField] Announcments announcements; [SerializeField] int minPlayerCount = 2; public GameState currentState { get; private set; } private Dictionary players = new Dictionary(); private Dictionary playerControlSchemes = new Dictionary(); private float restartMatchTime = 0; private ControlSchemeDetection controlSchemeDetector; void Awake() { if (GM != null) { GM.zone = zone; GM.announcements = announcements; Destroy(gameObject); } else { GM = this; DontDestroyOnLoad(gameObject); } } // void OnEnable() // { // SceneManager.sceneLoaded += OnSceneLoaded; // } // void OnDisable() // { // SceneManager.sceneLoaded -= OnSceneLoaded; // } // void OnSceneLoaded(Scene scene, LoadSceneMode mode) // { // StartControlAssignment(); // } void Update() { if (restartMatchTime > 0) { restartMatchTime -= Time.deltaTime; } else if (currentState == GameState.End) { restartMatchTime = 0; StartNewMatch(); enabled = false; } } // Start is called before the first frame update void Start() { if (currentState == GameState.End) { return; } currentState = GameState.Starting; controlSchemeDetector = new ControlSchemeDetection(); controlSchemeDetector.ControlSchemeDetected += DetectPlayerControls; controlSchemeDetector.EnableDetection(); announcements.AnnounceText("You both press a key \n on your control scheme of choice \n to start the match"); } void StartMatch() { if (zone != null) { zone.onPlayZoneExited += CheckLosingCondition; } if (announcements != null) { announcements.StopAnnouncement(); announcements.AnnounceText("Match Start", 1.6f); } } private void CheckLosingCondition(GameObject go) { if (!go.CompareTag("Player") || currentState == GameState.End) return; currentState = GameState.End; zone.onPlayZoneExited -= CheckLosingCondition; Destroy(go); announcements.AnnounceText(go.name + " has lost the match", 2f); restartMatchTime = 2.2f; enabled = true; } private void StartNewMatch() { string currentSceneName = SceneManager.GetActiveScene().name; players.Clear(); SceneManager.LoadScene(currentSceneName); currentState = GameState.Starting; } public void RegisterPlayer(PlayerController pc) { if (!players.ContainsKey(pc.playerId)) { players[pc.playerId] = pc; } DetectPlayerControls(this); } private void DetectPlayerControls(object sender, string controlScheme = "New Player") { if (players.Count < minPlayerCount) { return; } AssignPlayerControls(controlScheme); if (players.Count <= playerControlSchemes.Count) { if (players.All(pc => PlayerHasActiveControls(pc.Value))) { controlSchemeDetector.DisableDetection(); currentState = GameState.Match; StartMatch(); } } } private void AssignPlayerControls(string controlScheme = "New Player") { foreach (int playerId in players.Keys) { PlayerController pc = players[playerId]; if (PlayerHasActiveControls(pc)) { continue; } if (playerControlSchemes.ContainsKey(playerId)) { controlScheme = playerControlSchemes[playerId]; } else if (playerControlSchemes.ContainsValue(controlScheme)) { return; } if (controlScheme.Contains("Keyboard")) { pc.playerInput.SwitchCurrentControlScheme(controlScheme, Keyboard.current); } else if (controlScheme.Contains("Controller")) { pc.playerInput.SwitchCurrentControlScheme(controlScheme, Gamepad.current); } if (controlScheme != "New Player") { playerControlSchemes[playerId] = controlScheme; } } } private bool PlayerHasActiveControls(PlayerController pc) { if (pc == null) { return false; } string currentScheme = pc.playerInput.currentControlScheme; if (currentScheme != null && currentScheme != "New Player") { return true; } return false; } } public class ControlSchemeDetection : IPlayerActions { InputActionMaps actionMaps; public event EventHandler ControlSchemeDetected; public ControlSchemeDetection() { actionMaps = new InputActionMaps(); actionMaps.Player.SetCallbacks(this); } public void EnableDetection() { actionMaps.Player.Enable(); } public void DisableDetection() { actionMaps.Player.Disable(); } public void OnBoost(InputAction.CallbackContext context) { readControlScheme(context); } public void OnReset(InputAction.CallbackContext context) { readControlScheme(context); } public void OnSteer(InputAction.CallbackContext context) { readControlScheme(context); } public void OnThrust(InputAction.CallbackContext context) { readControlScheme(context); } public void readControlScheme(InputAction.CallbackContext context) { if (!context.canceled || context.performed) { return; } int bindingIndex = context.action.GetBindingIndexForControl(context.control); InputBinding binding = context.action.bindings[bindingIndex]; string controlScheme = binding.groups.Split(';')[0]; ControlSchemeDetected.Invoke(this, controlScheme); } }