144 lines
4.7 KiB
C#
144 lines
4.7 KiB
C#
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;
|
|
}
|
|
}
|