using System; using Unity.Netcode; using Unity.Services.Multiplayer; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using TMPro; public class MainMenuUIController : MonoBehaviour { [Header("Buttons")] [SerializeField] private Button hostButton; [SerializeField] private Button clientButton; [Header("Join by code")] [SerializeField] private TMP_InputField joinCodeInput; [Header("Feedback")] [SerializeField] private TMP_Text joinCodeDisplay; // показывает код созданной сессии [SerializeField] private TMP_Text statusText; // статус/ошибки [SerializeField] private Button copyCodeButton; // копирование кода в буфер обмена [Header("Session")] [SerializeField] private int maxPlayers = 2; [SerializeField] private string sessionType = "dev-game"; [SerializeField] private string gameSceneName = "DEV-Game"; private ISession session; private bool isBusy; private void Awake() { hostButton.onClick.AddListener(OnHostClicked); clientButton.onClick.AddListener(OnJoinClicked); if (copyCodeButton != null) { copyCodeButton.onClick.AddListener(CopyCode); copyCodeButton.gameObject.SetActive(false); } } private void OnDestroy() { hostButton.onClick.RemoveListener(OnHostClicked); clientButton.onClick.RemoveListener(OnJoinClicked); if (copyCodeButton != null) copyCodeButton.onClick.RemoveListener(CopyCode); } private void CopyCode() { if (string.IsNullOrEmpty(SessionInfo.JoinCode)) return; GUIUtility.systemCopyBuffer = SessionInfo.JoinCode; SetStatus($"Code copied: {SessionInfo.JoinCode}"); } private async void OnHostClicked() { if (isBusy) return; SetBusy(true); SetStatus("Creating session..."); try { SessionOptions _options = new SessionOptions { Name = $"session-{Guid.NewGuid().ToString().Substring(0, 6)}", MaxPlayers = maxPlayers, Type = sessionType }; _options.WithRelayNetwork(); // Sessions API сам поднимает Relay и запускает NetworkManager как host session = await MultiplayerService.Instance.CreateSessionAsync(_options); SessionInfo.JoinCode = session.Code; if (joinCodeDisplay != null) joinCodeDisplay.text = session.Code; if (copyCodeButton != null) copyCodeButton.gameObject.SetActive(true); SetStatus($"Hosting. Code: {session.Code}"); Debug.Log($"Session created. Join code: {session.Code}"); // Хост грузит игровую сцену — клиентам она синхронизируется автоматически. // Код сохранён в SessionInfo и показывается уже в игре (SessionCodeView). NetworkManager.Singleton.SceneManager.LoadScene(gameSceneName, LoadSceneMode.Single); } catch (Exception _e) { SetStatus($"Host failed: {_e.Message}"); Debug.LogException(_e); SetBusy(false); } } private async void OnJoinClicked() { if (isBusy) return; string _code = joinCodeInput != null ? joinCodeInput.text.Trim() : string.Empty; if (string.IsNullOrEmpty(_code)) { SetStatus("Enter a join code first"); return; } SetBusy(true); SetStatus($"Joining {_code}..."); try { JoinSessionOptions _options = new JoinSessionOptions { Type = sessionType }; // Подключение к Relay и запуск NetworkManager как client — автоматически. // Игровая сцена придёт от хоста через сетевую синхронизацию сцен. session = await MultiplayerService.Instance.JoinSessionByCodeAsync(_code, _options); SessionInfo.JoinCode = _code; SetStatus("Joined. Waiting for host scene..."); Debug.Log($"Joined session {session.Id}"); } catch (Exception _e) { SetStatus($"Join failed: {_e.Message}"); Debug.LogException(_e); SetBusy(false); } } private void SetBusy(bool _busy) { isBusy = _busy; hostButton.interactable = !_busy; clientButton.interactable = !_busy; } private void SetStatus(string _text) { if (statusText != null) statusText.text = _text; } }