diff --git a/Assets/Infrastructure/Network/Configs.meta b/Assets/Infrastructure/Network/Configs.meta deleted file mode 100644 index b8432f4..0000000 --- a/Assets/Infrastructure/Network/Configs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: fd48a88d389f79249986de098143c22f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/Configs/NetworkConfig.cs b/Assets/Infrastructure/Network/Configs/NetworkConfig.cs deleted file mode 100644 index e69bdde..0000000 --- a/Assets/Infrastructure/Network/Configs/NetworkConfig.cs +++ /dev/null @@ -1,404 +0,0 @@ -using UnityEngine; - -namespace ProjectVG.Infrastructure.Network.Configs -{ - /// - /// Unity 표준 방식의 네트워크 설정 ScriptableObject - /// Editor에서 설정 가능하고, 런타임에서는 정적 접근자로 사용 - /// - [CreateAssetMenu(fileName = "NetworkConfig", menuName = "ProjectVG/Network/NetworkConfig")] - public class NetworkConfig : ScriptableObject - { - [Header("Environment Settings")] - [SerializeField] private EnvironmentType environment = EnvironmentType.Development; - - [Header("Server Addresses")] - [SerializeField] private string developmentServer = "localhost:7900"; - [SerializeField] private string testServer = "localhost:7900"; - [SerializeField] private string productionServer = "122.153.130.223:7900"; - - [Header("HTTP API Settings")] - [SerializeField] private string apiVersion = "v1"; - [SerializeField] private string apiPath = "api"; - [SerializeField] private float httpTimeout = 30f; - [SerializeField] private int maxRetryCount = 3; - [SerializeField] private float retryDelay = 1f; - - [Header("WebSocket Settings")] - [SerializeField] private string wsPath = "ws"; - [SerializeField] private float wsTimeout = 30f; - [SerializeField] private float reconnectDelay = 5f; - [SerializeField] private int maxReconnectAttempts = 3; - [SerializeField] private bool autoReconnect = true; - [SerializeField] private float heartbeatInterval = 30f; - [SerializeField] private bool enableHeartbeat = true; - [SerializeField] private int maxMessageSize = 65536; // 64KB - [SerializeField] private float messageTimeout = 10f; - [SerializeField] private bool enableMessageLogging = true; - [SerializeField] private string wsMessageType = "json"; // "json" 또는 "binary" - - [Header("Common Settings")] - [SerializeField] private string userAgent = "ProjectVG-Client/1.0"; - [SerializeField] private string contentType = "application/json"; - - // Environment enum - public enum EnvironmentType - { - Development, - Test, - Production - } - - // Singleton instance - private static NetworkConfig _instance; - public static NetworkConfig Instance - { - get - { - if (_instance == null) - { - _instance = Resources.Load("NetworkConfig"); - if (_instance == null) - { - Debug.LogError("NetworkConfig를 찾을 수 없습니다. Resources 폴더에 NetworkConfig.asset 파일을 생성하세요."); - _instance = CreateDefaultInstance(); - } - } - return _instance; - } - } - - // Properties - public EnvironmentType Environment => environment; - public string ApiPath => apiPath; - public string WsPath => wsPath; - - - - #region Environment Configuration - - - - #endregion - - #region Static Accessors (편의 메서드들) - - /// - /// 현재 환경 - /// - public static EnvironmentType CurrentEnvironment => Instance.Environment; - - /// - /// HTTP 서버 주소 - /// - public static string HttpServerAddress - { - get - { - string server; - switch (Instance.environment) - { - case EnvironmentType.Development: - server = Instance.developmentServer; - break; - case EnvironmentType.Test: - server = Instance.testServer; - break; - case EnvironmentType.Production: - server = Instance.productionServer; - break; - default: - server = Instance.developmentServer; - break; - } - return $"http://{server}"; - } - } - - /// - /// WebSocket 서버 주소 - /// - public static string WebSocketServerAddress - { - get - { - string server; - switch (Instance.environment) - { - case EnvironmentType.Development: - server = Instance.developmentServer; - break; - case EnvironmentType.Test: - server = Instance.testServer; - break; - case EnvironmentType.Production: - server = Instance.productionServer; - break; - default: - server = Instance.developmentServer; - break; - } - return $"ws://{server}"; - } - } - - /// - /// API 버전 - /// - public static string ApiVersion => Instance.apiVersion; - - /// - /// HTTP 타임아웃 - /// - public static float HttpTimeout => Instance.httpTimeout; - - /// - /// 최대 재시도 횟수 - /// - public static int MaxRetryCount => Instance.maxRetryCount; - - /// - /// 재시도 지연 시간 - /// - public static float RetryDelay => Instance.retryDelay; - - /// - /// WebSocket 타임아웃 - /// - public static float WebSocketTimeout => Instance.wsTimeout; - - /// - /// 재연결 지연 시간 - /// - public static float ReconnectDelay => Instance.reconnectDelay; - - /// - /// 최대 재연결 시도 횟수 - /// - public static int MaxReconnectAttempts => Instance.maxReconnectAttempts; - - /// - /// 자동 재연결 - /// - public static bool AutoReconnect => Instance.autoReconnect; - - /// - /// 하트비트 간격 - /// - public static float HeartbeatInterval => Instance.heartbeatInterval; - - /// - /// 하트비트 활성화 - /// - public static bool EnableHeartbeat => Instance.enableHeartbeat; - - /// - /// 최대 메시지 크기 - /// - public static int MaxMessageSize => Instance.maxMessageSize; - - /// - /// 메시지 타임아웃 - /// - public static float MessageTimeout => Instance.messageTimeout; - - /// - /// 메시지 로깅 활성화 - /// - public static bool EnableMessageLogging => Instance.enableMessageLogging; - - /// - /// WebSocket 메시지 타입 - /// - public static string WebSocketMessageType => Instance.wsMessageType; - - /// - /// JSON 메시지 타입인지 확인 - /// - public static bool IsJsonMessageType => Instance.wsMessageType?.ToLower() == "json"; - - /// - /// 바이너리 메시지 타입인지 확인 - /// - public static bool IsBinaryMessageType => Instance.wsMessageType?.ToLower() == "binary"; - - /// - /// 사용자 에이전트 - /// - public static string UserAgent => Instance.userAgent; - - /// - /// 콘텐츠 타입 - /// - public static string ContentType => Instance.contentType; - - /// - /// 전체 API URL 생성 - /// - public static string GetFullApiUrl(string endpoint) - { - var baseUrl = HttpServerAddress; - return $"{baseUrl.TrimEnd('/')}/{Instance.apiPath.TrimStart('/').TrimEnd('/')}/{Instance.apiVersion.TrimStart('/').TrimEnd('/')}/{endpoint.TrimStart('/')}"; - } - - /// - /// 사용자 API URL - /// - public static string GetUserApiUrl(string path = "") - { - return GetFullApiUrl($"users/{path.TrimStart('/')}"); - } - - /// - /// 캐릭터 API URL - /// - public static string GetCharacterApiUrl(string path = "") - { - return GetFullApiUrl($"characters/{path.TrimStart('/')}"); - } - - /// - /// 대화 API URL - /// - public static string GetConversationApiUrl(string path = "") - { - return GetFullApiUrl($"conversations/{path.TrimStart('/')}"); - } - - /// - /// 인증 API URL - /// - public static string GetAuthApiUrl(string path = "") - { - return GetFullApiUrl($"auth/{path.TrimStart('/')}"); - } - - /// - /// WebSocket URL - /// - public static string GetWebSocketUrl() - { - var baseUrl = WebSocketServerAddress; - return $"{baseUrl.TrimEnd('/')}/{Instance.wsPath.TrimStart('/').TrimEnd('/')}"; - } - - /// - /// 버전이 포함된 WebSocket URL - /// - public static string GetWebSocketUrlWithVersion() - { - var baseUrl = WebSocketServerAddress; - return $"{baseUrl.TrimEnd('/')}/api/{Instance.apiVersion.TrimStart('/').TrimEnd('/')}/{Instance.wsPath.TrimStart('/').TrimEnd('/')}"; - } - - /// - /// 세션이 포함된 WebSocket URL - /// - public static string GetWebSocketUrlWithSession(string sessionId) - { - var baseWsUrl = GetWebSocketUrlWithVersion(); - return $"{baseWsUrl}?sessionId={sessionId}"; - } - - - /// - /// 개발 환경 설정 - /// - public static void SetDevelopmentEnvironment() - { - if (Application.isPlaying) - { - Debug.LogWarning("런타임 중에는 환경 설정을 변경할 수 없습니다."); - return; - } - - Instance.environment = EnvironmentType.Development; - } - - /// - /// 테스트 환경 설정 - /// - public static void SetTestEnvironment() - { - if (Application.isPlaying) - { - Debug.LogWarning("런타임 중에는 환경 설정을 변경할 수 없습니다."); - return; - } - - Instance.environment = EnvironmentType.Test; - } - - /// - /// 프로덕션 환경 설정 - /// - public static void SetProductionEnvironment() - { - if (Application.isPlaying) - { - Debug.LogWarning("런타임 중에는 환경 설정을 변경할 수 없습니다."); - return; - } - - Instance.environment = EnvironmentType.Production; - } - - /// - /// 현재 설정 로그 출력 - /// - public static void LogCurrentSettings() - { - Debug.Log($"=== NetworkConfig 현재 설정 ==="); - Debug.Log($"환경: {CurrentEnvironment}"); - Debug.Log($"HTTP 서버: {HttpServerAddress}"); - Debug.Log($"WebSocket 서버: {WebSocketServerAddress}"); - Debug.Log($"API 버전: {ApiVersion}"); - Debug.Log($"HTTP 타임아웃: {HttpTimeout}s"); - Debug.Log($"WebSocket 타임아웃: {WebSocketTimeout}s"); - Debug.Log($"자동 재연결: {AutoReconnect}"); - Debug.Log($"하트비트: {EnableHeartbeat} ({HeartbeatInterval}s)"); - Debug.Log($"================================"); - } - - #endregion - - #region Private Methods - - /// - /// 기본 인스턴스 생성 (Resources 폴더에 파일이 없을 때) - /// - private static NetworkConfig CreateDefaultInstance() - { - var instance = CreateInstance(); - - // 기본 설정 - instance.environment = EnvironmentType.Development; - instance.developmentServer = "localhost:7900"; - instance.testServer = "localhost:7900"; - instance.productionServer = "122.153.130.223:7900"; - instance.apiVersion = "v1"; - instance.apiPath = "api"; - instance.httpTimeout = 30f; - instance.maxRetryCount = 3; - instance.retryDelay = 1f; - instance.wsPath = "ws"; - instance.wsTimeout = 30f; - instance.reconnectDelay = 5f; - instance.maxReconnectAttempts = 3; - instance.autoReconnect = true; - instance.heartbeatInterval = 30f; - instance.enableHeartbeat = true; - instance.maxMessageSize = 65536; - instance.messageTimeout = 10f; - instance.enableMessageLogging = true; - instance.userAgent = "ProjectVG-Client/1.0"; - instance.contentType = "application/json"; - - Debug.LogWarning("기본 NetworkConfig를 생성했습니다. Resources 폴더에 NetworkConfig.asset 파일을 생성하는 것을 권장합니다."); - - return instance; - } - - #endregion - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Configs/NetworkConfig.cs.meta b/Assets/Infrastructure/Network/Configs/NetworkConfig.cs.meta deleted file mode 100644 index 233db0c..0000000 --- a/Assets/Infrastructure/Network/Configs/NetworkConfig.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 86f34d98107a627428323909bc15f04d \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Configs/ServerConfig.cs b/Assets/Infrastructure/Network/Configs/ServerConfig.cs deleted file mode 100644 index 8ea77ca..0000000 --- a/Assets/Infrastructure/Network/Configs/ServerConfig.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace ProjectVG.Infrastructure.Network.Configs -{ - /// - /// 서버 설정 정보 (현재 미사용) - /// 서버의 메시지 형식과 지원 기능을 정의합니다. - /// WebSocket뿐만 아니라 다른 서버 설정도 포함할 수 있습니다. - /// - [System.Serializable] - public class ServerConfig - { - /// - /// 메시지 타입 ("json" 또는 "binary") - /// - public string messageType; - - /// - /// 서버 버전 - /// - public string version; - - /// - /// 오디오 지원 여부 - /// - public bool supportsAudio; - - /// - /// 바이너리 메시지 지원 여부 - /// - public bool supportsBinary; - - /// - /// 오디오 형식 (예: "wav", "mp3") - /// - public string audioFormat; - - /// - /// 최대 메시지 크기 (바이트) - /// - public int maxMessageSize; - - /// - /// JSON 형식인지 확인 - /// - public bool IsJsonFormat => messageType?.ToLower() == "json"; - - /// - /// 바이너리 형식인지 확인 - /// - public bool IsBinaryFormat => messageType?.ToLower() == "binary"; - - /// - /// 설정 정보를 문자열로 반환 - /// - public override string ToString() - { - return $"ServerConfig[Type: {messageType}, Version: {version}, Audio: {supportsAudio}, Binary: {supportsBinary}, Format: {audioFormat}, MaxSize: {maxMessageSize} bytes]"; - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Configs/ServerConfig.cs.meta b/Assets/Infrastructure/Network/Configs/ServerConfig.cs.meta deleted file mode 100644 index d2afddc..0000000 --- a/Assets/Infrastructure/Network/Configs/ServerConfig.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: aed6fafe9b2afc74c800a2a8ba99570a \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs b/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs deleted file mode 100644 index d5a07db..0000000 --- a/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using UnityEngine; -using UnityEngine.Networking; -using Cysharp.Threading.Tasks; -using ProjectVG.Infrastructure.Network.Configs; - -namespace ProjectVG.Infrastructure.Network.Configs -{ - /// - /// 서버 설정 로더 (현재 미사용) - /// 서버에서 메시지 타입 등의 설정을 동적으로 로드합니다. - /// WebSocket뿐만 아니라 다른 서버 설정도 로드할 수 있습니다. - /// - public static class ServerConfigLoader - { - /// - /// 서버 설정 로드 - /// - /// 설정 엔드포인트 (기본값: "config") - /// 서버 설정 또는 null - public static async UniTask LoadServerConfigAsync(string configEndpoint = "config") - { - try - { - Debug.Log($"서버 설정 로드 중... (엔드포인트: {configEndpoint})"); - - var configUrl = NetworkConfig.GetFullApiUrl(configEndpoint); - using (var request = UnityWebRequest.Get(configUrl)) - { - request.timeout = 10; - await request.SendWebRequest(); - - if (request.result == UnityWebRequest.Result.Success) - { - var jsonResponse = request.downloadHandler.text; - var serverConfig = JsonUtility.FromJson(jsonResponse); - - Debug.Log($"서버 설정 로드 완료: {serverConfig.messageType}"); - return serverConfig; - } - else - { - Debug.LogWarning($"서버 설정 로드 실패: {request.error}"); - return null; - } - } - } - catch (Exception ex) - { - Debug.LogError($"서버 설정 로드 중 오류: {ex.Message}"); - return null; - } - } - - /// - /// 서버 설정 유효성 검사 - /// - /// 서버 설정 - /// 유효한지 여부 - public static bool ValidateServerConfig(ServerConfig config) - { - if (config == null) - { - Debug.LogWarning("서버 설정이 null입니다."); - return false; - } - - if (string.IsNullOrEmpty(config.messageType)) - { - Debug.LogWarning("서버 설정에 메시지 타입이 없습니다."); - return false; - } - - var messageType = config.messageType.ToLower(); - if (messageType != "json" && messageType != "binary") - { - Debug.LogWarning($"지원하지 않는 메시지 타입: {config.messageType}"); - return false; - } - - Debug.Log($"서버 설정 유효성 검사 통과: {config.messageType}"); - return true; - } - - /// - /// 서버 설정과 NetworkConfig 비교 - /// - /// 서버 설정 - /// 일치하는지 여부 - public static bool CompareWithNetworkConfig(ServerConfig serverConfig) - { - if (serverConfig == null) return false; - - var networkConfigType = NetworkConfig.WebSocketMessageType.ToLower(); - var serverConfigType = serverConfig.messageType.ToLower(); - - var isMatch = networkConfigType == serverConfigType; - - if (!isMatch) - { - Debug.LogWarning($"NetworkConfig({networkConfigType})와 서버 설정({serverConfigType})이 일치하지 않습니다."); - } - else - { - Debug.Log($"NetworkConfig와 서버 설정이 일치합니다: {networkConfigType}"); - } - - return isMatch; - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs.meta b/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs.meta deleted file mode 100644 index c972348..0000000 --- a/Assets/Infrastructure/Network/Configs/ServerConfigLoader.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 709b436d429928c4c8da5256aad82347 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs.meta b/Assets/Infrastructure/Network/DTOs.meta deleted file mode 100644 index 08d2e6f..0000000 --- a/Assets/Infrastructure/Network/DTOs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 195135de6dfc91948b7c869169221d53 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs b/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs deleted file mode 100644 index cc8bb20..0000000 --- a/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; - -namespace ProjectVG.Infrastructure.Network.DTOs -{ - /// - /// API 응답의 기본 구조 - /// - [Serializable] - public class BaseApiResponse - { - public bool success; - public string message; - public long timestamp; - public string requestId; - } - - /// - /// 데이터를 포함하는 API 응답 - /// - [Serializable] - public class ApiResponse : BaseApiResponse - { - public T data; - } - - /// - /// 페이지네이션 정보 - /// - [Serializable] - public class PaginationInfo - { - public int page; - public int limit; - public int total; - public int totalPages; - public bool hasNext; - public bool hasPrev; - } - - /// - /// 페이지네이션된 API 응답 - /// - [Serializable] - public class PaginatedApiResponse : BaseApiResponse - { - public T[] data; - public PaginationInfo pagination; - } - - /// - /// 에러 응답 - /// - [Serializable] - public class ErrorResponse : BaseApiResponse - { - public string errorCode; - public string errorType; - public string[] details; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs.meta b/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs.meta deleted file mode 100644 index 7c3ecc0..0000000 --- a/Assets/Infrastructure/Network/DTOs/BaseApiResponse.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 359796341ec306b42b9219b5fff1feca \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character.meta b/Assets/Infrastructure/Network/DTOs/Character.meta deleted file mode 100644 index 1705825..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6c376144b261f82498097408eb9c393f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs b/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs deleted file mode 100644 index 3db5e85..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using UnityEngine; - -namespace ProjectVG.Infrastructure.Network.DTOs.Character -{ - /// - /// 캐릭터 정보 DTO - /// - [Serializable] - public class CharacterData - { - [SerializeField] public string id; - [SerializeField] public string name; - [SerializeField] public string description; - [SerializeField] public string role; - [SerializeField] public bool isActive; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs.meta b/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs.meta deleted file mode 100644 index 28feae1..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/CharacterInfo.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4442e4d5ae93e4f4aa37f85e1a2eef48 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs b/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs deleted file mode 100644 index 45375d8..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace ProjectVG.Infrastructure.Network.DTOs.Character -{ - /// - /// 캐릭터 생성 요청 DTO - /// - [Serializable] - public class CreateCharacterRequest - { - public string name; - public string description; - public string role; - public bool isActive = true; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs.meta b/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs.meta deleted file mode 100644 index 2cc318b..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/CreateCharacterRequest.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8934f22c6576c584c9a76cd0ca57a5fe \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs b/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs deleted file mode 100644 index 2cf7044..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace ProjectVG.Infrastructure.Network.DTOs.Character -{ - /// - /// 캐릭터 수정 요청 DTO - /// - [Serializable] - public class UpdateCharacterRequest - { - public string name; - public string description; - public string role; - public bool isActive; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs.meta b/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs.meta deleted file mode 100644 index 51be348..0000000 --- a/Assets/Infrastructure/Network/DTOs/Character/UpdateCharacterRequest.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 88a11fb1cb2ce8f46a6fd6df981f1854 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Chat.meta b/Assets/Infrastructure/Network/DTOs/Chat.meta deleted file mode 100644 index 733db01..0000000 --- a/Assets/Infrastructure/Network/DTOs/Chat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 45b3af16b93a1e44399f346aed069e31 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs b/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs deleted file mode 100644 index 247f357..0000000 --- a/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using UnityEngine; -using Newtonsoft.Json; - -namespace ProjectVG.Infrastructure.Network.DTOs.Chat -{ - /// - /// 채팅 요청 DTO (Newtonsoft.Json을 사용하여 snake_case 지원) - /// - [Serializable] - public class ChatRequest - { - [JsonProperty("session_id")] - [SerializeField] public string sessionId; - - [JsonProperty("message")] - [SerializeField] public string message; - - [JsonProperty("character_id")] - [SerializeField] public string characterId; - - [JsonProperty("user_id")] - [SerializeField] public string userId; - - [JsonProperty("action")] - [SerializeField] public string action = "chat"; - - [JsonProperty("actor")] - [SerializeField] public string actor; - - [JsonProperty("instruction")] - [SerializeField] public string instruction; - - [JsonProperty("requested_at")] - [SerializeField] public string requestedAt; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs.meta b/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs.meta deleted file mode 100644 index 48b9b22..0000000 --- a/Assets/Infrastructure/Network/DTOs/Chat/ChatRequest.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 508dce3896fd1a24dbb39ec613bac2df \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs b/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs deleted file mode 100644 index 609dafb..0000000 --- a/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace ProjectVG.Infrastructure.Network.DTOs.Chat -{ - /// - /// 채팅 응답 DTO - /// - [Serializable] - public class ChatResponse - { - public bool success; - public string message; - public string sessionId; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs.meta b/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs.meta deleted file mode 100644 index 956fddd..0000000 --- a/Assets/Infrastructure/Network/DTOs/Chat/ChatResponse.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f55f8bd1f455ad54caaea20c4fc09253 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/DTOs/WebSocket.meta b/Assets/Infrastructure/Network/DTOs/WebSocket.meta deleted file mode 100644 index 461d67b..0000000 --- a/Assets/Infrastructure/Network/DTOs/WebSocket.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 96cf5f40d2d8aab478c179145464c91b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/Http.meta b/Assets/Infrastructure/Network/Http.meta deleted file mode 100644 index e5bdd72..0000000 --- a/Assets/Infrastructure/Network/Http.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a27aa8428fdf0974990bab2179bf081f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/Http/HttpApiClient.cs b/Assets/Infrastructure/Network/Http/HttpApiClient.cs deleted file mode 100644 index 9983bfa..0000000 --- a/Assets/Infrastructure/Network/Http/HttpApiClient.cs +++ /dev/null @@ -1,386 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using UnityEngine; -using UnityEngine.Networking; -using Cysharp.Threading.Tasks; -using System.Threading; -using ProjectVG.Infrastructure.Network.Configs; -using Newtonsoft.Json; - -namespace ProjectVG.Infrastructure.Network.Http -{ - /// - /// HTTP API 클라이언트 - /// UnityWebRequest를 사용하여 서버와 통신하며, UniTask 기반 비동기 처리를 지원합니다. - /// - public class HttpApiClient : MonoBehaviour - { - [Header("API Configuration")] - // NetworkConfig를 사용하여 설정을 관리합니다. - - private const string ACCEPT_HEADER = "application/json"; - private const string AUTHORIZATION_HEADER = "Authorization"; - private const string BEARER_PREFIX = "Bearer "; - - private readonly Dictionary defaultHeaders = new Dictionary(); - private CancellationTokenSource cancellationTokenSource; - - public static HttpApiClient Instance { get; private set; } - - #region Unity Lifecycle - - private void Awake() - { - InitializeSingleton(); - } - - private void OnDestroy() - { - Cleanup(); - } - - #endregion - - #region Public API - - - - public void AddDefaultHeader(string key, string value) - { - defaultHeaders[key] = value; - } - - public void SetAuthToken(string token) - { - AddDefaultHeader(AUTHORIZATION_HEADER, $"{BEARER_PREFIX}{token}"); - } - - public async UniTask GetAsync(string endpoint, Dictionary headers = null, CancellationToken cancellationToken = default) - { - var url = GetFullUrl(endpoint); - return await SendRequestAsync(url, UnityWebRequest.kHttpVerbGET, null, headers, cancellationToken); - } - - public async UniTask PostAsync(string endpoint, object data = null, Dictionary headers = null, CancellationToken cancellationToken = default) - { - var url = GetFullUrl(endpoint); - var jsonData = SerializeData(data); - LogRequestDetails("POST", url, jsonData); - return await SendRequestAsync(url, UnityWebRequest.kHttpVerbPOST, jsonData, headers, cancellationToken); - } - - public async UniTask PutAsync(string endpoint, object data = null, Dictionary headers = null, CancellationToken cancellationToken = default) - { - var url = GetFullUrl(endpoint); - var jsonData = SerializeData(data); - return await SendRequestAsync(url, UnityWebRequest.kHttpVerbPUT, jsonData, headers, cancellationToken); - } - - public async UniTask DeleteAsync(string endpoint, Dictionary headers = null, CancellationToken cancellationToken = default) - { - var url = GetFullUrl(endpoint); - return await SendRequestAsync(url, UnityWebRequest.kHttpVerbDELETE, null, headers, cancellationToken); - } - - public async UniTask UploadFileAsync(string endpoint, byte[] fileData, string fileName, string fieldName = "file", Dictionary headers = null, CancellationToken cancellationToken = default) - { - var url = GetFullUrl(endpoint); - return await SendFileRequestAsync(url, fileData, fileName, fieldName, headers, cancellationToken); - } - - public void Shutdown() - { - cancellationTokenSource?.Cancel(); - } - - #endregion - - #region Private Methods - - private void InitializeSingleton() - { - if (Instance == null) - { - Instance = this; - DontDestroyOnLoad(gameObject); - InitializeClient(); - } - else - { - Destroy(gameObject); - } - } - - private void InitializeClient() - { - cancellationTokenSource = new CancellationTokenSource(); - ApplyNetworkConfig(); - SetupDefaultHeaders(); - } - - private void ApplyNetworkConfig() - { - Debug.Log($"NetworkConfig 적용: {NetworkConfig.CurrentEnvironment} 환경"); - } - - private void SetupDefaultHeaders() - { - defaultHeaders.Clear(); - defaultHeaders["Content-Type"] = NetworkConfig.ContentType; - defaultHeaders["User-Agent"] = NetworkConfig.UserAgent; - defaultHeaders["Accept"] = ACCEPT_HEADER; - } - - private string GetFullUrl(string endpoint) - { - return NetworkConfig.GetFullApiUrl(endpoint); - } - - private string SerializeData(object data) - { - return data != null ? JsonConvert.SerializeObject(data) : null; - } - - private void LogRequestDetails(string method, string url, string jsonData) - { - Debug.Log($"HTTP {method} 요청 URL: {url}"); - if (!string.IsNullOrEmpty(jsonData)) - { - Debug.Log($"HTTP 요청 데이터: {jsonData}"); - } - } - - private async UniTask SendRequestAsync(string url, string method, string jsonData, Dictionary headers, CancellationToken cancellationToken) - { - var combinedCancellationToken = CreateCombinedCancellationToken(cancellationToken); - - Debug.Log($"HTTP 요청 시작: {method} {url}"); - if (!string.IsNullOrEmpty(jsonData)) - { - Debug.Log($"HTTP 요청 데이터: {jsonData}"); - } - - for (int attempt = 0; attempt <= NetworkConfig.MaxRetryCount; attempt++) - { - try - { - using var request = CreateRequest(url, method, jsonData, headers); - - Debug.Log($"HTTP 요청 전송 중... (시도 {attempt + 1}/{NetworkConfig.MaxRetryCount + 1})"); - var operation = request.SendWebRequest(); - await operation.WithCancellation(combinedCancellationToken); - - if (request.result == UnityWebRequest.Result.Success) - { - Debug.Log($"HTTP 요청 성공: {request.responseCode}"); - return ParseResponse(request); - } - else - { - await HandleRequestFailure(request, attempt, combinedCancellationToken); - } - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) when (ex is not ApiException) - { - await HandleRequestException(ex, attempt, combinedCancellationToken); - } - } - - throw new ApiException($"{NetworkConfig.MaxRetryCount + 1}번 시도 후 요청 실패", 0, "최대 재시도 횟수 초과"); - } - - private async UniTask SendFileRequestAsync(string url, byte[] fileData, string fileName, string fieldName, Dictionary headers, CancellationToken cancellationToken) - { - var combinedCancellationToken = CreateCombinedCancellationToken(cancellationToken); - - for (int attempt = 0; attempt <= NetworkConfig.MaxRetryCount; attempt++) - { - try - { - var form = new WWWForm(); - form.AddBinaryData(fieldName, fileData, fileName); - - using var request = UnityWebRequest.Post(url, form); - SetupRequest(request, headers); - request.timeout = (int)NetworkConfig.HttpTimeout; - - var operation = request.SendWebRequest(); - await operation.WithCancellation(combinedCancellationToken); - - if (request.result == UnityWebRequest.Result.Success) - { - return ParseResponse(request); - } - else - { - await HandleFileUploadFailure(request, attempt, combinedCancellationToken); - } - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) when (ex is not ApiException) - { - await HandleFileUploadException(ex, attempt, combinedCancellationToken); - } - } - - throw new ApiException($"{NetworkConfig.MaxRetryCount + 1}번 시도 후 파일 업로드 실패", 0, "최대 재시도 횟수 초과"); - } - - private CancellationToken CreateCombinedCancellationToken(CancellationToken cancellationToken) - { - return CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancellationTokenSource.Token).Token; - } - - private async UniTask HandleRequestFailure(UnityWebRequest request, int attempt, CancellationToken cancellationToken) - { - var error = new ApiException(request.error, request.responseCode, request.downloadHandler?.text); - Debug.LogError($"HTTP 요청 실패: {request.result}, 상태코드: {request.responseCode}, 오류: {request.error}"); - - if (ShouldRetry(request.responseCode) && attempt < NetworkConfig.MaxRetryCount) - { - Debug.LogWarning($"API 요청 실패 (시도 {attempt + 1}/{NetworkConfig.MaxRetryCount + 1}): {error.Message}"); - await UniTask.Delay(TimeSpan.FromSeconds(NetworkConfig.RetryDelay * (attempt + 1)), cancellationToken: cancellationToken); - return; - } - - throw error; - } - - private async UniTask HandleRequestException(Exception ex, int attempt, CancellationToken cancellationToken) - { - if (attempt < NetworkConfig.MaxRetryCount) - { - Debug.LogWarning($"API 요청 예외 발생 (시도 {attempt + 1}/{NetworkConfig.MaxRetryCount + 1}): {ex.Message}"); - await UniTask.Delay(TimeSpan.FromSeconds(NetworkConfig.RetryDelay * (attempt + 1)), cancellationToken: cancellationToken); - return; - } - throw new ApiException($"{NetworkConfig.MaxRetryCount + 1}번 시도 후 요청 실패", 0, ex.Message); - } - - private async UniTask HandleFileUploadFailure(UnityWebRequest request, int attempt, CancellationToken cancellationToken) - { - var error = new ApiException(request.error, request.responseCode, request.downloadHandler?.text); - - if (ShouldRetry(request.responseCode) && attempt < NetworkConfig.MaxRetryCount) - { - Debug.LogWarning($"파일 업로드 실패 (시도 {attempt + 1}/{NetworkConfig.MaxRetryCount + 1}): {error.Message}"); - await UniTask.Delay(TimeSpan.FromSeconds(NetworkConfig.RetryDelay * (attempt + 1)), cancellationToken: cancellationToken); - return; - } - - throw error; - } - - private async UniTask HandleFileUploadException(Exception ex, int attempt, CancellationToken cancellationToken) - { - if (attempt < NetworkConfig.MaxRetryCount) - { - Debug.LogWarning($"파일 업로드 예외 발생 (시도 {attempt + 1}/{NetworkConfig.MaxRetryCount + 1}): {ex.Message}"); - await UniTask.Delay(TimeSpan.FromSeconds(NetworkConfig.RetryDelay * (attempt + 1)), cancellationToken: cancellationToken); - return; - } - throw new ApiException($"{NetworkConfig.MaxRetryCount + 1}번 시도 후 파일 업로드 실패", 0, ex.Message); - } - - private UnityWebRequest CreateRequest(string url, string method, string jsonData, Dictionary headers) - { - var request = new UnityWebRequest(url, method); - - if (!string.IsNullOrEmpty(jsonData)) - { - var bodyRaw = Encoding.UTF8.GetBytes(jsonData); - request.uploadHandler = new UploadHandlerRaw(bodyRaw); - } - - request.downloadHandler = new DownloadHandlerBuffer(); - SetupRequest(request, headers); - request.timeout = (int)NetworkConfig.HttpTimeout; - - return request; - } - - private void SetupRequest(UnityWebRequest request, Dictionary headers) - { - foreach (var header in defaultHeaders) - { - request.SetRequestHeader(header.Key, header.Value); - } - - if (headers != null) - { - foreach (var header in headers) - { - request.SetRequestHeader(header.Key, header.Value); - } - } - } - - private T ParseResponse(UnityWebRequest request) - { - var responseText = request.downloadHandler?.text; - - if (string.IsNullOrEmpty(responseText)) - { - return default(T); - } - - try - { - return JsonConvert.DeserializeObject(responseText); - } - catch (Exception ex) - { - return TryFallbackParse(responseText, request.responseCode, ex); - } - } - - private T TryFallbackParse(string responseText, long responseCode, Exception originalException) - { - try - { - return JsonUtility.FromJson(responseText); - } - catch (Exception fallbackEx) - { - throw new ApiException($"응답 파싱 실패: {originalException.Message} (폴백도 실패: {fallbackEx.Message})", responseCode, responseText); - } - } - - private bool ShouldRetry(long responseCode) - { - return responseCode >= 500 || responseCode == 429; - } - - private void Cleanup() - { - cancellationTokenSource?.Cancel(); - cancellationTokenSource?.Dispose(); - } - - #endregion - } - - /// - /// API 예외 클래스 - /// - public class ApiException : Exception - { - public long StatusCode { get; } - public string ResponseBody { get; } - - public ApiException(string message, long statusCode, string responseBody) - : base(message) - { - StatusCode = statusCode; - ResponseBody = responseBody; - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Http/HttpApiClient.cs.meta b/Assets/Infrastructure/Network/Http/HttpApiClient.cs.meta deleted file mode 100644 index 4ad71af..0000000 --- a/Assets/Infrastructure/Network/Http/HttpApiClient.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 00fbb8efd091db646bc0653b6295222f \ No newline at end of file diff --git a/Assets/Infrastructure/Network/README.md b/Assets/Infrastructure/Network/README.md deleted file mode 100644 index b546cf2..0000000 --- a/Assets/Infrastructure/Network/README.md +++ /dev/null @@ -1,269 +0,0 @@ -# ProjectVG Network Module - -Unity 클라이언트와 서버 간의 통신을 위한 네트워크 모듈입니다. -강제된 JSON 형식 `{type: "xxx", data: {...}}`을 사용합니다. - -## 📦 설치 - -### 1. UniTask 설치 -```json -// Packages/manifest.json -"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask" -``` - -### 2. 플랫폼별 WebSocket 구현 -플랫폼에 따라 최적화된 WebSocket 구현을 사용합니다. - -**플랫폼별 구현:** -- 🟩 Desktop: System.Net.WebSockets.ClientWebSocket -- 🟩 WebGL: UnityWebRequest.WebSocket -- 🟩 Mobile: 네이티브 WebSocket 라이브러리 - -## 🏗️ 구조 - -``` -Assets/Infrastructure/Network/ -├── Configs/ # 설정 파일들 -│ └── NetworkConfig.cs # Unity 표준 ScriptableObject 기반 설정 -├── DTOs/ # 데이터 전송 객체들 -│ ├── BaseApiResponse.cs # 기본 API 응답 -│ ├── Chat/ # 채팅 관련 DTO -│ └── Character/ # 캐릭터 관련 DTO -├── Http/ # HTTP 클라이언트 -│ └── HttpApiClient.cs # HTTP API 클라이언트 -├── Services/ # API 서비스들 -│ ├── ApiServiceManager.cs # API 서비스 매니저 -│ ├── ChatApiService.cs # 채팅 API 서비스 -│ └── CharacterApiService.cs # 캐릭터 API 서비스 -└── WebSocket/ # WebSocket 관련 - ├── WebSocketManager.cs # WebSocket 매니저 (단순화됨) - ├── WebSocketFactory.cs # 플랫폼별 WebSocket 팩토리 - ├── INativeWebSocket.cs # 플랫폼별 WebSocket 인터페이스 - └── Platforms/ # 플랫폼별 WebSocket 구현 - ├── DesktopWebSocket.cs # 데스크톱용 (.NET ClientWebSocket) - ├── WebGLWebSocket.cs # WebGL용 (UnityWebRequest) - └── MobileWebSocket.cs # 모바일용 (네이티브 라이브러리) -``` - -## 🚀 사용법 - -### 1. Unity 표준 ScriptableObject 기반 설정 관리 - -#### 설정 파일 생성 -```csharp -// Unity Editor에서 ScriptableObject 생성 -// Assets/Infrastructure/Network/Configs/ 폴더에서 우클릭 -// Create > ProjectVG > Network > NetworkConfig -// Resources 폴더에 NetworkConfig.asset 파일 생성 -``` - -#### 앱 시작 시 환경 설정 -```csharp -// 앱 시작 시 (Editor에서만 가능) -NetworkConfig.SetDevelopmentEnvironment(); // localhost:7900 -NetworkConfig.SetTestEnvironment(); // localhost:7900 -NetworkConfig.SetProductionEnvironment(); // 122.153.130.223:7900 -``` - -#### 런타임 중 설정 사용 -```csharp -// 어디서든 동일한 설정 접근 (강제로 NetworkConfig 사용) -var currentEnv = NetworkConfig.CurrentEnvironment; -var apiUrl = NetworkConfig.GetFullApiUrl("chat"); -var wsUrl = NetworkConfig.GetWebSocketUrl(); - -// API URL 생성 -var userUrl = NetworkConfig.GetUserApiUrl(); -var characterUrl = NetworkConfig.GetCharacterApiUrl(); -var conversationUrl = NetworkConfig.GetConversationApiUrl(); -var authUrl = NetworkConfig.GetAuthApiUrl(); - -// WebSocket URL 생성 -var wsUrl = NetworkConfig.GetWebSocketUrl(); -var wsUrlWithVersion = NetworkConfig.GetWebSocketUrlWithVersion(); -var wsUrlWithSession = NetworkConfig.GetWebSocketUrlWithSession("session-123"); -``` - -### 2. WebSocket 사용 (단순화됨) - -#### 기본 사용법 -```csharp -// WebSocket 매니저 사용 -var wsManager = WebSocketManager.Instance; - -// 이벤트 구독 -wsManager.OnConnected += () => Debug.Log("연결됨"); -wsManager.OnDisconnected += () => Debug.Log("연결 해제됨"); -wsManager.OnError += (error) => Debug.LogError($"오류: {error}"); -wsManager.OnSessionIdReceived += (sessionId) => Debug.Log($"세션 ID: {sessionId}"); -wsManager.OnChatMessageReceived += (message) => Debug.Log($"채팅: {message}"); - -// 연결 -await wsManager.ConnectAsync(); - -// 메시지 전송 -await wsManager.SendChatMessageAsync("안녕하세요!"); - -// 연결 해제 -await wsManager.DisconnectAsync(); -``` - -#### 강제된 JSON 형식 사용 -```csharp -// 메시지 전송 (강제된 형식) -await wsManager.SendMessageAsync("chat", new ChatData -{ - message = "안녕하세요!", - sessionId = "session-123", - timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() -}); - -// 서버에서 받는 메시지 형식 -// { -// "type": "session_id", -// "data": { -// "session_id": "session_123456789" -// } -// } -// -// { -// "type": "chat", -// "data": { -// "message": "안녕하세요!", -// "sessionId": "session-123", -// "timestamp": 1703123456789 -// } -// } -``` - -### 3. HTTP API 사용 - -#### API 서비스 매니저 사용 -```csharp -// API 서비스 매니저 사용 -var apiManager = ApiServiceManager.Instance; - -// 채팅 API 사용 -var chatResponse = await apiManager.Chat.SendChatAsync( - new ChatRequest - { - message = "안녕하세요!", - characterId = "char-456", - userId = "user-789", - sessionId = "session-123" - } -); - -// 캐릭터 API 사용 -var character = await apiManager.Character.GetCharacterAsync("char-456"); -``` - -### 4. 전체 흐름 테스트 (권장) -```csharp -// NetworkTestManager 사용 -var testManager = FindObjectOfType(); - -// 1. WebSocket 연결 -await testManager.ConnectWebSocket(); - -// 2. HTTP 요청 전송 -await testManager.SendChatRequest(); - -// 3. WebSocket으로 결과 수신 (자동) -// 서버가 비동기 작업 완료 후 WebSocket으로 결과 전송 -``` - -## ⚙️ 설정 - -### Unity 표준 ScriptableObject 설정 관리 - -#### 1. 설정 파일 생성 -1. **NetworkConfig.asset** 생성: - - `Assets/Resources/` 폴더에 `NetworkConfig.asset` 파일 생성 - - Unity Editor에서 우클릭 > Create > ProjectVG > Network > NetworkConfig - -#### 2. 환경별 서버 주소 -- **개발 환경**: `localhost:7900` -- **테스트 환경**: `localhost:7900` -- **프로덕션 환경**: `122.153.130.223:7900` - -#### 3. 설정값들 (Editor에서 설정 가능) -- **HTTP 타임아웃**: 30초 -- **최대 재시도**: 3회 -- **WebSocket 타임아웃**: 30초 -- **자동 재연결**: 활성화 -- **하트비트**: 활성화 (30초 간격) - -#### 4. 런타임 보안 -- ✅ 앱 시작 시 한 번 설정 -- ✅ 런타임 중 설정 변경 불가 -- ✅ 어디서든 동일한 설정 접근 -- ✅ ScriptableObject로 일관성 보장 -- ✅ Editor에서 설정 가능 -- ✅ 팀 협업 용이 -- ✅ NetworkConfig 강제 사용으로 일관성 보장 - -## 🔧 플랫폼별 WebSocket 구현 - -### 1. DesktopWebSocket (데스크톱) -- System.Net.WebSockets.ClientWebSocket 사용 -- Windows/Mac/Linux 지원 -- 최고 성능 -- JSON 메시지만 처리 - -### 2. WebGLWebSocket (브라우저) -- UnityWebRequest.WebSocket 사용 -- WebGL 플랫폼 지원 -- 브라우저 제약사항 대응 -- JSON 메시지만 처리 - -### 3. MobileWebSocket (모바일) -- 네이티브 WebSocket 라이브러리 사용 -- iOS/Android 지원 -- 네이티브 성능 -- JSON 메시지만 처리 - -### 4. WebSocketFactory -- 플랫폼별 WebSocket 구현 생성 -- 컴파일 타임에 적절한 구현체 선택 - -## 🐛 문제 해결 - -### 플랫폼별 WebSocket -``` -데스크톱 플랫폼용 WebSocket 생성 -WebSocket 연결 시도: ws://localhost:7900/ws -WebSocket 연결 성공 -``` -**설명:** 플랫폼에 따라 적절한 WebSocket 구현체가 자동으로 선택됩니다. - -### 플랫폼별 특징 -- **Desktop**: .NET ClientWebSocket으로 최고 성능 -- **WebGL**: 브라우저 WebSocket API 사용 -- **Mobile**: 네이티브 라이브러리로 최적화 - -### 테스트 실행 방법 -1. **NetworkTestManager** 컴포넌트를 씬에 추가 -2. **Context Menu**에서 테스트 실행: - - `1. WebSocket 연결` - - `2. HTTP 채팅 요청` - - `3. HTTP 캐릭터 정보 요청` - - `4. WebSocket 메시지 전송` - - `5. WebSocket 연결 해제` - - `전체 테스트 실행` - -## 📝 로그 - -모든 로그는 한국어로 출력됩니다: -- `Debug.Log("WebSocket 연결 성공")` -- `Debug.LogError("연결 실패")` -- `Debug.LogWarning("재연결 시도")` - -## 🔄 변경 사항 - -### 주요 변경사항 (v2.0) -1. **바이너리 방식 완전 제거**: JSON 메시지만 처리 -2. **강제된 JSON 형식**: `{type: "xxx", data: {...}}` 형식 사용 -3. **MessageRouter 제거**: WebSocketManager에서 직접 처리 -4. **단순화된 구조**: 불필요한 복잡성 제거 -5. **확장 가능한 설계**: 추후 기능 추가 용이 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/README.md.meta b/Assets/Infrastructure/Network/README.md.meta deleted file mode 100644 index 6d02e29..0000000 --- a/Assets/Infrastructure/Network/README.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4ceeee07406643741bb8b3a1e83f927f -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/Services.meta b/Assets/Infrastructure/Network/Services.meta deleted file mode 100644 index c4ba0b4..0000000 --- a/Assets/Infrastructure/Network/Services.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f9bc83dcef956db4784a7336ee77e17b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/Services/ApiServiceManager.cs b/Assets/Infrastructure/Network/Services/ApiServiceManager.cs deleted file mode 100644 index 08f14da..0000000 --- a/Assets/Infrastructure/Network/Services/ApiServiceManager.cs +++ /dev/null @@ -1,72 +0,0 @@ -using UnityEngine; - -namespace ProjectVG.Infrastructure.Network.Services -{ - /// - /// API 서비스 매니저 - /// 모든 API 서비스의 중앙 관리자 - /// - public class ApiServiceManager : MonoBehaviour - { - private static ApiServiceManager _instance; - public static ApiServiceManager Instance - { - get - { - if (_instance == null) - { - _instance = FindFirstObjectByType(); - if (_instance == null) - { - GameObject go = new GameObject("ApiServiceManager"); - _instance = go.AddComponent(); - DontDestroyOnLoad(go); - } - } - return _instance; - } - } - - // API 서비스 인스턴스들 - private ChatApiService _chatService; - private CharacterApiService _characterService; - - // 프로퍼티로 서비스 접근 - public ChatApiService Chat => _chatService ??= new ChatApiService(); - public CharacterApiService Character => _characterService ??= new CharacterApiService(); - - private void Awake() - { - if (_instance == null) - { - _instance = this; - DontDestroyOnLoad(gameObject); - InitializeServices(); - } - else if (_instance != this) - { - Destroy(gameObject); - } - } - - private void InitializeServices() - { - // 서비스 초기화 - _chatService = new ChatApiService(); - _characterService = new CharacterApiService(); - - Debug.Log("API 서비스 매니저 초기화 완료"); - } - - /// - /// 모든 서비스 재초기화 - /// - public void ReinitializeServices() - { - _chatService = new ChatApiService(); - _characterService = new CharacterApiService(); - - Debug.Log("API 서비스 재초기화 완료"); - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Services/ApiServiceManager.cs.meta b/Assets/Infrastructure/Network/Services/ApiServiceManager.cs.meta deleted file mode 100644 index fe19897..0000000 --- a/Assets/Infrastructure/Network/Services/ApiServiceManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: bc3a1165acfed50488abb14eb8dbc022 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Services/CharacterApiService.cs b/Assets/Infrastructure/Network/Services/CharacterApiService.cs deleted file mode 100644 index 2e9205d..0000000 --- a/Assets/Infrastructure/Network/Services/CharacterApiService.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; -using ProjectVG.Infrastructure.Network.Http; -using ProjectVG.Infrastructure.Network.DTOs.Character; - -namespace ProjectVG.Infrastructure.Network.Services -{ - /// - /// 캐릭터 API 서비스 - /// - public class CharacterApiService - { - private readonly HttpApiClient _httpClient; - - public CharacterApiService() - { - _httpClient = HttpApiClient.Instance; - if (_httpClient == null) - { - Debug.LogError("HttpApiClient.Instance가 null입니다. HttpApiClient가 생성되지 않았습니다."); - } - } - - /// - /// 모든 캐릭터 목록 조회 - /// - /// 취소 토큰 - /// 캐릭터 목록 - public async UniTask GetAllCharactersAsync(CancellationToken cancellationToken = default) - { - if (_httpClient == null) - { - Debug.LogError("HttpApiClient가 null입니다. 초기화를 확인해주세요."); - return null; - } - - return await _httpClient.GetAsync("character", cancellationToken: cancellationToken); - } - - /// - /// 특정 캐릭터 정보 조회 - /// - /// 캐릭터 ID - /// 취소 토큰 - /// 캐릭터 정보 - public async UniTask GetCharacterAsync(string characterId, CancellationToken cancellationToken = default) - { - if (_httpClient == null) - { - Debug.LogError("HttpApiClient가 null입니다. 초기화를 확인해주세요."); - return null; - } - - return await _httpClient.GetAsync($"character/{characterId}", cancellationToken: cancellationToken); - } - - /// - /// 캐릭터 생성 - /// - /// 캐릭터 생성 요청 - /// 취소 토큰 - /// 생성된 캐릭터 정보 - public async UniTask CreateCharacterAsync(CreateCharacterRequest request, CancellationToken cancellationToken = default) - { - return await _httpClient.PostAsync("character", request, cancellationToken: cancellationToken); - } - - /// - /// 간편한 캐릭터 생성 - /// - /// 캐릭터 이름 - /// 캐릭터 설명 - /// 캐릭터 역할 - /// 활성화 여부 - /// 취소 토큰 - /// 생성된 캐릭터 정보 - public async UniTask CreateCharacterAsync( - string name, - string description, - string role, - bool isActive = true, - CancellationToken cancellationToken = default) - { - var request = new CreateCharacterRequest - { - name = name, - description = description, - role = role, - isActive = isActive - }; - - return await CreateCharacterAsync(request, cancellationToken); - } - - /// - /// 캐릭터 정보 수정 - /// - /// 캐릭터 ID - /// 수정 요청 - /// 취소 토큰 - /// 수정된 캐릭터 정보 - public async UniTask UpdateCharacterAsync(string characterId, UpdateCharacterRequest request, CancellationToken cancellationToken = default) - { - return await _httpClient.PutAsync($"character/{characterId}", request, cancellationToken: cancellationToken); - } - - /// - /// 간편한 캐릭터 수정 - /// - /// 캐릭터 ID - /// 캐릭터 이름 - /// 캐릭터 설명 - /// 캐릭터 역할 - /// 활성화 여부 - /// 취소 토큰 - /// 수정된 캐릭터 정보 - public async UniTask UpdateCharacterAsync( - string characterId, - string name = null, - string description = null, - string role = null, - bool? isActive = null, - CancellationToken cancellationToken = default) - { - var request = new UpdateCharacterRequest(); - - if (name != null) request.name = name; - if (description != null) request.description = description; - if (role != null) request.role = role; - if (isActive.HasValue) request.isActive = isActive.Value; - - return await UpdateCharacterAsync(characterId, request, cancellationToken); - } - - /// - /// 캐릭터 삭제 - /// - /// 캐릭터 ID - /// 취소 토큰 - /// 삭제 성공 여부 - public async UniTask DeleteCharacterAsync(string characterId, CancellationToken cancellationToken = default) - { - try - { - await _httpClient.DeleteAsync($"character/{characterId}", cancellationToken: cancellationToken); - return true; - } - catch - { - return false; - } - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Services/CharacterApiService.cs.meta b/Assets/Infrastructure/Network/Services/CharacterApiService.cs.meta deleted file mode 100644 index a985190..0000000 --- a/Assets/Infrastructure/Network/Services/CharacterApiService.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 2e505a265149b82478a22ae11d759ca6 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Services/ChatApiService.cs b/Assets/Infrastructure/Network/Services/ChatApiService.cs deleted file mode 100644 index f6ec055..0000000 --- a/Assets/Infrastructure/Network/Services/ChatApiService.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System; -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; -using ProjectVG.Infrastructure.Network.Http; -using ProjectVG.Infrastructure.Network.DTOs.Chat; -using Newtonsoft.Json; - -namespace ProjectVG.Infrastructure.Network.Services -{ - /// - /// 채팅 API 서비스 - /// - public class ChatApiService - { - private readonly HttpApiClient _httpClient; - private const string CHAT_ENDPOINT = "chat"; - private const string DEFAULT_ACTION = "chat"; - - public ChatApiService() - { - _httpClient = HttpApiClient.Instance; - ValidateHttpClient(); - } - - /// - /// 채팅 요청 전송 - /// - /// 채팅 요청 데이터 - /// 취소 토큰 - /// 채팅 응답 - public async UniTask SendChatAsync(ChatRequest request, CancellationToken cancellationToken = default) - { - ValidateRequest(request); - ValidateHttpClient(); - - var serverRequest = CreateServerRequest(request); - LogRequestDetails(serverRequest); - - return await _httpClient.PostAsync(CHAT_ENDPOINT, serverRequest, cancellationToken: cancellationToken); - } - - /// - /// 간편한 채팅 요청 (기본값 사용) - /// - /// 메시지 - /// 캐릭터 ID - /// 사용자 ID - /// 세션 ID (선택사항) - /// 액터 (선택사항) - /// 취소 토큰 - /// 채팅 응답 - public async UniTask SendChatAsync( - string message, - string characterId, - string userId, - string sessionId = null, - string actor = null, - CancellationToken cancellationToken = default) - { - var request = CreateSimpleRequest(message, characterId, userId, sessionId, actor); - return await SendChatAsync(request, cancellationToken); - } - - #region Private Methods - - private void ValidateHttpClient() - { - if (_httpClient == null) - { - throw new InvalidOperationException("HttpApiClient.Instance가 null입니다. HttpApiClient가 생성되지 않았습니다."); - } - } - - private void ValidateRequest(ChatRequest request) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request), "채팅 요청이 null입니다."); - } - - if (string.IsNullOrEmpty(request.message)) - { - throw new ArgumentException("메시지가 비어있습니다.", nameof(request.message)); - } - - if (string.IsNullOrEmpty(request.characterId)) - { - throw new ArgumentException("캐릭터 ID가 비어있습니다.", nameof(request.characterId)); - } - - if (string.IsNullOrEmpty(request.userId)) - { - throw new ArgumentException("사용자 ID가 비어있습니다.", nameof(request.userId)); - } - } - - private ChatRequest CreateServerRequest(ChatRequest originalRequest) - { - return new ChatRequest - { - sessionId = originalRequest.sessionId, - message = originalRequest.message, - characterId = originalRequest.characterId, - userId = originalRequest.userId, - action = originalRequest.action, - actor = originalRequest.actor, - instruction = originalRequest.instruction, - requestedAt = originalRequest.requestedAt - }; - } - - private ChatRequest CreateSimpleRequest(string message, string characterId, string userId, string sessionId, string actor) - { - return new ChatRequest - { - sessionId = sessionId, - message = message, - characterId = characterId, - userId = userId, - actor = actor, - action = DEFAULT_ACTION, - requestedAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") - }; - } - - private void LogRequestDetails(ChatRequest request) - { - Debug.Log($"채팅 요청 엔드포인트: {CHAT_ENDPOINT}"); - Debug.Log($"서버로 전송할 JSON: {JsonConvert.SerializeObject(request)}"); - } - - #endregion - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/Services/ChatApiService.cs.meta b/Assets/Infrastructure/Network/Services/ChatApiService.cs.meta deleted file mode 100644 index 5a73fce..0000000 --- a/Assets/Infrastructure/Network/Services/ChatApiService.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 0c581a111d7799c40b9d79a5887c988b \ No newline at end of file diff --git a/Assets/Infrastructure/Network/TestScene.meta b/Assets/Infrastructure/Network/TestScene.meta deleted file mode 100644 index 8558e6e..0000000 --- a/Assets/Infrastructure/Network/TestScene.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 153323d148c986941975059f33cfa79e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/UI.meta b/Assets/Infrastructure/Network/UI.meta deleted file mode 100644 index 194b70f..0000000 --- a/Assets/Infrastructure/Network/UI.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 191d3f4a282ef6545b6fde81cdd0b3d3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/WebSocket.meta b/Assets/Infrastructure/Network/WebSocket.meta deleted file mode 100644 index 27133f5..0000000 --- a/Assets/Infrastructure/Network/WebSocket.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b7243b76e275de847a176769c0af5e9e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/WebSocket/Handlers.meta b/Assets/Infrastructure/Network/WebSocket/Handlers.meta deleted file mode 100644 index 3e9543f..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Handlers.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 45c015a8db87cc9409bf35790fcb2470 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs b/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs deleted file mode 100644 index 12fd0d1..0000000 --- a/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Threading; -using Cysharp.Threading.Tasks; - -namespace ProjectVG.Infrastructure.Network.WebSocket -{ - /// - /// 플랫폼별 Native WebSocket 구현을 위한 인터페이스 - /// - public interface INativeWebSocket : IDisposable - { - // 연결 상태 - bool IsConnected { get; } - bool IsConnecting { get; } - - // 이벤트 - event Action OnConnected; - event Action OnDisconnected; - event Action OnError; - event Action OnMessageReceived; - - // 연결 관리 - UniTask ConnectAsync(string url, CancellationToken cancellationToken = default); - UniTask DisconnectAsync(); - - // 메시지 전송 - UniTask SendMessageAsync(string message, CancellationToken cancellationToken = default); - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs.meta b/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs.meta deleted file mode 100644 index dc687fe..0000000 --- a/Assets/Infrastructure/Network/WebSocket/INativeWebSocket.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 259c46c284a0b4e4e9fb9510200ccf0c \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms.meta b/Assets/Infrastructure/Network/WebSocket/Platforms.meta deleted file mode 100644 index 44c78e9..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4da30c2f4bafd614ca7d49bf3e3b9287 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs b/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs deleted file mode 100644 index 4c8bacf..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; -using System.Net.WebSockets; -using System.Text; -using System.Threading.Tasks; - -namespace ProjectVG.Infrastructure.Network.WebSocket.Platforms -{ - /// - /// 데스크톱 플랫폼용 WebSocket 구현체 - /// System.Net.WebSockets.ClientWebSocket을 사용합니다. - /// JSON 메시지만 처리합니다. - /// - public class DesktopWebSocket : INativeWebSocket - { - public bool IsConnected { get; private set; } - public bool IsConnecting { get; private set; } - - public event Action OnConnected; - public event Action OnDisconnected; - public event Action OnError; - public event Action OnMessageReceived; - - private ClientWebSocket _webSocket; - private CancellationTokenSource _cancellationTokenSource; - private bool _isDisposed = false; - - public DesktopWebSocket() - { - _webSocket = new ClientWebSocket(); - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async UniTask ConnectAsync(string url, CancellationToken cancellationToken = default) - { - if (IsConnected || IsConnecting) - { - return IsConnected; - } - - IsConnecting = true; - - try - { - var wsUrl = url.Replace("http://", "wss://").Replace("https://", "wss://"); - Debug.Log($"Desktop WebSocket 연결: {wsUrl}"); - - var combinedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token).Token; - - await _webSocket.ConnectAsync(new Uri(wsUrl), combinedCancellationToken); - - IsConnected = true; - IsConnecting = false; - OnConnected?.Invoke(); - - // 메시지 수신 루프 시작 - _ = ReceiveLoopAsync(); - - return true; - } - catch (Exception ex) - { - IsConnecting = false; - var error = $"Desktop WebSocket 연결 실패: {ex.Message}"; - Debug.LogError(error); - OnError?.Invoke(error); - return false; - } - } - - public async UniTask DisconnectAsync() - { - if (!IsConnected) - { - return; - } - - try - { - IsConnected = false; - IsConnecting = false; - - if (_webSocket.State == WebSocketState.Open) - { - await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client disconnect", CancellationToken.None); - } - - OnDisconnected?.Invoke(); - } - catch (Exception ex) - { - Debug.LogError($"Desktop WebSocket 연결 해제 중 오류: {ex.Message}"); - } - } - - public async UniTask SendMessageAsync(string message, CancellationToken cancellationToken = default) - { - if (!IsConnected || _webSocket.State != WebSocketState.Open) - { - Debug.LogWarning("Desktop WebSocket이 연결되지 않았습니다."); - return false; - } - - try - { - var buffer = Encoding.UTF8.GetBytes(message); - await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, cancellationToken); - return true; - } - catch (Exception ex) - { - Debug.LogError($"Desktop WebSocket 메시지 전송 실패: {ex.Message}"); - return false; - } - } - - private async Task ReceiveLoopAsync() - { - var buffer = new byte[4096]; - - try - { - while (IsConnected && _webSocket.State == WebSocketState.Open) - { - var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), _cancellationTokenSource.Token); - - if (result.MessageType == WebSocketMessageType.Close) - { - Debug.Log("Desktop WebSocket: 서버에서 연결 종료 요청"); - break; - } - else if (result.MessageType == WebSocketMessageType.Text) - { - var message = Encoding.UTF8.GetString(buffer, 0, result.Count); - OnMessageReceived?.Invoke(message); - } - else if (result.MessageType == WebSocketMessageType.Binary) - { - // 바이너리 메시지는 무시 (JSON만 처리) - Debug.LogWarning("Desktop WebSocket: 바이너리 메시지 수신됨 (무시됨)"); - } - } - } - catch (Exception ex) - { - if (!_isDisposed) - { - Debug.LogError($"Desktop WebSocket 수신 루프 오류: {ex.Message}"); - OnError?.Invoke(ex.Message); - } - } - finally - { - IsConnected = false; - if (!_isDisposed) - { - OnDisconnected?.Invoke(); - } - } - } - - public void Dispose() - { - if (_isDisposed) - return; - - _isDisposed = true; - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - _webSocket?.Dispose(); - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs.meta b/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs.meta deleted file mode 100644 index 8b9b5bd..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/DesktopWebSocket.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ecf4142f21c17ee48a6646dd7e267fec \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs b/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs deleted file mode 100644 index 7d94fad..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; - -namespace ProjectVG.Infrastructure.Network.WebSocket.Platforms -{ - /// - /// 모바일 플랫폼용 WebSocket 구현체 - /// iOS/Android 네이티브 WebSocket 라이브러리를 사용합니다. - /// - public class MobileWebSocket : INativeWebSocket - { - public bool IsConnected { get; private set; } - public bool IsConnecting { get; private set; } - - public event Action OnConnected; - public event Action OnDisconnected; - public event Action OnError; -#pragma warning disable CS0067 - public event Action OnMessageReceived; -#pragma warning restore CS0067 - - private CancellationTokenSource _cancellationTokenSource; - private bool _isDisposed = false; - - public MobileWebSocket() - { - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async UniTask ConnectAsync(string url, CancellationToken cancellationToken = default) - { - if (IsConnected || IsConnecting) - { - return IsConnected; - } - - IsConnecting = true; - - try - { - var combinedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token).Token; - - // TODO : 모바일에서는 네이티브 WebSocket 라이브러리 사용 - // TODO : 현재는 기본 구현만 제공 (실제 구현 시 네이티브 플러그인 필요) - - // TODO : 임시로 성공 시뮬레이션 - await UniTask.Delay(100, cancellationToken: combinedCancellationToken); - - IsConnected = true; - IsConnecting = false; - OnConnected?.Invoke(); - - // 메시지 수신 루프 시작 - _ = ReceiveLoopAsync(); - - return true; - } - catch (Exception ex) - { - IsConnecting = false; - var error = $"모바일 WebSocket 연결 중 예외 발생: {ex.Message}"; - Debug.LogError(error); - OnError?.Invoke(error); - return false; - } - } - - public async UniTask DisconnectAsync() - { - if (!IsConnected) - { - return; - } - - try - { - IsConnected = false; - IsConnecting = false; - - // TODO : 네이티브 WebSocket 연결 해제 - // TODO : 실제 구현 시 네이티브 플러그인 호출 - await UniTask.CompletedTask; - - OnDisconnected?.Invoke(); - } - catch (Exception ex) - { - Debug.LogError($"모바일 WebSocket 연결 해제 중 오류: {ex.Message}"); - } - } - - public async UniTask SendMessageAsync(string message, CancellationToken cancellationToken = default) - { - if (!IsConnected) - { - Debug.LogWarning("모바일 WebSocket이 연결되지 않았습니다."); - return false; - } - - try - { - // TODO : 네이티브 WebSocket 메시지 전송 - // TODO : 실제 구현 시 네이티브 플러그인 호출 - await UniTask.CompletedTask; - return true; - } - catch (Exception ex) - { - Debug.LogError($"모바일 WebSocket 메시지 전송 실패: {ex.Message}"); - return false; - } - } - - private async UniTask ReceiveLoopAsync() - { - try - { - while (IsConnected && !_isDisposed) - { - // TODO : 네이티브 WebSocket 메시지 수신 - // TODO : 실제 구현 시 네이티브 플러그인에서 메시지 수신 - await UniTask.Delay(100); - } - } - catch (Exception ex) - { - if (!_isDisposed) - { - Debug.LogError($"모바일 WebSocket 수신 루프 오류: {ex.Message}"); - OnError?.Invoke(ex.Message); - } - } - finally - { - IsConnected = false; - if (!_isDisposed) - { - OnDisconnected?.Invoke(); - } - } - } - - public void Dispose() - { - if (_isDisposed) - return; - - _isDisposed = true; - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs.meta b/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs.meta deleted file mode 100644 index de72dd6..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/MobileWebSocket.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 1150790d7959b3147b99271055b8e7ff \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs b/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs deleted file mode 100644 index 849911d..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; -using UnityEngine.Networking; - -namespace ProjectVG.Infrastructure.Network.WebSocket.Platforms -{ - /// - /// WebGL 플랫폼용 WebSocket 구현체 - /// UnityWebRequest.WebSocket을 사용합니다. - /// - public class WebGLWebSocket : INativeWebSocket - { - public bool IsConnected { get; private set; } - public bool IsConnecting { get; private set; } - - public event Action OnConnected; - public event Action OnDisconnected; - public event Action OnError; -#pragma warning disable CS0067 - public event Action OnMessageReceived; -#pragma warning restore CS0067 - - private UnityWebRequest _webRequest; - private CancellationTokenSource _cancellationTokenSource; - private bool _isDisposed = false; - - public WebGLWebSocket() - { - _cancellationTokenSource = new CancellationTokenSource(); - } - - public async UniTask ConnectAsync(string url, CancellationToken cancellationToken = default) - { - if (IsConnected || IsConnecting) - { - return IsConnected; - } - - IsConnecting = true; - - try - { - var combinedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token).Token; - - // UnityWebRequest.WebSocket 사용 - _webRequest = UnityWebRequest.Get(url); - _webRequest.SetRequestHeader("Upgrade", "websocket"); - _webRequest.SetRequestHeader("Connection", "Upgrade"); - - var operation = _webRequest.SendWebRequest(); - await operation.WithCancellation(combinedCancellationToken); - - if (_webRequest.result == UnityWebRequest.Result.Success) - { - IsConnected = true; - IsConnecting = false; - OnConnected?.Invoke(); - - // 메시지 수신 루프 시작 - _ = ReceiveLoopAsync(); - - return true; - } - else - { - var error = $"WebGL WebSocket 연결 실패: {_webRequest.error}"; - Debug.LogError(error); - OnError?.Invoke(error); - return false; - } - } - catch (Exception ex) - { - IsConnecting = false; - var error = $"WebGL WebSocket 연결 중 예외 발생: {ex.Message}"; - Debug.LogError(error); - OnError?.Invoke(error); - return false; - } - } - - public async UniTask DisconnectAsync() - { - if (!IsConnected) - { - return; - } - - try - { - IsConnected = false; - IsConnecting = false; - - _webRequest?.Abort(); - _webRequest?.Dispose(); - _webRequest = null; - - await UniTask.CompletedTask; // 비동기 작업 시뮬레이션 - - OnDisconnected?.Invoke(); - } - catch (Exception ex) - { - Debug.LogError($"WebGL WebSocket 연결 해제 중 오류: {ex.Message}"); - } - } - - public async UniTask SendMessageAsync(string message, CancellationToken cancellationToken = default) - { - if (!IsConnected) - { - Debug.LogWarning("WebGL WebSocket이 연결되지 않았습니다."); - return false; - } - - try - { - // TODO : WebGL에서는 WebSocket 메시지 전송을 위한 별도 구현 필요 - await UniTask.CompletedTask; - return true; - } - catch (Exception ex) - { - Debug.LogError($"WebGL WebSocket 메시지 전송 실패: {ex.Message}"); - return false; - } - } - - private async UniTask ReceiveLoopAsync() - { - try - { - while (IsConnected && !_isDisposed) - { - // TODO : WebGL에서는 WebSocket 메시지 수신을 위한 별도 구현 필요 - await UniTask.Delay(100); - } - } - catch (Exception ex) - { - if (!_isDisposed) - { - Debug.LogError($"WebGL WebSocket 수신 루프 오류: {ex.Message}"); - OnError?.Invoke(ex.Message); - } - } - finally - { - IsConnected = false; - if (!_isDisposed) - { - OnDisconnected?.Invoke(); - } - } - } - - public void Dispose() - { - if (_isDisposed) - return; - - _isDisposed = true; - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - _webRequest?.Dispose(); - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs.meta b/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs.meta deleted file mode 100644 index 3705f86..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Platforms/WebGLWebSocket.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 21c0c4d6a3b08134d975cd3c476a8dd6 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/Processors.meta b/Assets/Infrastructure/Network/WebSocket/Processors.meta deleted file mode 100644 index dd8cb27..0000000 --- a/Assets/Infrastructure/Network/WebSocket/Processors.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a0069f6496b3bf7468c732dd8bce79a1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs b/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs deleted file mode 100644 index fa186d5..0000000 --- a/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UnityEngine; -using ProjectVG.Infrastructure.Network.WebSocket.Platforms; - -namespace ProjectVG.Infrastructure.Network.WebSocket -{ - /// - /// 플랫폼별 WebSocket 구현을 생성하는 팩토리 - /// - public static class WebSocketFactory - { - /// - /// 현재 플랫폼에 맞는 WebSocket 구현을 생성합니다. - /// - public static INativeWebSocket Create() - { - #if UNITY_WEBGL && !UNITY_EDITOR - return new WebGLWebSocket(); - #elif UNITY_IOS || UNITY_ANDROID - return new MobileWebSocket(); - #else - return new DesktopWebSocket(); - #endif - } - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs.meta b/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs.meta deleted file mode 100644 index 6b9be90..0000000 --- a/Assets/Infrastructure/Network/WebSocket/WebSocketFactory.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 60c74fa19d97fbb46930ab87d63ab193 \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs b/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs deleted file mode 100644 index 6f5b1b7..0000000 --- a/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs +++ /dev/null @@ -1,482 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using UnityEngine; -using UnityEngine.Networking; -using Cysharp.Threading.Tasks; -using ProjectVG.Infrastructure.Network.Configs; - -namespace ProjectVG.Infrastructure.Network.WebSocket -{ - /// - /// WebSocket 연결 및 메시지 관리자 - /// 강제된 JSON 형식 {type: "xxx", data: {...}}을 사용합니다. - /// - public class WebSocketManager : MonoBehaviour - { - private INativeWebSocket _nativeWebSocket; - private CancellationTokenSource _cancellationTokenSource; - - // 메시지 버퍼링을 위한 필드 - private readonly StringBuilder _messageBuffer = new StringBuilder(); - private readonly object _bufferLock = new object(); - - private bool _isConnected = false; - private bool _isConnecting = false; - private int _reconnectAttempts = 0; - private string _sessionId; - - public static WebSocketManager Instance { get; private set; } - - // 이벤트 - public event Action OnConnected; - public event Action OnDisconnected; - public event Action OnError; - public event Action OnSessionIdReceived; - public event Action OnChatMessageReceived; - - public bool IsConnected => _isConnected; - public bool IsConnecting => _isConnecting; - public string SessionId => _sessionId; - - private void Awake() - { - if (Instance == null) - { - Instance = this; - DontDestroyOnLoad(gameObject); - InitializeManager(); - } - else - { - Destroy(gameObject); - } - } - - private void OnDestroy() - { - DisconnectAsync().Forget(); - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - } - - private void InitializeManager() - { - _cancellationTokenSource = new CancellationTokenSource(); - InitializeNativeWebSocket(); - } - - private void InitializeNativeWebSocket() - { - _nativeWebSocket = WebSocketFactory.Create(); - - _nativeWebSocket.OnConnected += OnNativeConnected; - _nativeWebSocket.OnDisconnected += OnNativeDisconnected; - _nativeWebSocket.OnError += OnNativeError; - _nativeWebSocket.OnMessageReceived += OnNativeMessageReceived; - } - - /// - /// WebSocket 연결 - /// - public async UniTask ConnectAsync(string sessionId = null, CancellationToken cancellationToken = default) - { - if (_isConnected || _isConnecting) - { - Debug.LogWarning("이미 연결 중이거나 연결되어 있습니다."); - return _isConnected; - } - - _isConnecting = true; - _sessionId = sessionId; - - try - { - var combinedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token).Token; - - var wsUrl = GetWebSocketUrl(sessionId); - Debug.Log($"WebSocket 연결 시도: {wsUrl}"); - - var success = await _nativeWebSocket.ConnectAsync(wsUrl, combinedCancellationToken); - - if (success) - { - _isConnected = true; - _isConnecting = false; - _reconnectAttempts = 0; - Debug.Log("WebSocket 연결 성공"); - return true; - } - else - { - _isConnecting = false; - return false; - } - } - catch (OperationCanceledException) - { - Debug.Log("WebSocket 연결이 취소되었습니다."); - return false; - } - catch (Exception ex) - { - var error = $"WebSocket 연결 중 예외 발생: {ex.Message}"; - Debug.LogError(error); - OnError?.Invoke(error); - return false; - } - finally - { - _isConnecting = false; - } - } - - /// - /// WebSocket 연결 해제 - /// - public async UniTask DisconnectAsync() - { - if (!_isConnected) - { - return; - } - - _isConnected = false; - _isConnecting = false; - - if (_nativeWebSocket != null) - { - await _nativeWebSocket.DisconnectAsync(); - } - - Debug.Log("WebSocket 연결 해제"); - OnDisconnected?.Invoke(); - } - - /// - /// 메시지 전송 - /// - public async UniTask SendMessageAsync(string type, object data, CancellationToken cancellationToken = default) - { - if (!_isConnected) - { - Debug.LogWarning("WebSocket이 연결되지 않았습니다."); - return false; - } - - try - { - var message = new WebSocketMessage - { - type = type, - data = data - }; - - var jsonMessage = JsonUtility.ToJson(message); - return await _nativeWebSocket.SendMessageAsync(jsonMessage, cancellationToken); - } - catch (Exception ex) - { - Debug.LogError($"메시지 전송 실패: {ex.Message}"); - return false; - } - } - - /// - /// 채팅 메시지 전송 - /// - public async UniTask SendChatMessageAsync(string message, CancellationToken cancellationToken = default) - { - var chatData = new ChatData - { - message = message, - sessionId = _sessionId, - timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - }; - - return await SendMessageAsync("chat", chatData, cancellationToken); - } - - /// - /// WebSocket URL 생성 - /// - private string GetWebSocketUrl(string sessionId = null) - { - string baseUrl = NetworkConfig.GetWebSocketUrl(); - - if (!string.IsNullOrEmpty(sessionId)) - { - return $"{baseUrl}?sessionId={sessionId}"; - } - - return baseUrl; - } - - /// - /// 자동 재연결 시도 - /// - private async UniTaskVoid TryReconnectAsync() - { - bool autoReconnect = NetworkConfig.AutoReconnect; - int maxReconnectAttempts = NetworkConfig.MaxReconnectAttempts; - float reconnectDelay = NetworkConfig.ReconnectDelay; - - if (!autoReconnect || _reconnectAttempts >= maxReconnectAttempts) - { - return; - } - - _reconnectAttempts++; - Debug.Log($"WebSocket 재연결 시도 {_reconnectAttempts}/{maxReconnectAttempts}"); - - await UniTask.Delay(TimeSpan.FromSeconds(reconnectDelay)); - - if (!_isConnected) - { - ConnectAsync(_sessionId).Forget(); - } - } - - #region Native WebSocket Event Handlers - - private void OnNativeConnected() - { - _isConnected = true; - _isConnecting = false; - _reconnectAttempts = 0; - - Debug.Log("WebSocket 연결 성공"); - OnConnected?.Invoke(); - } - - private void OnNativeDisconnected() - { - _isConnected = false; - _isConnecting = false; - - OnDisconnected?.Invoke(); - TryReconnectAsync().Forget(); - } - - private void OnNativeError(string error) - { - _isConnected = false; - _isConnecting = false; - - OnError?.Invoke(error); - } - - private void OnNativeMessageReceived(string message) - { - try - { - Debug.Log($"메시지 수신: {message?.Length ?? 0} bytes"); - ProcessBufferedMessage(message); - } - catch (Exception ex) - { - Debug.LogError($"메시지 파싱 실패: {ex.Message}"); - Debug.LogError($"원시 메시지: {message}"); - } - } - - /// - /// 메시지 버퍼링 및 완전한 JSON 메시지 처리 - /// - private void ProcessBufferedMessage(string message) - { - lock (_bufferLock) - { - _messageBuffer.Append(message); - string bufferedMessage = _messageBuffer.ToString(); - - Debug.Log($"버퍼링된 메시지 길이: {bufferedMessage.Length}"); - - if (IsCompleteJsonMessage(bufferedMessage)) - { - Debug.Log("완전한 JSON 메시지 감지됨. 처리 시작."); - - if (IsValidJsonMessage(bufferedMessage)) - { - ProcessMessage(bufferedMessage); - } - else - { - Debug.LogWarning("JSON 형식이 아닌 메시지가 수신됨"); - } - - _messageBuffer.Clear(); - Debug.Log("메시지 처리 완료. 버퍼 초기화됨."); - } - else - { - Debug.Log($"불완전한 메시지. 버퍼에 누적 중... (현재 길이: {bufferedMessage.Length})"); - } - } - } - - /// - /// 완전한 JSON 메시지인지 확인 - /// - private bool IsCompleteJsonMessage(string message) - { - if (string.IsNullOrEmpty(message)) - return false; - - int openBraces = 0; - int closeBraces = 0; - bool inString = false; - char escapeChar = '\\'; - - for (int i = 0; i < message.Length; i++) - { - char c = message[i]; - - if (c == '"' && (i == 0 || message[i - 1] != escapeChar)) - { - inString = !inString; - } - else if (!inString) - { - if (c == '{') - openBraces++; - else if (c == '}') - closeBraces++; - } - } - - bool isComplete = openBraces > 0 && openBraces == closeBraces; - Debug.Log($"JSON 완성도 체크: 열린괄호={openBraces}, 닫힌괄호={closeBraces}, 완성={isComplete}"); - - return isComplete; - } - - /// - /// JSON 형식인지 확인 - /// - private bool IsValidJsonMessage(string message) - { - if (string.IsNullOrEmpty(message)) - return false; - - message = message.Trim(); - - if (message.StartsWith("{") && message.EndsWith("}")) - return true; - - if (message.StartsWith("[") && message.EndsWith("]")) - return true; - - return false; - } - - /// - /// 메시지 타입에 따른 처리 - /// - private void ProcessMessage(string message) - { - try - { - var webSocketMessage = JsonUtility.FromJson(message); - if (webSocketMessage == null) - { - Debug.LogError("WebSocket 메시지 파싱 실패"); - return; - } - - Debug.Log($"메시지 타입: {webSocketMessage.type}"); - - switch (webSocketMessage.type) - { - case "session_id": - ProcessSessionIdMessage(webSocketMessage.data); - break; - case "chat": - ProcessChatMessage(webSocketMessage.data); - break; - default: - Debug.LogWarning($"알 수 없는 메시지 타입: {webSocketMessage.type}"); - break; - } - } - catch (Exception ex) - { - Debug.LogError($"메시지 처리 중 오류: {ex.Message}"); - } - } - - /// - /// 세션 ID 메시지 처리 - /// - private void ProcessSessionIdMessage(object data) - { - try - { - var sessionIdData = JsonUtility.FromJson(JsonUtility.ToJson(data)); - if (sessionIdData != null) - { - _sessionId = sessionIdData.session_id; - Debug.Log($"세션 ID 수신: {sessionIdData.session_id}"); - OnSessionIdReceived?.Invoke(sessionIdData.session_id); - } - } - catch (Exception ex) - { - Debug.LogError($"세션 ID 메시지 처리 중 오류: {ex.Message}"); - } - } - - /// - /// 채팅 메시지 처리 - /// - private void ProcessChatMessage(object data) - { - try - { - var chatData = JsonUtility.FromJson(JsonUtility.ToJson(data)); - if (chatData != null) - { - Debug.Log($"채팅 메시지 수신: {chatData.message}"); - OnChatMessageReceived?.Invoke(chatData.message); - } - } - catch (Exception ex) - { - Debug.LogError($"채팅 메시지 처리 중 오류: {ex.Message}"); - } - } - - #endregion - } - - /// - /// WebSocket 메시지 기본 구조 - /// - [Serializable] - public class WebSocketMessage - { - public string type; - public object data; - } - - /// - /// 세션 ID 데이터 - /// - [Serializable] - public class SessionIdData - { - public string session_id; - } - - /// - /// 채팅 데이터 - /// - [Serializable] - public class ChatData - { - public string message; - public string sessionId; - public long timestamp; - } -} \ No newline at end of file diff --git a/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs.meta b/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs.meta deleted file mode 100644 index 22dfba5..0000000 --- a/Assets/Infrastructure/Network/WebSocket/WebSocketManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8e1977f0484f5f84684a077ad63409b5 \ No newline at end of file diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/Mao.fadeMotionList.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/Mao.fadeMotionList.asset index 4a530de..09f5f5a 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/Mao.fadeMotionList.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/Mao.fadeMotionList.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 403ae2dd693bb1d4b924f6b8d206b053, type: 3} m_Name: Mao.fadeMotionList m_EditorClassIdentifier: - MotionInstanceIds: 14d2000020d20000d8d20000e8d20000dad100007ad2000086d2000018d20000 + MotionInstanceIds: e0d10000e8d1000042d2000052d20000bed100001cd2000024d20000e4d10000 CubismFadeMotionObjects: - {fileID: 11400000, guid: c6a5276089e6b2c4bb2f78cca94c4ded, type: 2} - {fileID: 11400000, guid: a0145e27134640343b894f03870256bc, type: 2} diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.anim index 5e56187..8083ee5 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.anim @@ -11378,5 +11378,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53882 + intParameter: 53788 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.fade.asset index e5459ca..eb31e47 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_01.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_01.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Mao/motions/mtn_01.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.anim index 38b146e..5323a7b 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.anim @@ -12098,5 +12098,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53722 + intParameter: 53694 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.fade.asset index a911e59..0b70576 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_02.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_02.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Mao/motions/mtn_02.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Mao/motions/mtn_02.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.5 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.anim index 0445509..8b6dff7 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.anim @@ -11774,5 +11774,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53792 + intParameter: 53736 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.fade.asset index 7f02379..65403f3 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_03.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_03.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Mao/motions/mtn_03.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Mao/motions/mtn_03.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.5 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.anim index 1202af8..5f8bca3 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.anim @@ -12944,5 +12944,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53894 + intParameter: 53796 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.fade.asset index 9e8d2a1..76fb1c1 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_04.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Mao/motions/mtn_04.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.5 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.anim index c5d4590..50626d2 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.anim @@ -11168,5 +11168,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53976 + intParameter: 53826 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.fade.asset index 8508f79..b647ce3 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: sample_01.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/sample_01.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Mao/motions/sample_01.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.anim index 7f8f15a..a8ba80f 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.anim @@ -15266,5 +15266,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53784 + intParameter: 53732 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.fade.asset index 9bc7561..80566a8 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: special_01.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_01.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Mao/motions/special_01.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.25 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.anim index 676e10f..9a145ff 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.anim @@ -17336,5 +17336,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53780 + intParameter: 53728 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.fade.asset index 121ded3..29d1ffe 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_02.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: special_02.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Mao/motions/special_02.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Mao/motions/special_02.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.25 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.anim index 1d7c7e4..3383509 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.anim @@ -18134,5 +18134,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53992 + intParameter: 53842 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.fade.asset index 84be377..3788240 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Mao/motions/special_03.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: special_03.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Mao/motions/special_03.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Mao/motions/special_03.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 0.25 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/Natori.fadeMotionList.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/Natori.fadeMotionList.asset index 20c858a..4d4da11 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/Natori.fadeMotionList.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/Natori.fadeMotionList.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 403ae2dd693bb1d4b924f6b8d206b053, type: 3} m_Name: Natori.fadeMotionList m_EditorClassIdentifier: - MotionInstanceIds: 5cd200000cd2000032d200007ed20000b4d2000002d20000ecd20000d6d10000a2d20000 + MotionInstanceIds: 10d20000d8d10000f8d1000020d200003ad20000d4d1000056d20000bad100002cd20000 CubismFadeMotionObjects: - {fileID: 11400000, guid: b211dc549c58a9e448169cc818f5edfa, type: 2} - {fileID: 11400000, guid: 145e4856478ab1540affc40745dbea64, type: 2} diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.anim index e16506c..14196ef 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.anim @@ -731,5 +731,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53922 + intParameter: 53804 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.fade.asset index 605d5f4..759eed3 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_00.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Natori/motions/mtn_00.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.anim index 2cf088d..e828e8c 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.anim @@ -6842,5 +6842,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53886 + intParameter: 53792 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.fade.asset index f069fae..a96ec73 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_01.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_01.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_01.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_01.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.anim index 44ec12a..cfa71b0 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.anim @@ -9107,5 +9107,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53762 + intParameter: 53716 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.fade.asset index f698b66..37cd1ec 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_02.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_02.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_02.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_02.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.anim index efd8cdc..5731b3f 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.anim @@ -9668,5 +9668,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53996 + intParameter: 53846 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.fade.asset index 02b649f..1faf747 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_03.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_03.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_03.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_03.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.anim index 2485b36..09e400b 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.anim @@ -10931,5 +10931,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53810 + intParameter: 53752 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.fade.asset index 19c0b38..933b3a7 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_04.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Natori/motions/mtn_04.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.anim index 5ca0846..1dd9384 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.anim @@ -10211,5 +10211,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53940 + intParameter: 53818 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.fade.asset index df66149..d4faf9d 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_05.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_05.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_05.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_05.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.anim index 798fcc1..a6d7d28 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.anim @@ -10199,5 +10199,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53772 + intParameter: 53720 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.fade.asset index 98e3237..fb5f7d7 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_06.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_06.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_06.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_06.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.anim index 9d23e6b..da79cf3 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.anim @@ -9533,5 +9533,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53852 + intParameter: 53776 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.fade.asset index 501f020..e317caf 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_07.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_07.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Natori/motions/mtn_07.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_07.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.anim b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.anim index e242e1a..d68f5ff 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.anim +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.anim @@ -9083,5 +9083,5 @@ AnimationClip: data: objectReferenceParameter: {fileID: 0} floatParameter: 0 - intParameter: 53718 + intParameter: 53690 messageOptions: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.fade.asset index 6b3a873..e2173d1 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_08.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Natori/motions/mtn_08.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Natori/motions/mtn_08.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_00.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_00.fade.asset index 655c1d6..6c34070 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_00.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_00.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_00.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Rice/motions/mtn_00.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Rice/motions/mtn_00.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_01.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_01.fade.asset index cc7b39e..dbac025 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_01.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_01.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_01.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Rice/motions/mtn_01.motion3.json + MotionName: Assets\Live2D\Cubism\Samples\Models\Rice/motions/mtn_01.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.fade.asset index c293b7c..66fc115 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_02.fade m_EditorClassIdentifier: - MotionName: Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Rice/motions/mtn_02.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_03.fade.asset b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_03.fade.asset index 533bdfa..52bcdb0 100644 --- a/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_03.fade.asset +++ b/Assets/Plugins/Live2D/Cubism/Samples/Models/Rice/motions/mtn_03.fade.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8f1ee1adc36a8a04a8d7c42ac5d6bc27, type: 3} m_Name: mtn_03.fade m_EditorClassIdentifier: - MotionName: Assets\Plugins\Live2D\Cubism\Samples\Models\Rice/motions/mtn_03.motion3.json + MotionName: Assets/Live2D/Cubism/Samples/Models/Rice/motions/mtn_03.motion3.json ModelFadeInTime: -1 ModelFadeOutTime: -1 FadeInTime: 1 diff --git a/Assets/Tests/Runtime.meta b/Assets/Tests/Runtime.meta deleted file mode 100644 index 76a563c..0000000 --- a/Assets/Tests/Runtime.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0412d803e6fb9cd408e6cf0d4a917590 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Tests/Runtime/NetworkTestManager.cs b/Assets/Tests/Runtime/NetworkTestManager.cs deleted file mode 100644 index e60a124..0000000 --- a/Assets/Tests/Runtime/NetworkTestManager.cs +++ /dev/null @@ -1,847 +0,0 @@ -using System; -using System.Threading; -using UnityEngine; -using Cysharp.Threading.Tasks; -using ProjectVG.Infrastructure.Network.WebSocket; -using ProjectVG.Infrastructure.Network.Services; -using ProjectVG.Infrastructure.Network.Configs; -using ProjectVG.Infrastructure.Network.Http; -using ProjectVG.Infrastructure.Network.DTOs.Chat; - -namespace ProjectVG.Tests.Runtime -{ - /// - /// WebSocket + HTTP 통합 테스트 매니저 - /// 더미 클라이언트와 동일한 방식으로 테스트합니다. - /// - public class NetworkTestManager : MonoBehaviour - { - [Header("테스트 설정")] - [SerializeField] private string testCharacterId = "44444444-4444-4444-4444-444444444444"; // 제로 - [SerializeField] private string testUserId = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"; - [SerializeField] private string testMessage = "안녕하세요! 테스트 메시지입니다."; - - [Header("자동 테스트")] - [SerializeField] private bool autoTest = false; - [SerializeField] private float testInterval = 15f; // 더 긴 간격으로 변경 - - // UI에서 접근할 수 있도록 public 프로퍼티 추가 - public bool AutoTest - { - get => autoTest; - set => autoTest = value; - } - - public float TestInterval - { - get => testInterval; - set => testInterval = value; - } - - private WebSocketManager _webSocketManager; - private ApiServiceManager _apiServiceManager; - private CancellationTokenSource _cancellationTokenSource; - private bool _isTestRunning = false; - private string _receivedSessionId = null; - private bool _chatResponseReceived = false; - private string _lastChatResponse = null; - private int _reconnectAttempts = 0; - private const int MAX_RECONNECT_ATTEMPTS = 3; - private bool _isIntentionalDisconnect = false; // 의도적인 연결 해제 여부 - - private void Awake() - { - _cancellationTokenSource = new CancellationTokenSource(); - - // HTTP 연결 허용 설정 - #if UNITY_EDITOR || UNITY_STANDALONE - UnityEngine.Networking.UnityWebRequest.ClearCookieCache(); - #endif - - // 매니저들이 없으면 생성 - EnsureManagersExist(); - - InitializeManagers(); - } - - /// - /// 필요한 매니저들이 존재하는지 확인하고 없으면 생성 - /// - private void EnsureManagersExist() - { - // HttpApiClient가 없으면 생성 - if (HttpApiClient.Instance == null) - { - Debug.Log("HttpApiClient를 생성합니다..."); - var httpApiClientGO = new GameObject("HttpApiClient"); - httpApiClientGO.AddComponent(); - DontDestroyOnLoad(httpApiClientGO); - } - - // WebSocketManager가 없으면 생성 - if (WebSocketManager.Instance == null) - { - Debug.Log("WebSocketManager를 생성합니다..."); - var webSocketManagerGO = new GameObject("WebSocketManager"); - webSocketManagerGO.AddComponent(); - DontDestroyOnLoad(webSocketManagerGO); - } - - // ApiServiceManager가 없으면 생성 - if (ApiServiceManager.Instance == null) - { - Debug.Log("ApiServiceManager를 생성합니다..."); - var apiServiceManagerGO = new GameObject("ApiServiceManager"); - apiServiceManagerGO.AddComponent(); - DontDestroyOnLoad(apiServiceManagerGO); - } - } - - private void Start() - { - if (autoTest) - { - StartAutoTest().Forget(); - } - } - - /// - /// UI에서 자동 테스트를 시작할 수 있도록 public 메서드 제공 - /// - public void StartAutoTestFromUI() - { - if (autoTest) - { - StartAutoTest().Forget(); - } - } - - private void OnDestroy() - { - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); - } - - private void InitializeManagers() - { - try - { - // NetworkConfig 초기화 (앱 시작 시 환경 설정) - NetworkConfig.SetDevelopmentEnvironment(); - - // WebSocket 매니저 초기화 - _webSocketManager = WebSocketManager.Instance; - if (_webSocketManager == null) - { - Debug.LogError("WebSocketManager.Instance가 null입니다. 매니저가 생성되지 않았습니다."); - return; - } - - Debug.Log($"WebSocket 설정 적용: {NetworkConfig.GetWebSocketUrl()}"); - Debug.Log($"현재 환경: {NetworkConfig.CurrentEnvironment}"); - - // HTTP API 클라이언트 설정 - if (HttpApiClient.Instance != null) - { - Debug.Log($"API 설정 적용: {NetworkConfig.GetFullApiUrl("chat")}"); - } - - // API 서비스 매니저 초기화 - _apiServiceManager = ApiServiceManager.Instance; - if (_apiServiceManager == null) - { - Debug.LogError("ApiServiceManager.Instance가 null입니다. 매니저가 생성되지 않았습니다."); - return; - } - - // WebSocket 이벤트 구독 - _webSocketManager.OnConnected += OnWebSocketConnected; - _webSocketManager.OnDisconnected += OnWebSocketDisconnected; - _webSocketManager.OnError += OnWebSocketError; - _webSocketManager.OnSessionIdReceived += OnSessionIdReceived; - _webSocketManager.OnChatMessageReceived += OnChatMessageReceived; - - Debug.Log("NetworkTestManager 초기화 완료"); - NetworkConfig.LogCurrentSettings(); - } - catch (Exception ex) - { - Debug.LogError($"NetworkTestManager 초기화 중 오류: {ex.Message}"); - } - } - - #region 수동 테스트 메서드들 - - [ContextMenu("1. WebSocket 연결 (더미 클라이언트 방식)")] - public async void ConnectWebSocket() - { - if (_isTestRunning) - { - Debug.LogWarning("테스트가 이미 실행 중입니다."); - return; - } - - if (_webSocketManager == null) - { - Debug.LogError("WebSocketManager가 초기화되지 않았습니다."); - return; - } - - try - { - Debug.Log("=== WebSocket 연결 시작 (더미 클라이언트 방식) ==="); - - // 현재 설정 정보 출력 - Debug.Log($"현재 환경: {NetworkConfig.CurrentEnvironment}"); - Debug.Log($"WebSocket 서버: {NetworkConfig.GetWebSocketUrl()}"); - - _receivedSessionId = null; // 세션 ID 초기화 - _reconnectAttempts = 0; - _isIntentionalDisconnect = false; // 의도적 해제 플래그 초기화 - - // 더미 클라이언트처럼 세션 ID 없이 연결 - bool connected = await _webSocketManager.ConnectAsync(); - - if (connected) - { - Debug.Log("✅ WebSocket 연결 성공! 세션 ID 대기 중..."); - } - else - { - Debug.LogError("❌ WebSocket 연결 실패!"); - } - } - catch (Exception ex) - { - Debug.LogError($"WebSocket 연결 중 오류: {ex.Message}"); - } - } - - [ContextMenu("2. HTTP 채팅 요청 (더미 클라이언트 방식)")] - public async void SendChatRequest() - { - if (_webSocketManager == null || !_webSocketManager.IsConnected) - { - Debug.LogWarning("WebSocket이 연결되지 않았습니다. 먼저 연결해주세요."); - return; - } - - if (_apiServiceManager == null) - { - Debug.LogError("ApiServiceManager가 초기화되지 않았습니다."); - return; - } - - // 세션 ID가 아직 수신되지 않았으면 대기 - if (string.IsNullOrEmpty(_receivedSessionId)) - { - Debug.LogError("세션 ID가 없습니다. WebSocket에서 세션 ID를 먼저 받아야 합니다."); - return; - } - - try - { - Debug.Log("=== HTTP 채팅 요청 시작 (더미 클라이언트 방식) ==="); - - // 현재 설정 정보 출력 - Debug.Log($"현재 환경: {NetworkConfig.CurrentEnvironment}"); - Debug.Log($"API 서버: {NetworkConfig.GetFullApiUrl("chat")}"); - Debug.Log($"세션 ID: {_receivedSessionId}"); - - var chatRequest = new ChatRequest - { - message = testMessage, - characterId = testCharacterId, - userId = testUserId, - sessionId = _receivedSessionId, // WebSocket에서 받은 세션 ID 사용 - actor = "web_user", - action = "chat", // 클라이언트와 동일하게 명시적으로 설정 - requestedAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") - }; - - var response = await _apiServiceManager.Chat.SendChatAsync(chatRequest); - - if (response != null && response.success) - { - Debug.Log($"✅ HTTP 채팅 요청 성공! 응답: {response.message}"); - Debug.Log($" - 세션 ID: {_receivedSessionId}"); - Debug.Log($" - 캐릭터 ID: {testCharacterId}"); - Debug.Log($" - 사용자 ID: {testUserId}"); - } - else - { - Debug.LogError($"❌ HTTP 채팅 요청 실패: {response?.message ?? "알 수 없는 오류"}"); - } - } - catch (Exception ex) - { - Debug.LogError($"HTTP 채팅 요청 중 오류: {ex.Message}"); - } - } - - [ContextMenu("3. HTTP 캐릭터 정보 요청")] - public async void GetCharacterInfo() - { - try - { - Debug.Log("=== HTTP 캐릭터 정보 요청 시작 ==="); - - var character = await _apiServiceManager.Character.GetCharacterAsync(testCharacterId); - - if (character != null) - { - Debug.Log($"✅ 캐릭터 정보 조회 성공!"); - Debug.Log($" - ID: {character.id}"); - Debug.Log($" - 이름: {character.name}"); - Debug.Log($" - 설명: {character.description}"); - Debug.Log($" - 역할: {character.role}"); - Debug.Log($" - 활성화: {character.isActive}"); - } - else - { - Debug.LogError($"❌ 캐릭터 정보 조회 실패: 캐릭터를 찾을 수 없습니다."); - } - } - catch (Exception ex) - { - Debug.LogError($"HTTP 캐릭터 정보 요청 중 오류: {ex.Message}"); - } - } - - [ContextMenu("4. WebSocket 메시지 전송")] - public async void SendWebSocketMessage() - { - if (!_webSocketManager.IsConnected) - { - Debug.LogWarning("WebSocket이 연결되지 않았습니다."); - return; - } - - try - { - Debug.Log("=== WebSocket 메시지 전송 시작 ==="); - - bool sent = await _webSocketManager.SendChatMessageAsync( - message: "WebSocket으로 직접 전송하는 테스트 메시지" - ); - - if (sent) - { - Debug.Log("✅ WebSocket 메시지 전송 성공!"); - } - else - { - Debug.LogError("❌ WebSocket 메시지 전송 실패!"); - } - } - catch (Exception ex) - { - Debug.LogError($"WebSocket 메시지 전송 중 오류: {ex.Message}"); - } - } - - [ContextMenu("5. WebSocket 연결 해제")] - public async void DisconnectWebSocket() - { - try - { - Debug.Log("=== WebSocket 연결 해제 시작 ==="); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await _webSocketManager.DisconnectAsync(); - _receivedSessionId = null; // 세션 ID 초기화 - Debug.Log("✅ WebSocket 연결 해제 완료!"); - } - catch (Exception ex) - { - Debug.LogError($"WebSocket 연결 해제 중 오류: {ex.Message}"); - } - } - - [ContextMenu("더미 클라이언트 방식 전체 테스트")] - public async void RunDummyClientTest() - { - if (_isTestRunning) - { - Debug.LogWarning("테스트가 이미 실행 중입니다."); - return; - } - - _isTestRunning = true; - - try - { - Debug.Log("🚀 === 더미 클라이언트 방식 전체 테스트 시작 ==="); - - // 현재 설정 정보 출력 - Debug.Log($"테스트 환경: {NetworkConfig.CurrentEnvironment}"); - Debug.Log($"API 서버: {NetworkConfig.GetFullApiUrl("")}"); - Debug.Log($"WebSocket 서버: {NetworkConfig.GetWebSocketUrl()}"); - - // 0. 기존 연결이 있으면 해제 - if (_webSocketManager.IsConnected) - { - Debug.Log("0️⃣ 기존 연결 해제 중..."); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await _webSocketManager.DisconnectAsync(); - await UniTask.Delay(1000); // 연결 해제 완료 대기 - } - - // 1. WebSocket 연결 (세션 ID 없이) - Debug.Log("1️⃣ WebSocket 연결 중..."); - bool connected = await _webSocketManager.ConnectAsync(); - if (!connected) - { - Debug.LogError("WebSocket 연결 실패로 테스트 중단"); - return; - } - - // 2. 세션 ID 수신 대기 (최대 10초) - Debug.Log("2️⃣ 세션 ID 수신 대기 중..."); - int waitCount = 0; - while (string.IsNullOrEmpty(_receivedSessionId) && waitCount < 100) // 10초로 증가 - { - await UniTask.Delay(100); - waitCount++; - if (waitCount % 10 == 0) // 1초마다 로그 - { - Debug.Log($"2️⃣ 세션 ID 대기 중... ({waitCount/10}초 경과)"); - } - } - - if (string.IsNullOrEmpty(_receivedSessionId)) - { - Debug.LogError("세션 ID를 받지 못했습니다. (10초 타임아웃)"); - Debug.LogWarning("서버에서 세션 ID 메시지를 보내지 않았거나, 메시지 형식이 다를 수 있습니다."); - return; - } - - Debug.Log($"✅ 세션 ID 수신: {_receivedSessionId}"); - - await UniTask.Delay(1000); // 안정화 대기 - - // 3. HTTP 채팅 요청 (세션 ID 포함) - Debug.Log("3️⃣ HTTP 채팅 요청 중..."); - await SendChatRequestInternal(); - - // 채팅 응답을 기다림 - await WaitForChatResponse(15); // 15초 타임아웃 - - // 4. HTTP 캐릭터 정보 요청 - Debug.Log("4️⃣ HTTP 캐릭터 정보 요청 중..."); - await GetCharacterInfoInternal(); - - await UniTask.Delay(1000); - - // 5. WebSocket 연결 해제 - Debug.Log("5️⃣ WebSocket 연결 해제 중..."); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await _webSocketManager.DisconnectAsync(); - _receivedSessionId = null; - - // 연결 해제 후 충분한 대기 시간 - await UniTask.Delay(2000); - - Debug.Log("✅ === 더미 클라이언트 방식 전체 테스트 완료 ==="); - } - catch (Exception ex) - { - Debug.LogError($"더미 클라이언트 방식 전체 테스트 중 오류: {ex.Message}"); - } - finally - { - _isTestRunning = false; - } - } - - [ContextMenu("전체 테스트 실행")] - public async void RunFullTest() - { - if (_isTestRunning) - { - Debug.LogWarning("테스트가 이미 실행 중입니다."); - return; - } - - _isTestRunning = true; - - try - { - Debug.Log("🚀 === 전체 테스트 시작 ==="); - - // 현재 설정 정보 출력 - Debug.Log($"테스트 환경: {NetworkConfig.CurrentEnvironment}"); - Debug.Log($"API 서버: {NetworkConfig.GetFullApiUrl("")}"); - Debug.Log($"WebSocket 서버: {NetworkConfig.GetWebSocketUrl()}"); - - // 1. WebSocket 연결 - Debug.Log("1️⃣ WebSocket 연결 중..."); - bool connected = await _webSocketManager.ConnectAsync(); - if (!connected) - { - Debug.LogError("WebSocket 연결 실패로 테스트 중단"); - return; - } - - // 2. 세션 ID 수신 대기 (최대 10초) - Debug.Log("2️⃣ 세션 ID 수신 대기 중..."); - int waitCount = 0; - while (string.IsNullOrEmpty(_receivedSessionId) && waitCount < 100) - { - await UniTask.Delay(100); - waitCount++; - if (waitCount % 10 == 0) // 1초마다 로그 - { - Debug.Log($"2️⃣ 세션 ID 대기 중... ({waitCount/10}초 경과)"); - } - } - - if (string.IsNullOrEmpty(_receivedSessionId)) - { - Debug.LogError("세션 ID를 받지 못했습니다. (10초 타임아웃)"); - return; - } - - Debug.Log($"✅ 세션 ID 수신: {_receivedSessionId}"); - await UniTask.Delay(1000); // 안정화 대기 - - // 3. HTTP 채팅 요청 - Debug.Log("3️⃣ HTTP 채팅 요청 중..."); - await SendChatRequestInternal(); - - // 채팅 응답을 기다림 - await WaitForChatResponse(15); // 15초 타임아웃 - - // 4. HTTP 캐릭터 정보 요청 - Debug.Log("4️⃣ HTTP 캐릭터 정보 요청 중..."); - await GetCharacterInfoInternal(); - - await UniTask.Delay(1000); - - // 5. WebSocket 메시지 전송 - Debug.Log("5️⃣ WebSocket 메시지 전송 중..."); - await SendWebSocketMessageInternal(); - - await UniTask.Delay(1000); - - // 6. WebSocket 연결 해제 - Debug.Log("6️⃣ WebSocket 연결 해제 중..."); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await _webSocketManager.DisconnectAsync(); - - Debug.Log("✅ === 전체 테스트 완료 ==="); - } - catch (Exception ex) - { - Debug.LogError($"전체 테스트 중 오류: {ex.Message}"); - } - finally - { - _isTestRunning = false; - } - } - - [ContextMenu("현재 네트워크 설정 정보 출력")] - public void LogCurrentNetworkConfig() - { - Debug.Log("=== 현재 네트워크 설정 정보 ==="); - NetworkConfig.LogCurrentSettings(); - } - - #endregion - - #region 자동 테스트 - - private async UniTaskVoid StartAutoTest() - { - Debug.Log("🔄 자동 테스트 시작..."); - - // 매니저 초기화 확인 - if (_webSocketManager == null || _apiServiceManager == null) - { - Debug.LogError("매니저가 초기화되지 않았습니다. 자동 테스트를 중단합니다."); - return; - } - - // HttpApiClient 확인 - if (HttpApiClient.Instance == null) - { - Debug.LogError("HttpApiClient가 초기화되지 않았습니다. 자동 테스트를 중단합니다."); - return; - } - - // 현재 설정 정보 출력 - Debug.Log($"자동 테스트 환경: {NetworkConfig.CurrentEnvironment}"); - Debug.Log($"API 서버: {NetworkConfig.GetFullApiUrl("")}"); - Debug.Log($"WebSocket 서버: {NetworkConfig.GetWebSocketUrl()}"); - - while (!_cancellationTokenSource.Token.IsCancellationRequested) - { - try - { - await RunDummyClientTestInternal(); - await UniTask.Delay(TimeSpan.FromSeconds(testInterval), cancellationToken: _cancellationTokenSource.Token); - } - catch (OperationCanceledException) - { - Debug.Log("자동 테스트가 취소되었습니다."); - break; - } - catch (Exception ex) - { - Debug.LogError($"자동 테스트 중 오류: {ex.Message}"); - Debug.LogError($"스택 트레이스: {ex.StackTrace}"); - await UniTask.Delay(5000, cancellationToken: _cancellationTokenSource.Token); - } - } - - Debug.Log("🔄 자동 테스트 종료"); - } - - private async UniTask RunDummyClientTestInternal() - { - // 매니저 null 체크 - if (_webSocketManager == null) - { - Debug.LogError("WebSocketManager가 null입니다. 초기화를 확인해주세요."); - return; - } - - if (_apiServiceManager == null) - { - Debug.LogError("ApiServiceManager가 null입니다. 초기화를 확인해주세요."); - return; - } - - try - { - // 현재 설정 정보 출력 - Debug.Log($"자동 테스트 환경: {NetworkConfig.CurrentEnvironment}"); - - // 0. 기존 연결이 있으면 해제 - if (_webSocketManager.IsConnected) - { - Debug.Log("자동 테스트 - 기존 연결 해제 중..."); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await _webSocketManager.DisconnectAsync(); - await UniTask.Delay(1000); - } - - // 1. WebSocket 연결 (세션 ID 없이) - Debug.Log("자동 테스트 - WebSocket 연결 중..."); - bool connected = await _webSocketManager.ConnectAsync(); - if (!connected) - { - Debug.LogError("자동 테스트 - WebSocket 연결 실패"); - return; - } - - // 2. 세션 ID 수신 대기 - Debug.Log("자동 테스트 - 세션 ID 수신 대기 중..."); - int waitCount = 0; - while (string.IsNullOrEmpty(_receivedSessionId) && waitCount < 100) // 10초로 증가 - { - await UniTask.Delay(100); - waitCount++; - if (waitCount % 10 == 0) - { - Debug.Log($"자동 테스트 - 세션 ID 대기 중... ({waitCount/10}초 경과)"); - } - } - - if (string.IsNullOrEmpty(_receivedSessionId)) - { - Debug.LogError("자동 테스트 - 세션 ID를 받지 못했습니다. (10초 타임아웃)"); - Debug.LogWarning("서버에서 세션 ID 메시지를 보내지 않았거나, 메시지 형식이 다를 수 있습니다."); - return; - } - - Debug.Log($"자동 테스트 - 세션 ID 수신: {_receivedSessionId}"); - await UniTask.Delay(500); - - // 3. HTTP 채팅 요청 (세션 ID 포함) - Debug.Log("자동 테스트 - HTTP 채팅 요청 중..."); - await SendChatRequestInternal(); - Debug.Log("자동 테스트 - HTTP 요청 완료, 채팅 응답 대기 중..."); - - // 채팅 응답을 기다림 - await WaitForChatResponse(15); // 15초 타임아웃 - - // 4. HTTP 캐릭터 정보 요청 - Debug.Log("자동 테스트 - HTTP 캐릭터 정보 요청 중..."); - await GetCharacterInfoInternal(); - await UniTask.Delay(500); - - // 5. 연결 해제 (더 오래 기다린 후) - Debug.Log("자동 테스트 - WebSocket 응답 대기 완료, 연결 해제 중..."); - _isIntentionalDisconnect = true; // 의도적 해제 플래그 설정 - await UniTask.Delay(2000); // 추가 대기 시간 - await _webSocketManager.DisconnectAsync(); - _receivedSessionId = null; - - // 연결 해제 후 충분한 대기 시간 - await UniTask.Delay(2000); - - Debug.Log("자동 테스트 - 더미 클라이언트 방식 테스트 완료"); - } - catch (Exception ex) - { - Debug.LogError($"자동 테스트 중 오류: {ex.Message}"); - throw; // 상위로 예외 전파 - } - } - - private async UniTask SendChatRequestInternal() - { - if (_apiServiceManager?.Chat == null) - { - Debug.LogError("ChatApiService가 null입니다."); - return; - } - - // 세션 ID가 없으면 HTTP 요청을 보내지 않음 - if (string.IsNullOrEmpty(_receivedSessionId)) - { - Debug.LogError("세션 ID가 없습니다. WebSocket에서 세션 ID를 먼저 받아야 합니다."); - return; - } - - var chatRequest = new ChatRequest - { - message = $"자동 테스트 메시지 - {DateTime.Now:HH:mm:ss}", - characterId = testCharacterId, - userId = testUserId, - sessionId = _receivedSessionId, // 서버에서 받은 세션 ID 사용 - actor = "web_user", - action = "chat", // 클라이언트와 동일하게 명시적으로 설정 - requestedAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") - }; - - Debug.Log($"HTTP 채팅 요청 전송: {JsonUtility.ToJson(chatRequest)}"); - - // 채팅 응답 수신 상태 초기화 - _chatResponseReceived = false; - _lastChatResponse = null; - - try - { - var response = await _apiServiceManager.Chat.SendChatAsync(chatRequest); - Debug.Log($"HTTP 채팅 요청 성공: {JsonUtility.ToJson(response)}"); - } - catch (Exception ex) - { - Debug.LogError($"HTTP 채팅 요청 실패: {ex.Message}"); - } - } - - /// - /// 채팅 응답을 기다리는 메서드 - /// - private async UniTask WaitForChatResponse(int timeoutSeconds = 15) - { - Debug.Log($"채팅 응답 대기 시작 (타임아웃: {timeoutSeconds}초)"); - - var startTime = DateTime.Now; - while (!_chatResponseReceived && (DateTime.Now - startTime).TotalSeconds < timeoutSeconds) - { - await UniTask.Delay(100); - - // WebSocket 연결 상태 확인 - if (_webSocketManager != null && !_webSocketManager.IsConnected) - { - Debug.LogWarning("WebSocket 연결이 끊어졌습니다. 응답 대기 중단"); - break; - } - } - - if (_chatResponseReceived) - { - Debug.Log($"✅ 채팅 응답 수신 완료: {_lastChatResponse}"); - } - else - { - Debug.LogWarning($"⚠️ 채팅 응답 타임아웃 ({timeoutSeconds}초)"); - } - } - - private async UniTask GetCharacterInfoInternal() - { - if (_apiServiceManager?.Character == null) - { - Debug.LogError("CharacterApiService가 null입니다."); - return; - } - - var character = await _apiServiceManager.Character.GetCharacterAsync(testCharacterId); - if (character != null) - { - Debug.Log($"자동 테스트 - 캐릭터 정보 조회 성공: {character.name}"); - } - } - - private async UniTask SendWebSocketMessageInternal() - { - if (_webSocketManager == null) - { - Debug.LogError("WebSocketManager가 null입니다."); - return; - } - - await _webSocketManager.SendChatMessageAsync( - message: $"자동 WebSocket 메시지 - {DateTime.Now:HH:mm:ss}" - ); - } - - #endregion - - #region WebSocket 이벤트 핸들러 - - private void OnWebSocketConnected() - { - Debug.Log("🎉 WebSocket 연결됨!"); - _reconnectAttempts = 0; // 연결 성공 시 재연결 시도 횟수 초기화 - } - - private void OnWebSocketDisconnected() - { - Debug.Log("🔌 WebSocket 연결 해제됨!"); - - // 의도적인 연결 해제가 아닌 경우에만 자동 재연결 시도 - if (!_isIntentionalDisconnect && _reconnectAttempts < MAX_RECONNECT_ATTEMPTS) - { - _reconnectAttempts++; - Debug.Log($"재연결 시도 {_reconnectAttempts}/{MAX_RECONNECT_ATTEMPTS}"); - ConnectWebSocket(); - } - else if (_isIntentionalDisconnect) - { - Debug.Log("의도적인 연결 해제로 재연결을 시도하지 않습니다."); - _isIntentionalDisconnect = false; // 플래그 초기화 - } - else - { - Debug.LogError("최대 재연결 시도 횟수 초과"); - } - } - - private void OnWebSocketError(string error) - { - Debug.LogError($"❌ WebSocket 오류: {error}"); - } - - private void OnSessionIdReceived(string sessionId) - { - _receivedSessionId = sessionId; - Debug.Log($"🆔 WebSocket 세션 ID 수신: {_receivedSessionId}"); - Debug.Log($"✅ 세션 ID가 성공적으로 저장되었습니다!"); - } - - private void OnChatMessageReceived(string message) - { - Debug.Log($"💬 WebSocket 채팅 메시지 수신: {message}"); - _chatResponseReceived = true; - _lastChatResponse = message; - } - - #endregion - } -} \ No newline at end of file diff --git a/Assets/Tests/Runtime/NetworkTestManager.cs.meta b/Assets/Tests/Runtime/NetworkTestManager.cs.meta deleted file mode 100644 index 6e6f889..0000000 --- a/Assets/Tests/Runtime/NetworkTestManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: d0a3e75ea471e5f47b758f5a032a094e \ No newline at end of file diff --git a/Assets/Tests/Runtime/NetworkTestUI.cs b/Assets/Tests/Runtime/NetworkTestUI.cs deleted file mode 100644 index eebc0b0..0000000 --- a/Assets/Tests/Runtime/NetworkTestUI.cs +++ /dev/null @@ -1,355 +0,0 @@ -using UnityEngine; -using UnityEngine.UI; -using TMPro; - -namespace ProjectVG.Tests.Runtime -{ - /// - /// 네트워크 테스트를 위한 UI 매니저 - /// 더미 클라이언트 방식 테스트를 지원합니다. - /// - public class NetworkTestUI : MonoBehaviour - { - [Header("UI References")] - [SerializeField] private Button connectButton; - [SerializeField] private Button disconnectButton; - [SerializeField] private Button chatRequestButton; - [SerializeField] private Button characterInfoButton; - [SerializeField] private Button webSocketMessageButton; - [SerializeField] private Button fullTestButton; - [SerializeField] private Button dummyClientTestButton; - [SerializeField] private Button autoTestButton; - - [Header("Status Display")] - [SerializeField] private TextMeshProUGUI statusText; - [SerializeField] private TextMeshProUGUI logText; - [SerializeField] private ScrollRect logScrollRect; - - [Header("Input Fields")] - [SerializeField] private TMP_InputField characterIdInput; - [SerializeField] private TMP_InputField userIdInput; - [SerializeField] private TMP_InputField messageInput; - - [Header("Test Settings")] - [SerializeField] private Toggle autoTestToggle; - [SerializeField] private Slider testIntervalSlider; - [SerializeField] private TextMeshProUGUI intervalText; - - private NetworkTestManager _testManager; - private bool _isAutoTestRunning = false; - - private void Start() - { - _testManager = FindFirstObjectByType(); - if (_testManager == null) - { - Debug.LogError("NetworkTestManager를 찾을 수 없습니다!"); - return; - } - - InitializeUI(); - UpdateStatus("대기 중..."); - } - - private void InitializeUI() - { - // 버튼 이벤트 연결 - if (connectButton != null) - connectButton.onClick.AddListener(OnConnectButtonClicked); - - if (disconnectButton != null) - disconnectButton.onClick.AddListener(OnDisconnectButtonClicked); - - if (chatRequestButton != null) - chatRequestButton.onClick.AddListener(OnChatRequestButtonClicked); - - if (characterInfoButton != null) - characterInfoButton.onClick.AddListener(OnCharacterInfoButtonClicked); - - if (webSocketMessageButton != null) - webSocketMessageButton.onClick.AddListener(OnWebSocketMessageButtonClicked); - - if (fullTestButton != null) - fullTestButton.onClick.AddListener(OnFullTestButtonClicked); - - if (dummyClientTestButton != null) - dummyClientTestButton.onClick.AddListener(OnDummyClientTestButtonClicked); - - if (autoTestButton != null) - autoTestButton.onClick.AddListener(OnAutoTestButtonClicked); - - // 초기값 설정 - if (characterIdInput != null) - characterIdInput.text = "44444444-4444-4444-4444-444444444444"; // 제로 - - if (userIdInput != null) - userIdInput.text = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"; - - if (messageInput != null) - messageInput.text = "안녕하세요! 테스트 메시지입니다."; - - // 자동 테스트 설정 - if (autoTestToggle != null) - { - autoTestToggle.isOn = _testManager.AutoTest; - autoTestToggle.onValueChanged.AddListener(OnAutoTestToggleChanged); - } - - if (testIntervalSlider != null) - { - testIntervalSlider.minValue = 5f; - testIntervalSlider.maxValue = 30f; - testIntervalSlider.value = _testManager.TestInterval; - testIntervalSlider.onValueChanged.AddListener(OnTestIntervalChanged); - UpdateIntervalText(); - } - - // 초기 버튼 상태 설정 - UpdateButtonStates(false); - } - - private void UpdateButtonStates(bool isConnected) - { - if (connectButton != null) - connectButton.interactable = !isConnected; - - if (disconnectButton != null) - disconnectButton.interactable = isConnected; - - if (chatRequestButton != null) - chatRequestButton.interactable = isConnected; - - if (characterInfoButton != null) - characterInfoButton.interactable = true; // HTTP 요청은 연결 없이도 가능 - - if (webSocketMessageButton != null) - webSocketMessageButton.interactable = isConnected; - - if (fullTestButton != null) - fullTestButton.interactable = !_isAutoTestRunning; - - if (dummyClientTestButton != null) - dummyClientTestButton.interactable = !_isAutoTestRunning; - - if (autoTestButton != null) - { - autoTestButton.interactable = !_isAutoTestRunning; - autoTestButton.GetComponentInChildren().text = - _isAutoTestRunning ? "자동 테스트 중지" : "자동 테스트 시작"; - } - } - - private void UpdateStatus(string status) - { - if (statusText != null) - { - statusText.text = $"상태: {status}"; - } - } - - private void AddLog(string message) - { - if (logText != null) - { - logText.text += $"[{System.DateTime.Now:HH:mm:ss}] {message}\n"; - - // 스크롤을 맨 아래로 이동 - if (logScrollRect != null) - { - Canvas.ForceUpdateCanvases(); - logScrollRect.verticalNormalizedPosition = 0f; - } - } - } - - private void UpdateIntervalText() - { - if (intervalText != null && testIntervalSlider != null) - { - intervalText.text = $"테스트 간격: {testIntervalSlider.value:F1}초"; - } - } - - #region Button Event Handlers - - private void OnConnectButtonClicked() - { - AddLog("WebSocket 연결 시도 (더미 클라이언트 방식)..."); - UpdateStatus("연결 중..."); - _testManager.ConnectWebSocket(); - } - - private void OnDisconnectButtonClicked() - { - AddLog("WebSocket 연결 해제..."); - UpdateStatus("연결 해제 중..."); - _testManager.DisconnectWebSocket(); - } - - private void OnChatRequestButtonClicked() - { - AddLog("HTTP 채팅 요청 전송 (더미 클라이언트 방식)..."); - UpdateStatus("채팅 요청 중..."); - _testManager.SendChatRequest(); - } - - private void OnCharacterInfoButtonClicked() - { - AddLog("HTTP 캐릭터 정보 요청..."); - UpdateStatus("캐릭터 정보 요청 중..."); - _testManager.GetCharacterInfo(); - } - - private void OnWebSocketMessageButtonClicked() - { - string message = messageInput != null ? messageInput.text : "테스트 메시지"; - AddLog($"WebSocket 메시지 전송: {message}"); - UpdateStatus("WebSocket 메시지 전송 중..."); - _testManager.SendWebSocketMessage(); - } - - private void OnFullTestButtonClicked() - { - AddLog("전체 테스트 시작..."); - UpdateStatus("전체 테스트 실행 중..."); - _testManager.RunFullTest(); - } - - private void OnDummyClientTestButtonClicked() - { - AddLog("더미 클라이언트 방식 전체 테스트 시작..."); - UpdateStatus("더미 클라이언트 테스트 실행 중..."); - _testManager.RunDummyClientTest(); - } - - private void OnAutoTestButtonClicked() - { - if (!_isAutoTestRunning) - { - _isAutoTestRunning = true; - AddLog("자동 테스트 시작 (더미 클라이언트 방식)..."); - UpdateStatus("자동 테스트 실행 중..."); - UpdateButtonStates(true); - - // 자동 테스트 시작 - _testManager.AutoTest = true; - _testManager.StartAutoTestFromUI(); - } - else - { - _isAutoTestRunning = false; - AddLog("자동 테스트 중지..."); - UpdateStatus("대기 중..."); - UpdateButtonStates(false); - - // 자동 테스트 중지 - _testManager.AutoTest = false; - } - } - - private void OnAutoTestToggleChanged(bool isOn) - { - _testManager.AutoTest = isOn; - AddLog($"자동 테스트 설정: {(isOn ? "활성화" : "비활성화")}"); - } - - private void OnTestIntervalChanged(float value) - { - _testManager.TestInterval = value; - UpdateIntervalText(); - AddLog($"테스트 간격 변경: {value:F1}초"); - } - - #endregion - - #region Public Methods for External Updates - - public void OnWebSocketConnected() - { - UpdateStatus("WebSocket 연결됨"); - UpdateButtonStates(true); - AddLog("✅ WebSocket 연결 성공!"); - } - - public void OnWebSocketDisconnected() - { - UpdateStatus("WebSocket 연결 해제됨"); - UpdateButtonStates(false); - AddLog("🔌 WebSocket 연결 해제됨!"); - } - - public void OnWebSocketError(string error) - { - UpdateStatus("WebSocket 오류"); - AddLog($"❌ WebSocket 오류: {error}"); - } - - public void OnChatMessageReceived(string message) - { - AddLog($"💬 채팅 메시지 수신: {message}"); - } - - public void OnSessionIdMessageReceived(string sessionId) - { - AddLog($"🆔 세션 ID 수신: {sessionId}"); - } - - public void OnHttpRequestSuccess(string operation) - { - AddLog($"✅ HTTP {operation} 성공!"); - } - - public void OnHttpRequestFailed(string operation, string error) - { - AddLog($"❌ HTTP {operation} 실패: {error}"); - } - - public void OnReconnectAttempt(int attempt, int maxAttempts) - { - AddLog($"🔄 재연결 시도 {attempt}/{maxAttempts}"); - UpdateStatus($"재연결 시도 중... ({attempt}/{maxAttempts})"); - } - - public void OnReconnectFailed() - { - AddLog("❌ 최대 재연결 시도 횟수 초과"); - UpdateStatus("재연결 실패"); - } - - #endregion - - private void OnDestroy() - { - // 버튼 이벤트 해제 - if (connectButton != null) - connectButton.onClick.RemoveListener(OnConnectButtonClicked); - - if (disconnectButton != null) - disconnectButton.onClick.RemoveListener(OnDisconnectButtonClicked); - - if (chatRequestButton != null) - chatRequestButton.onClick.RemoveListener(OnChatRequestButtonClicked); - - if (characterInfoButton != null) - characterInfoButton.onClick.RemoveListener(OnCharacterInfoButtonClicked); - - if (webSocketMessageButton != null) - webSocketMessageButton.onClick.RemoveListener(OnWebSocketMessageButtonClicked); - - if (fullTestButton != null) - fullTestButton.onClick.RemoveListener(OnFullTestButtonClicked); - - if (dummyClientTestButton != null) - dummyClientTestButton.onClick.RemoveListener(OnDummyClientTestButtonClicked); - - if (autoTestButton != null) - autoTestButton.onClick.RemoveListener(OnAutoTestButtonClicked); - - if (autoTestToggle != null) - autoTestToggle.onValueChanged.RemoveListener(OnAutoTestToggleChanged); - - if (testIntervalSlider != null) - testIntervalSlider.onValueChanged.RemoveListener(OnTestIntervalChanged); - } - } -} \ No newline at end of file diff --git a/Assets/Tests/Runtime/NetworkTestUI.cs.meta b/Assets/Tests/Runtime/NetworkTestUI.cs.meta deleted file mode 100644 index 492659f..0000000 --- a/Assets/Tests/Runtime/NetworkTestUI.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 729ea7f71af70c8429f9b8bc96104350 \ No newline at end of file diff --git a/Assets/Tests/Sences.meta b/Assets/Tests/Sences.meta deleted file mode 100644 index 53f0200..0000000 --- a/Assets/Tests/Sences.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 77f308e5225109541b47748e59a0fd92 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Tests/Sences/NetworkTestScene.unity b/Assets/Tests/Sences/NetworkTestScene.unity deleted file mode 100644 index 0d1d109..0000000 --- a/Assets/Tests/Sences/NetworkTestScene.unity +++ /dev/null @@ -1,423 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 10 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 3 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 13 - m_BakeOnSceneLoad: 0 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 0 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 3 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - buildHeightMesh: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &519420028 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 519420032} - - component: {fileID: 519420031} - - component: {fileID: 519420029} - - component: {fileID: 519420033} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &519420029 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 519420028} - m_Enabled: 1 ---- !u!20 &519420031 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 519420028} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &519420032 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 519420028} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &519420033 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 519420028} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!1001 &757794372 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 1234567890, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_Name - value: NetworkTestCanvas - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1234567891, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: - - targetCorrespondingSourceObject: {fileID: 1234567890, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - insertIndex: -1 - addedObject: {fileID: 1075127431} - m_SourcePrefab: {fileID: 100100000, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} ---- !u!1 &1075127430 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 1234567890, guid: 39117f8af9ef0d742ac7d549538819b1, type: 3} - m_PrefabInstance: {fileID: 757794372} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1075127431 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1075127430} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!1 &1234567890 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1234567891} - - component: {fileID: 1234567892} - m_Layer: 0 - m_Name: NetworkTestManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1234567891 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1234567892 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0a3e75ea471e5f47b758f5a032a094e, type: 3} - m_Name: - m_EditorClassIdentifier: - testSessionId: test-session-123 - testCharacterId: 44444444-4444-4444-4444-444444444444 - testUserId: bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb - autoTest: 1 - testInterval: 1 ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 519420032} - - {fileID: 1234567891} - - {fileID: 757794372} diff --git a/Assets/Tests/Sences/NetworkTestScene.unity.meta b/Assets/Tests/Sences/NetworkTestScene.unity.meta deleted file mode 100644 index bf59580..0000000 --- a/Assets/Tests/Sences/NetworkTestScene.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6877c3ec4230db044838b9e74fb80cba -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Tests/UI.meta b/Assets/Tests/UI.meta deleted file mode 100644 index 05b6495..0000000 --- a/Assets/Tests/UI.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e536c7952bfc22f49b22d94b7f4dcb8c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Tests/UI/NetworkTestCanvas.prefab b/Assets/Tests/UI/NetworkTestCanvas.prefab deleted file mode 100644 index 6454229..0000000 --- a/Assets/Tests/UI/NetworkTestCanvas.prefab +++ /dev/null @@ -1,221 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &1234567890 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2572838951417541798} - - component: {fileID: 1234567892} - - component: {fileID: 1234567893} - - component: {fileID: 3180861085867238070} - m_Layer: 5 - m_Name: NetworkTestCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2572838951417541798 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1234567896} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!20 &1234567892 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 0 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!223 &1234567893 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 1234567892} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_VertexColorAlwaysGammaSpace: 0 - m_AdditionalShaderChannelsFlag: 0 - m_UpdateRectTransformForStandalone: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!114 &3180861085867238070 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567890} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!1 &1234567894 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1234567896} - - component: {fileID: 9090619396326344028} - m_Layer: 5 - m_Name: TestPanel - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1234567896 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567894} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 2572838951417541798} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &9090619396326344028 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1234567894} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 729ea7f71af70c8429f9b8bc96104350, type: 3} - m_Name: - m_EditorClassIdentifier: - connectButton: {fileID: 0} - disconnectButton: {fileID: 0} - chatRequestButton: {fileID: 0} - characterInfoButton: {fileID: 0} - webSocketMessageButton: {fileID: 0} - fullTestButton: {fileID: 0} - autoTestButton: {fileID: 0} - statusText: {fileID: 0} - logText: {fileID: 0} - logScrollRect: {fileID: 0} - sessionIdInput: {fileID: 0} - characterIdInput: {fileID: 0} - userIdInput: {fileID: 0} - messageInput: {fileID: 0} diff --git a/Assets/Tests/UI/NetworkTestCanvas.prefab.meta b/Assets/Tests/UI/NetworkTestCanvas.prefab.meta deleted file mode 100644 index 48cb39b..0000000 --- a/Assets/Tests/UI/NetworkTestCanvas.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 39117f8af9ef0d742ac7d549538819b1 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json index 22f7d83..0f53190 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,7 +1,5 @@ { "dependencies": { - "com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask", - "com.unity.nuget.newtonsoft-json": "3.2.1", "com.unity.collab-proxy": "2.8.2", "com.unity.feature.2d": "2.0.1", "com.unity.ide.rider": "3.0.36", @@ -42,6 +40,8 @@ "com.unity.modules.unitywebrequestwww": "1.0.0", "com.unity.modules.vehicles": "1.0.0", "com.unity.modules.video": "1.0.0", - "com.unity.modules.wind": "1.0.0" + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" } } diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index c643a11..dc200af 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,12 +1,5 @@ { "dependencies": { - "com.cysharp.unitask": { - "version": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask", - "depth": 0, - "source": "git", - "dependencies": {}, - "hash": "f213ff497e4ff462a77319cf677cf20cc0860ca9" - }, "com.unity.2d.animation": { "version": "10.2.1", "depth": 1, @@ -198,13 +191,6 @@ "dependencies": {}, "url": "https://packages.unity.com" }, - "com.unity.nuget.newtonsoft-json": { - "version": "3.2.1", - "depth": 0, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, "com.unity.render-pipelines.core": { "version": "17.0.4", "depth": 1, @@ -418,6 +404,14 @@ "com.unity.modules.imageconversion": "1.0.0" } }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, "com.unity.modules.terrain": { "version": "1.0.0", "depth": 0, @@ -537,11 +531,31 @@ "com.unity.modules.unitywebrequest": "1.0.0" } }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, "com.unity.modules.wind": { "version": "1.0.0", "depth": 0, "source": "builtin", "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } } } } diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 6286a4b..8c4ad5b 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -776,6 +776,6 @@ PlayerSettings: hmiLoadingImage: {fileID: 0} platformRequiresReadableAssets: 0 virtualTexturingSupportEnabled: 0 - insecureHttpOption: 2 + insecureHttpOption: 0 androidVulkanDenyFilterList: [] androidVulkanAllowFilterList: [] diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json deleted file mode 100644 index ede5887..0000000 --- a/ProjectSettings/SceneTemplateSettings.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "templatePinStates": [], - "dependencyTypeInfos": [ - { - "userAdded": false, - "type": "UnityEngine.AnimationClip", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.Animations.AnimatorController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.AnimatorOverrideController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.Audio.AudioMixerController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.ComputeShader", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Cubemap", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.GameObject", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.LightingDataAsset", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.LightingSettings", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Material", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.MonoScript", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicsMaterial", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicsMaterial2D", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.VolumeProfile", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.SceneAsset", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Shader", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.ShaderVariantCollection", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Texture", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Texture2D", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Timeline.TimelineAsset", - "defaultInstantiationMode": 0 - } - ], - "defaultDependencyTypeInfo": { - "userAdded": false, - "type": "", - "defaultInstantiationMode": 1 - }, - "newSceneOverride": 0 -} \ No newline at end of file