using Cysharp.Threading.Tasks; using Gs2.Realtime.Sync; using UnityEngine; [RequireComponent(typeof(NetworkWorld), typeof(NetworkSession))] public sealed class AdventureRoom : MonoBehaviour { [SerializeField] private AdventureLogin login; private NetworkWorld world; private NetworkSession session; private bool busy; private string roomName = "practice"; private string targetConnection = ""; private string message = "룸을 만든 뒤 연결하세요"; private void Awake() { world = GetComponent(); session = GetComponent(); session.Ready += OnReady; session.Disconnected += OnDisconnected; } private void OnDestroy() { session.Ready -= OnReady; session.Disconnected -= OnDisconnected; } private void OnReady() { world.Instantiate(1, new Vector3(Random.Range(-3f, 3f), 1, Random.Range(-3f, 3f)), Quaternion.identity); message = "연결했습니다. WASD로 이동하고 Space로 인사합니다"; } private void OnDisconnected(string reason) { message = "연결이 끊겼습니다: " + reason; } private void OnGUI() { if (login == null || login.Session == null) return; GUILayout.BeginArea(new Rect(20, 210, 650, Screen.height - 230), GUI.skin.box); GUILayout.Label(message); var connected = world.Client != null && world.Client.Ready; GUI.enabled = !busy && !connected; roomName = GUILayout.TextField(roomName); if (GUILayout.Button("이 룸에 연결")) Connect().Forget(); GUI.enabled = !busy && connected; if (GUILayout.Button("연결 끊기")) session.Disconnect(); if (connected) { GUILayout.Label("내 연결 ID: " + world.Client.ConnectionId); GUILayout.Label("조작 권한을 받을 상대 연결 ID"); targetConnection = GUILayout.TextField(targetConnection); foreach (var entity in world.GetComponentsInChildren()) { if (!entity.IsSpawned) continue; GUILayout.Label("오브젝트 " + entity.Object.Id + " / 소유자 " + entity.OwnerId); GUI.enabled = entity.IsMine && uint.TryParse(targetConnection, out _); if (GUILayout.Button("이 오브젝트의 조작 권한 넘기기")) entity.TransferOwnership(uint.Parse(targetConnection)); } } GUI.enabled = true; GUILayout.EndArea(); } private async UniTask Connect() { if (busy) return; busy = true; try { var room = login.Gs2.Realtime.Namespace("adventure-sync").Room(roomName); room.Invalidate(); var get = await room.ModelAsync(); if (get == null || string.IsNullOrEmpty(get.IpAddress) || get.Port == 0) { message = "룸 연결을 준비 중입니다. 잠시 기다린 뒤 연결하세요"; return; } session.Connect(login.Session.AccessToken.Token, get.IpAddress, get.Port, get.EncryptionKey); await UniTask.WaitUntil( () => session.State == NetworkSessionState.Ready || session.State == NetworkSessionState.Disconnected, cancellationToken: this.GetCancellationTokenOnDestroy()); if (session.ConnectionError != null) message = session.ConnectionError.Message; } catch (System.Exception error) { message = error.Message; } finally { busy = false; } } }