Multiplayer Game Lobby C#, Unity

👤 Sharing: AI
```csharp
using UnityEngine;
using UnityEngine.UI;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using TMPro; // Required for TextMeshPro

public class MultiplayerLobby : MonoBehaviour
{
    [Header("UI Elements")]
    public Button HostButton;
    public Button ClientButton;
    public TMP_InputField IPAddressInputField; // Use TMP_InputField
    public TextMeshProUGUI StatusText; // Use TextMeshProUGUI

    [Header("Configuration")]
    public string DefaultIPAddress = "127.0.0.1";
    public ushort DefaultPort = 7777;  // Standard port. Good practice to define.

    private void Start()
    {
        // Initialize UI elements and event listeners
        if (HostButton != null)
        {
            HostButton.onClick.AddListener(StartHost);
        }
        else
        {
            Debug.LogError("Host Button not assigned.");
        }

        if (ClientButton != null)
        {
            ClientButton.onClick.AddListener(StartClient);
        }
        else
        {
            Debug.LogError("Client Button not assigned.");
        }

        if (IPAddressInputField != null)
        {
            IPAddressInputField.text = DefaultIPAddress; // Set default IP
        }
        else
        {
            Debug.LogError("IP Address Input Field not assigned.");
        }

        if (StatusText == null)
        {
            Debug.LogError("Status Text not assigned.");
        }
        else
        {
            StatusText.text = "Ready"; //initial state
        }


        // Netcode Initialization (important even before starting host/client)
        NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
        NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnected;

    }


    private void OnDestroy() //Important for cleanup to avoid memory leaks/errors.
    {
        if(NetworkManager.Singleton != null)
        {
            NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnected;
            NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientDisconnected;
        }
    }

    private void StartHost()
    {
        // Set Status Text
        StatusText.text = "Starting Host...";

        //Configure the transport if needed (not strictly required if using defaults)
        ConfigureTransport();

        // Start the Host (Server + Client on the same machine)
        NetworkManager.Singleton.StartHost();
    }

    private void StartClient()
    {
        // Set Status Text
        StatusText.text = "Starting Client...";

        // Get IP Address from input field
        string ipAddress = IPAddressInputField.text;

        //Configure the transport with the IP address
        ConfigureTransport(ipAddress);


        // Start the Client
        NetworkManager.Singleton.StartClient();
    }



    private void ConfigureTransport(string ipAddress = null)
    {
        // Get the Unity Transport
        UnityTransport transport = NetworkManager.Singleton.GetComponent<UnityTransport>();

        if (transport != null)
        {
            // Set the IP Address, if provided.  If null, it will use the default.
            if (!string.IsNullOrEmpty(ipAddress))
            {
                transport.ConnectionData.Address = ipAddress;
            }

            //Set the Port
            transport.ConnectionData.Port = DefaultPort;  //Use the defined port

            Debug.Log($"Transport configured. IP: {transport.ConnectionData.Address}, Port: {transport.ConnectionData.Port}"); //Useful for debugging
        }
        else
        {
            Debug.LogError("Unity Transport not found on the NetworkManager!");
            StatusText.text = "Error: Transport missing!";
        }
    }



    // Network Events
    private void OnClientConnected(ulong clientId)
    {
        Debug.Log($"Client connected: {clientId}");
        StatusText.text = $"Client {clientId} connected";
    }

    private void OnClientDisconnected(ulong clientId)
    {
        Debug.Log($"Client disconnected: {clientId}");
        StatusText.text = $"Client {clientId} disconnected";
    }
}
```

**Explanation:**

1.  **Namespaces:**  Imports necessary namespaces from Unity and Netcode for UI elements, network functionality, and TextMeshPro (for better UI text rendering).

2.  **`MultiplayerLobby` Class:**
    *   Inherits from `MonoBehaviour` so it can be attached to a GameObject in the Unity scene.
    *   Manages the UI elements and the network startup process.

