HoangMinhNguyen

Game Manager Example

Jul 13th, 2025 (edited)
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.30 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System.Collections;
  4.  
  5. public class GameManager : MonoBehaviour
  6. {
  7.     [Header("Player Management")]
  8.     public GameObject playerPrefab;
  9.     public Transform playerSpawnParent;
  10.     public Vector3[] spawnPositions = new Vector3[4];
  11.    
  12.     [Header("Game Settings")]
  13.     public int maxPlayers = 4;
  14.     public float gameStartDelay = 3f;
  15.    
  16.     private UnityPositionSync positionSync;
  17.     private Dictionary<short, CharacterController> players = new Dictionary<short, CharacterController>();
  18.     private short localPlayerSlot = -1;
  19.     private bool gameStarted = false;
  20.    
  21.     void Start()
  22.     {
  23.         // Get position sync component
  24.         positionSync = FindObjectOfType<UnityPositionSync>();
  25.         if (positionSync == null)
  26.         {
  27.             Debug.LogError("UnityPositionSync not found!");
  28.             return;
  29.         }
  30.        
  31.         // Start monitoring for player assignments
  32.         StartCoroutine(MonitorPlayerAssignments());
  33.     }
  34.    
  35.     void Update()
  36.     {
  37.         if (!gameStarted || positionSync == null) return;
  38.        
  39.         // Update all players
  40.         UpdatePlayers();
  41.        
  42.         // Handle player disconnections
  43.         HandlePlayerDisconnections();
  44.     }
  45.    
  46.     System.Collections.IEnumerator MonitorPlayerAssignments()
  47.     {
  48.         // Wait for connection
  49.         while (!positionSync.IsConnected())
  50.         {
  51.             yield return new WaitForSeconds(0.1f);
  52.         }
  53.        
  54.         Debug.Log("Connected to server, waiting for slot assignment...");
  55.        
  56.         // Wait for slot assignment
  57.         while (positionSync.GetMySlot() == -1)
  58.         {
  59.             yield return new WaitForSeconds(0.1f);
  60.         }
  61.        
  62.         localPlayerSlot = positionSync.GetMySlot();
  63.         Debug.Log($"Local player assigned to slot: {localPlayerSlot}");
  64.        
  65.         // Create local player
  66.         CreatePlayer(localPlayerSlot, true);
  67.        
  68.         // Start game
  69.         StartCoroutine(StartGame());
  70.     }
  71.    
  72.     System.Collections.IEnumerator StartGame()
  73.     {
  74.         Debug.Log("Game starting in " + gameStartDelay + " seconds...");
  75.         yield return new WaitForSeconds(gameStartDelay);
  76.        
  77.         gameStarted = true;
  78.         Debug.Log("Game started!");
  79.        
  80.         // Start monitoring for other players
  81.         StartCoroutine(MonitorOtherPlayers());
  82.     }
  83.    
  84.     System.Collections.IEnumerator MonitorOtherPlayers()
  85.     {
  86.         while (gameStarted)
  87.         {
  88.             // Check for new players
  89.             Dictionary<short, Vector3> positions = positionSync.GetOtherPlayerPositions();
  90.            
  91.             foreach (var kvp in positions)
  92.             {
  93.                 short slot = kvp.Key;
  94.                
  95.                 // Skip local player
  96.                 if (slot == localPlayerSlot)
  97.                     continue;
  98.                
  99.                 // Create player if not exists
  100.                 if (!players.ContainsKey(slot))
  101.                 {
  102.                     CreatePlayer(slot, false);
  103.                     Debug.Log($"Created remote player for slot: {slot}");
  104.                 }
  105.             }
  106.            
  107.             yield return new WaitForSeconds(0.5f); // Check every 500ms
  108.         }
  109.     }
  110.    
  111.     void CreatePlayer(short slot, bool isLocalPlayer)
  112.     {
  113.         if (playerPrefab == null)
  114.         {
  115.             Debug.LogError("Player prefab not assigned!");
  116.             return;
  117.         }
  118.        
  119.         // Calculate spawn position
  120.         Vector3 spawnPos = GetSpawnPosition(slot);
  121.        
  122.         // Create player GameObject
  123.         GameObject playerObj = Instantiate(playerPrefab, spawnPos, Quaternion.identity, playerSpawnParent);
  124.         playerObj.name = $"Player_{slot}";
  125.        
  126.         // Setup character controller
  127.         CharacterController characterController = playerObj.GetComponent<CharacterController>();
  128.         if (characterController == null)
  129.         {
  130.             characterController = playerObj.AddComponent<CharacterController>();
  131.         }
  132.        
  133.         characterController.slot = slot;
  134.         characterController.isLocalPlayer = isLocalPlayer;
  135.        
  136.         // Setup visual elements
  137.         SetupPlayerVisuals(playerObj, slot, isLocalPlayer);
  138.        
  139.         // Add to players dictionary
  140.         players[slot] = characterController;
  141.        
  142.         Debug.Log($"Created player {slot} (Local: {isLocalPlayer}) at position {spawnPos}");
  143.     }
  144.    
  145.     Vector3 GetSpawnPosition(short slot)
  146.     {
  147.         int index = (slot - 1) % spawnPositions.Length;
  148.         return spawnPositions[index];
  149.     }
  150.    
  151.     void SetupPlayerVisuals(GameObject playerObj, short slot, bool isLocalPlayer)
  152.     {
  153.         // Setup character model
  154.         GameObject characterModel = playerObj.transform.Find("CharacterModel")?.gameObject;
  155.         if (characterModel != null)
  156.         {
  157.             Renderer renderer = characterModel.GetComponent<Renderer>();
  158.             if (renderer != null)
  159.             {
  160.                 Material material = new Material(renderer.material);
  161.                
  162.                 if (isLocalPlayer)
  163.                 {
  164.                     material.color = Color.cyan;
  165.                 }
  166.                 else
  167.                 {
  168.                     // Different colors for different slots
  169.                     Color[] colors = { Color.red, Color.blue, Color.yellow, Color.green };
  170.                     int colorIndex = (slot - 1) % colors.Length;
  171.                     material.color = colors[colorIndex];
  172.                 }
  173.                
  174.                 renderer.material = material;
  175.             }
  176.         }
  177.        
  178.         // Setup name tag
  179.         GameObject nameTag = playerObj.transform.Find("NameTag")?.gameObject;
  180.         if (nameTag != null)
  181.         {
  182.             TextMesh nameText = nameTag.GetComponent<TextMesh>();
  183.             if (nameText != null)
  184.             {
  185.                 nameText.text = $"Player {slot}";
  186.                 nameText.color = isLocalPlayer ? Color.green : Color.white;
  187.             }
  188.         }
  189.        
  190.         // Setup health bar (if exists)
  191.         GameObject healthBar = playerObj.transform.Find("HealthBar")?.gameObject;
  192.         if (healthBar != null)
  193.         {
  194.             // Setup health bar logic here
  195.         }
  196.     }
  197.    
  198.     void UpdatePlayers()
  199.     {
  200.         // Update all players
  201.         foreach (var kvp in players)
  202.         {
  203.             short slot = kvp.Key;
  204.             CharacterController player = kvp.Value;
  205.            
  206.             if (player != null)
  207.             {
  208.                 // Player controller handles its own updates
  209.                 // This is just for game manager logic
  210.             }
  211.         }
  212.     }
  213.    
  214.     void HandlePlayerDisconnections()
  215.     {
  216.         List<short> disconnectedSlots = new List<short>();
  217.        
  218.         // Check for disconnected players
  219.         foreach (var kvp in players)
  220.         {
  221.             short slot = kvp.Key;
  222.             CharacterController player = kvp.Value;
  223.            
  224.             // Skip local player
  225.             if (slot == localPlayerSlot)
  226.                 continue;
  227.            
  228.             // Check if player still exists in position sync
  229.             Dictionary<short, Vector3> positions = positionSync.GetOtherPlayerPositions();
  230.             if (!positions.ContainsKey(slot))
  231.             {
  232.                 disconnectedSlots.Add(slot);
  233.             }
  234.         }
  235.        
  236.         // Remove disconnected players
  237.         foreach (short slot in disconnectedSlots)
  238.         {
  239.             RemovePlayer(slot);
  240.         }
  241.     }
  242.    
  243.     void RemovePlayer(short slot)
  244.     {
  245.         if (players.ContainsKey(slot))
  246.         {
  247.             CharacterController player = players[slot];
  248.             if (player != null)
  249.             {
  250.                 // Add disconnect effect
  251.                 AddDisconnectEffect(player.transform.position);
  252.                
  253.                 // Destroy player GameObject
  254.                 Destroy(player.gameObject);
  255.             }
  256.            
  257.             players.Remove(slot);
  258.             Debug.Log($"Removed player {slot}");
  259.         }
  260.     }
  261.    
  262.     void AddDisconnectEffect(Vector3 position)
  263.     {
  264.         // Create disconnect particle effect
  265.         GameObject disconnectEffect = new GameObject("DisconnectEffect");
  266.         disconnectEffect.transform.position = position;
  267.        
  268.         ParticleSystem particles = disconnectEffect.AddComponent<ParticleSystem>();
  269.         var main = particles.main;
  270.         main.startLifetime = 2f;
  271.         main.startSpeed = 3f;
  272.         main.startSize = 0.5f;
  273.         main.startColor = Color.red;
  274.        
  275.         var emission = particles.emission;
  276.         emission.rateOverTime = 20;
  277.        
  278.         var shape = particles.shape;
  279.         shape.shapeType = ParticleSystemShapeType.Sphere;
  280.         shape.radius = 1f;
  281.        
  282.         // Destroy effect after 3 seconds
  283.         Destroy(disconnectEffect, 3f);
  284.     }
  285.    
  286.     // Public methods
  287.     public CharacterController GetPlayer(short slot)
  288.     {
  289.         return players.ContainsKey(slot) ? players[slot] : null;
  290.     }
  291.    
  292.     public Dictionary<short, CharacterController> GetAllPlayers()
  293.     {
  294.         return new Dictionary<short, CharacterController>(players);
  295.     }
  296.    
  297.     public short GetLocalPlayerSlot()
  298.     {
  299.         return localPlayerSlot;
  300.     }
  301.    
  302.     public bool IsGameStarted()
  303.     {
  304.         return gameStarted;
  305.     }
  306.    
  307.     public int GetPlayerCount()
  308.     {
  309.         return players.Count;
  310.     }
  311.    
  312.     // Debug methods
  313.     void OnGUI()
  314.     {
  315.         if (!gameStarted) return;
  316.        
  317.         GUILayout.BeginArea(new Rect(10, 10, 300, 200));
  318.         GUILayout.Label($"Game Status: {(gameStarted ? "Running" : "Waiting")}");
  319.         GUILayout.Label($"Local Player Slot: {localPlayerSlot}");
  320.         GUILayout.Label($"Total Players: {players.Count}");
  321.         GUILayout.Label($"Connection: {(positionSync.IsConnected() ? "Connected" : "Disconnected")}");
  322.        
  323.         // Show interpolation status
  324.         Dictionary<short, bool> interpStatus = positionSync.GetInterpolationStatus();
  325.         GUILayout.Label("Interpolation Status:");
  326.         foreach (var kvp in interpStatus)
  327.         {
  328.             GUILayout.Label($"  Slot {kvp.Key}: {(kvp.Value ? "Active" : "Inactive")}");
  329.         }
  330.        
  331.         GUILayout.EndArea();
  332.     }
  333. }
Add Comment
Please, Sign In to add comment