using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Events; 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("Choose your control schemes \n Each player press a button \n to start the match \n (see description for controls)"); } void StartMatch() { if (zone != null) { zone.onPlayZoneExited += CheckLosingCondition; } if (announcements != null) { announcements.StopAnnouncement(); announcements.QueueAnnounceText("Match Start", 1.6f); } } private void CheckLosingCondition(GameObject go) { if (!go.CompareTag("Player") || currentState == GameState.End) return; PlayerController pc = go.GetComponent(); currentState = GameState.End; zone.onPlayZoneExited -= CheckLosingCondition; announcements.AnnounceText(pc.playerName + " has lost the match", 2f); Destroy(go); 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, new Tuple("New Player", 0)); } private void DetectPlayerControls(object eventCauser, Tuple controlScheme) { 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(Tuple controlScheme) { 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.Item1.Contains("Keyboard")) { pc.playerInput.SwitchCurrentControlScheme(controlScheme.Item1, InputSystem.GetDeviceById(controlScheme.Item2)); } else if (controlScheme.Item1.Contains("Controller")) { pc.playerInput.SwitchCurrentControlScheme(controlScheme.Item1, InputSystem.GetDeviceById(controlScheme.Item2)); } if (controlScheme.Item1 != "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, new Tuple(controlScheme, context.control.device.deviceId)); } }