Search Unity

Question Need Help using Ui with facepunch + unity netcode for games

Discussion in 'Netcode for GameObjects' started by Vitor_barbosa, Mar 14, 2022.

  1. Vitor_barbosa

    Vitor_barbosa

    Joined:
    Oct 10, 2020
    Posts:
    5
    Ok, so what I'm trying to do is be able to use these two panels I've created to create and join a lobby using steam services. I don't have any experience with using multiplayer so i just followed a tutorial and this is the code i have so far but he did not cover implementing it into a UI and have not been able to find a video or article/documentation on this subject. So i thought it would be worth an ask.




    Code (CSharp):
    1. using Netcode.Transports.Facepunch;
    2. using UnityEngine;
    3. using Steamworks.Data;
    4. using Steamworks;
    5. using Unity.Netcode;
    6.  
    7. public class GameNetworkManager : MonoBehaviour
    8. {
    9. public GameNetworkManager Instance { get; private set; } = null;
    10.  
    11. public Lobby? currentLobby { get; private set; } = null ;
    12.  
    13. private FacepunchTransport transport = null;
    14.  
    15. //bool InviteFriend(SteamId friendId)
    16.  
    17.  
    18. private void Awake()
    19. {
    20. if(Instance == null)
    21. Instance = this;
    22. else
    23. {
    24. Destroy(gameObject);
    25. return;
    26. }
    27. }
    28. private void Start()
    29. {
    30. transport = GetComponent<FacepunchTransport>();
    31. SteamMatchmaking.OnLobbyCreated += OnlobbyCreated;
    32. SteamMatchmaking.OnLobbyEntered += OnLobbyEntered;
    33. SteamMatchmaking.OnLobbyMemberJoined += OnLobbyMemberJoined;
    34. SteamMatchmaking.OnLobbyMemberLeave += OnLobbyMemberLeave;
    35. SteamMatchmaking.OnLobbyInvite += OnLobbyInvite;
    36. SteamMatchmaking.OnLobbyGameCreated += OnLobbyGameCreated;
    37. SteamFriends.OnGameLobbyJoinRequested += OnGameLobbyJoinRequested;
    38. }
    39.  
    40. public void StartClient(SteamId id)
    41. {
    42. NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback;
    43. NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnectCallback;
    44.  
    45. transport.targetSteamId = id;
    46.  
    47. if (NetworkManager.Singleton.StartClient())
    48. Debug.Log("Client has joined", this);
    49. }
    50.  
    51. public async void startHost(int maxMembers = 100)
    52. {
    53.  
    54. NetworkManager.Singleton.OnServerStarted += OnServerStarted;
    55. NetworkManager.Singleton.StartHost();
    56.  
    57. currentLobby = await SteamMatchmaking.CreateLobbyAsync(maxMembers);
    58.  
    59. }
    60. public void OnApplicationQuit() => Disconnect();
    61.  
    62. public void Disconnect( )
    63. {
    64.  
    65. currentLobby?.Leave();
    66. if (NetworkManager.Singleton == null)
    67. return;
    68.  
    69. NetworkManager.Singleton.Shutdown();
    70. }
    71.  
    72.  
    73. #region Network Callbacks
    74. private void OnServerStarted() => Debug.Log("Server has started",this);
    75. private void OnClientConnectedCallback(ulong clientId)
    76. {
    77. Debug.Log($"Client Connected, clientId={clientId}");
    78. }
    79. private void OnClientDisconnectCallback(ulong clientId)
    80. {
    81. Debug.Log($"Client Disconnected, clientId={clientId}");
    82. NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback;
    83. NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientDisconnectCallback;
    84. }
    85.  
    86. #endregion
    87.  
    88.  
    89.  
    90.  
    91. #region Steam Callbacks
    92. private void OnGameLobbyJoinRequested(Lobby lobby, SteamId id) => StartClient(id);
    93. private void OnLobbyGameCreated(Lobby lobby, uint ip, ushort port, SteamId id)
    94. {
    95.  
    96. }
    97.  
    98. private void OnLobbyInvite(Friend friend, Lobby lobby) => Debug.Log($"You got an invite from {friend.Name}", this);
    99.  
    100. private void OnLobbyMemberLeave(Lobby lobby, Friend friend)
    101. {
    102.  
    103. }
    104.  
    105. private void OnLobbyMemberJoined(Lobby lobby, Friend friend)
    106. {
    107.  
    108. }
    109.  
    110. private void OnLobbyEntered(Lobby lobby)
    111. {
    112. if (NetworkManager.Singleton.IsHost)
    113. return;
    114.  
    115. StartClient(lobby.Id);
    116. }
    117.  
    118. private void OnlobbyCreated(Result result,Lobby lobby)
    119. {
    120. if(result != Result.OK)
    121. {
    122. Debug.LogError($"Lobby couldn't be created!,{result}",this);
    123. return;
    124. }
    125.  
    126. lobby.SetFriendsOnly();
    127. lobby.SetData("name", "vitors test lobby");
    128. lobby.SetJoinable(true);
    129. Debug.Log("Lobby Created");
    130.  
    131. }
    132. #endregion
    133.  
    134. private void OnDestroy()
    135. {
    136.  
    137. SteamMatchmaking.OnLobbyCreated -= OnlobbyCreated;
    138. SteamMatchmaking.OnLobbyEntered -= OnLobbyEntered;
    139. SteamMatchmaking.OnLobbyMemberJoined -= OnLobbyMemberJoined;
    140. SteamMatchmaking.OnLobbyMemberLeave -= OnLobbyMemberLeave;
    141. SteamMatchmaking.OnLobbyInvite -= OnLobbyInvite;
    142. SteamMatchmaking.OnLobbyGameCreated -= OnLobbyGameCreated;
    143. SteamFriends.OnGameLobbyJoinRequested -= OnGameLobbyJoinRequested;
    144. if (NetworkManager.Singleton == null)
    145. return;
    146. NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback;
    147. NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientDisconnectCallback;
    148. NetworkManager.Singleton.OnServerStarted -= OnServerStarted;
    149. }
    150. }

    So I'm just wondering what sort of classes or what would i have to add to this in order to get the buttons to work like used Unity Ui and even have done the lobby screen for multiplayer with different solutions but with implementing steam and facepunch I'm having a bit of problem, especially with the limited amount of documentation on the facepunch website on how to do this. So yeah I'm just wondering if there is a hero out there to save this damsel in distress
     
    Last edited: Mar 14, 2022
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    You essentially need to bridge the gap between the game logic and the presentation layer. Here's a very simplified overview of how to achieve this:
    • At the start of the scene grab all the UI elements and put then in a manager so they're easily accessible.

    • Create something like an OnLobbyChangeService to pass in the relevant fields that need to be shown/updated on the UI.

    • In your OnLobby* callbacks make a call like OnLobbyChangeService.ProcessChange() with the information and type of change, and pass these details on to the UI manager to update the UI elements of the scene.
    That's my approach to it anyway, not necessarily the best way. :) As I've done something similar I can share some code examples if it will make things clearer.
     
  3. Vitor_barbosa

    Vitor_barbosa

    Joined:
    Oct 10, 2020
    Posts:
    5
    Oh Ok thank you for your help and if you feel like it I would love to look at your code
     
  4. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    660
    My code's quite convoluted so I've cut out some simple code for buttons that will hopefully give you some ideas.

    Code (CSharp):
    1.     public class LobbySceneController : MonoBehaviour
    2.     {
    3.         LobbyUiInitialisationService lobbyUiInitialisationService = new LobbyUiInitialisationService();
    4.  
    5.         void Awake()
    6.         {
    7.             Debug.Log("LobbySceneController Awake");
    8.  
    9.             lobbyUiInitialisationService.Initialise();
    10.         }
    11. }
    Code (CSharp):
    1.     public class LobbyUiInitialisationService
    2.     {
    3.         LobbyUiButtonInitialisationService buttonInitialisationService = new LobbyUiButtonInitialisationService();
    4.  
    5.         public void Initialise()
    6.         {
    7.             Canvas canvas = GameObject.FindObjectOfType<Canvas>();
    8.  
    9.             buttonInitialisationService.Initialise(canvas);
    10.         }
    11.     }
    Code (CSharp):
    1.     public class LobbyUiButtonInitialisationService
    2.     {
    3.         public void Initialise(Canvas canvas)
    4.         {
    5.             List<Button> buttons = FindButtons(canvas);
    6.  
    7.             InitialiseButtons(buttons);
    8.  
    9.             LobbyUiButtonManager.Instance().Initialise(buttons);
    10.         }
    11.  
    12.         private void InitialiseButtons(List<Button> buttons)
    13.         {
    14.             foreach (Button button in buttons)
    15.             {
    16.                 button.onClick.RemoveAllListeners();
    17.                 button.onClick.AddListener(() => LobbyUiButtonManager.Instance().ButtonPress(button.name));
    18.             }
    19.         }
    20.  
    21.         private List<Button> FindButtons(Canvas canvas)
    22.         {
    23.             return ObjectUtils.GetChildComponents<Button>(canvas);
    24.         }
    25.     }
    Code (CSharp):
    1.     public class LobbyUiButtonManager : Singleton<LobbyUiButtonManager>
    2.     {
    3.         List<Button> buttons;
    4.  
    5.         LobbyActionDetail lobbyActionDetail = new LobbyActionDetail();
    6.  
    7.         public void Initialise(List<Button> buttons)
    8.         {
    9.             this.buttons = buttons;
    10.         }
    11.  
    12.         public void ButtonPress(string name)
    13.         {
    14.             Debug.Log("LobbyUiButtonManager ButtonPress: " + name);
    15.  
    16.             switch (name)
    17.             {
    18.                 case Constants.LOBBY_BUTTON_NAME_EXIT:
    19.                     lobbyActionDetail.ActionType = LobbyActionType.Exit;
    20.                     break;
    21.  
    22.                 case Constants.LOBBY_BUTTON_NAME_JOIN:
    23.                     lobbyActionDetail.ActionType = LobbyActionType.Join;
    24.                     break;
    25.  
    26.                 case Constants.LOBBY_BUTTON_NAME_CREATE:
    27.                     lobbyActionDetail.ActionType = LobbyActionType.Create;
    28.                     break;
    29.  
    30.                 default:
    31.                     Debug.LogError("LobbyUiButtonManager ButtonPress unhandled buttonPress: " + name);
    32.                     break;
    33.             }
    34.  
    35.             ClientActionController.Instance().ProcessAction(MenuActionType.Lobby, lobbyActionDetail);
    36.         }
    37.     }
    That should work for buttons, you grab the other UI types in a similar way but their managers will work quite differently. Rather than post a ton of code just shout if there's something in particular you need help with.

    I tend to do most of what I can in code and don't use GameObjects unless I need to, you may prefer to handle the initialisation side of things in the editor.
     
  5. Vitor_barbosa

    Vitor_barbosa

    Joined:
    Oct 10, 2020
    Posts:
    5