3.  **UI Elements (Public Variables):**
    *   `HostButton`: A `Button` component that the user clicks to start a host.
    *   `ClientButton`: A `Button` component that the user clicks to start a client.
    *   `IPAddressInputField`: A `TMP_InputField`  component (TextMeshPro input field) for entering the server's IP address.
    *   `StatusText`: A `TextMeshProUGUI` component to display status messages (e.g., "Connecting...", "Connected").
    *   The `[Header("UI Elements")]` attribute organizes these variables in the Inspector.

4.  **Configuration (Public Variables):**
    *   `DefaultIPAddress`: A string containing the default IP address (usually "127.0.0.1" for localhost).
    *   `DefaultPort`: An unsigned short integer defining the port number for the network connection.  Using a const or readonly would also be good for these.

5.  **`Start()` Method:**
    *   This method is called when the script is initialized.
    *   **Adds Listeners:** It adds `onClick.AddListener()` to the `HostButton` and `ClientButton` to call the `StartHost()` and `StartClient()` methods when the buttons are clicked. This sets up the UI event handling.
    *   **Sets Default IP:** It sets the `IPAddressInputField`'s text to the `DefaultIPAddress`.
    *   **Initializes Status Text:** Sets the initial status to "Ready".
    *   **Network Event Subscriptions:** Subscribes to the `OnClientConnectedCallback` and `OnClientDisconnectCallback` events of the `NetworkManager`. This is crucial for receiving notifications when clients connect or disconnect.  This code *must* be present before a connection occurs, so `Start` is a good place.
    *   **Error Handling:**  Checks if the UI elements are assigned in the Inspector and logs errors to the console if they are not. This is important for debugging.

6. **`OnDestroy()` Method:**

   * This is called when the GameObject is destroyed.  It's *very* important to unsubscribe from the NetworkManager events to prevent memory leaks or errors if the `MultiplayerLobby` object is destroyed while the network is still running.

7.  **`StartHost()` Method:**
    *   Sets the `StatusText` to "Starting Host...".
    *   Calls `ConfigureTransport()` to set up the network transport with the default IP address (if necessary; you might also just use the transport's defaults).
    *   Calls `NetworkManager.Singleton.StartHost()` to start the Netcode host. This makes the Unity instance both the server and a client.

8.  **`StartClient()` Method:**
    *   Sets the `StatusText` to "Starting Client...".
    *   Gets the IP address from the `IPAddressInputField`.
    *   Calls `ConfigureTransport(ipAddress)` to configure the network transport with the IP address entered by the user.
    *   Calls `NetworkManager.Singleton.StartClient()` to start the Netcode client.

9.  **`ConfigureTransport()` Method:**
    *   Gets the `UnityTransport` component from the `NetworkManager`.  This is the actual transport layer that handles sending and receiving network data.
    *   Sets the `ConnectionData.Address` property of the `UnityTransport` to the provided `ipAddress` if one is given. This is how you tell the client which server to connect to.
    *   Sets the `ConnectionData.Port` to the `DefaultPort`.  Make sure this matches the port the host is using.
    *   Includes Debug.Log messages to help with debugging the transport configuration.
    *   Includes error handling in case the `UnityTransport` component is not found.

10. **Network Event Handlers (`OnClientConnected`, `OnClientDisconnected`):**
    *   These methods are called automatically by the Netcode framework when clients connect or disconnect.
    *   They log messages to the console and update the `StatusText` to provide feedback to the user.  The `clientId` is a unique identifier for each connected client.

**How to Use This Script in Unity:**

1.  **Create a new Unity project** (if you don't already have one).
2.  **Install Netcode for GameObjects:**
    *   In the Unity Editor, go to `Window -> Package Manager`.
    *   Search for "Netcode for GameObjects" and install it.  If it's not listed, you might need to enable pre-release packages in the Package Manager settings.
3.  **Install Unity Transport Package:**
    *   In the Unity Editor, go to `Window -> Package Manager`.
    *   Search for "Unity Transport" and install it.
4.  **Install TextMeshPro:**
    *   Go to `Window -> TextMeshPro -> Import TMP Essential Resources`.
5.  **Create a new scene:** `File -> New Scene`.
6.  **Create UI Elements:**
    *   Right-click in the Hierarchy window and select `UI -> Button`. Rename it "HostButton".
    *   Right-click in the Hierarchy window and select `UI -> Button`. Rename it "ClientButton".
    *   Right-click in the Hierarchy window and select `UI -> Text - TextMeshPro`.  Rename it "StatusText".
    *   Right-click in the Hierarchy window and select `UI -> Input Field - TextMeshPro`. Rename it "IPAddressInputField".
7.  **Create a GameObject:**
    *   Right-click in the Hierarchy window and select `Create Empty`.  Rename it "MultiplayerLobby".
8.  **Add the script:**
    *   Drag the `MultiplayerLobby.cs` script onto the "MultiplayerLobby" GameObject.
9.  **Assign UI Elements:**
    *   In the Inspector window for the "MultiplayerLobby" GameObject, drag the UI elements from the Hierarchy window to the corresponding fields in the `MultiplayerLobby` script.  (Drag "HostButton" to "Host Button", "ClientButton" to "Client Button", etc.)
10. **Add a NetworkManager:**
    *   Create a new GameObject in the scene (`Create Empty`) and rename it "NetworkManager".
    *   Add the `NetworkManager` component to the "NetworkManager" GameObject (you'll find it by searching for "NetworkManager" in the Add Component menu).  *Important*: It's generally a good idea to only have *one* NetworkManager in your scene, or unexpected behaviour can occur.
    *   Add the `UnityTransport` component to the "NetworkManager" GameObject.
11. **Configure the Transport (Optional):**
    *   In the Inspector for the `UnityTransport` component (on the "NetworkManager" GameObject), you can change the port number and other settings if needed.  The default is usually fine for testing.
12. **Test:**
    *   Build and run the game.  You'll need to build it to test multiplayer properly (File -> Build Settings -> Build).
    *   Run two instances of the game (two executables).
    *   In one instance, click the "Host" button.
    *   In the other instance, enter the IP address of the host machine (or "127.0.0.1" if you're running both on the same machine) in the `IPAddressInputField` and click the "Client" button.

**Important Considerations:**

*   **Security:** This example is a basic lobby.  For production games, you'll need to add more robust security measures (authentication, authorization, etc.).  Don't blindly expose your game to the internet without proper security.
*   **Error Handling:**  Add more comprehensive error handling (e.g., what happens if the connection fails, if the IP address is invalid, etc.).
*   **UI Design:**  This is a very basic UI.  Design a more user-friendly and visually appealing lobby.
*   **Networked Game Logic:**  This example only sets up the lobby.  You'll need to implement the game logic and network it using Netcode.  This involves creating NetworkPrefabs, spawning objects on the network, and sending network variables and RPCs (Remote Procedure Calls) to synchronize the game state between clients.
*   **Relay Services:** For games where players are behind NAT firewalls, you'll need to use a relay service (like Unity Relay or a third-party solution). The Unity Transport currently supports Unity Relay.
*   **Scene Management:** You'll likely want to use `NetworkSceneManager` to load different scenes after the players connect to the lobby.
*   **Scalability:**  This is a very basic setup.  For games with a large number of players, you'll need to consider scalability and server architecture.
*   **TextMeshPro:** Using TextMeshPro provides better text rendering and more control over the appearance of your text.  It's highly recommended for UI elements.

This comprehensive example and explanation will help you get started with creating a multiplayer game lobby in Unity using C# and Netcode for GameObjects. Remember to explore the Netcode documentation for more advanced features and best practices.
👁️ Viewed: 6

Comments