From b3bf7e6eff45d8927403df5c20ac12fb4a748c3b Mon Sep 17 00:00:00 2001 From: logonkhi Date: Tue, 24 Jun 2025 19:29:37 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=95=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20DataValidator=20=EC=B6=94=EA=B0=80,=20HttpPipeLine?= =?UTF-8?q?=20=EC=93=B0=EB=A0=88=EB=93=9C=EC=97=90=EC=84=9C=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Resources/MouseControls.cs | 322 -------- Assets/Resources/MouseControls.cs.meta | 2 - Assets/Resources/MouseControls.inputactions | 134 ---- .../Resources/MouseControls.inputactions.meta | 14 - .../SampleProject/UI/InfoWindow.prefab | 150 +++- Assets/Scenes/SampleProject.unity | 161 +--- Assets/Scenes/Test.unity | 730 ------------------ Assets/Scenes/Test.unity.meta | 7 - Assets/Scenes/Test2.unity | 726 ----------------- Assets/Scenes/Test2.unity.meta | 7 - .../SampleProject/Advanced3DMouseHandler .cs | 394 ---------- .../Advanced3DMouseHandler .cs.meta | 2 - Assets/Scripts/SampleProject/AppMain.cs | 9 +- .../CompleteMouseInputActionsCreator.cs | 142 ---- .../CompleteMouseInputActionsCreator.cs.meta | 2 - .../Scripts/SampleProject/RaycastDebugger.cs | 42 - .../SampleProject/RaycastDebugger.cs.meta | 2 - Assets/Scripts/UVC/Data/DataMapper.cs | 1 + Assets/Scripts/UVC/Data/DataMask.cs | 1 - Assets/Scripts/UVC/Data/DataValidator.cs | 358 +++++++++ Assets/Scripts/UVC/Data/DataValidator.cs.meta | 2 + Assets/Scripts/UVC/Data/HttpPipeLine.cs | 199 ++++- Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs | 95 +++ Assets/Scripts/UVC/Data/MQTTPipeLine.cs | 22 +- Assets/Scripts/UVC/Data/MQTTPipeLineInfo.cs | 80 ++ Assets/Scripts/UVC/Extention/TransformEx.cs | 10 + .../UVC/Factory/Alarm/AlarmUIController.cs | 1 + .../UVC/Factory/Alarm/SingleAlarmIcon.cs | 1 + .../Scripts/UVC/Factory/CameraController.cs | 37 - .../UVC/Factory/CameraController.cs.meta | 2 - Assets/Scripts/UVC/Factory/Component/AGV.cs | 56 +- .../UVC/Factory/Component/ClickTest.cs | 156 ---- .../UVC/Factory/Component/ClickTest.cs.meta | 2 - .../UVC/Factory/Component/FactoryObject.cs | 2 - .../Scripts/UVC/Object3d/InteractiveObject.cs | 13 +- .../UVC/{input.meta => Threading.meta} | 2 +- .../UVC/Threading/MainThreadDispatcher.cs | 218 ++++++ .../Threading/MainThreadDispatcher.cs.meta | 2 + Assets/Scripts/UVC/UI/Info/InfoWindow.cs | 105 ++- Assets/Scripts/UVC/UI/Modal/Modal.cs | 2 +- .../UVC/UI/ToolBar/View/ToolbarView.cs | 2 +- .../Scripts/UVC/UI/Tooltip/TooltipManager.cs | 2 +- Assets/Scripts/UVC/Util/CameraController.cs | 244 ++++++ .../Scripts/UVC/Util/CameraController.cs.meta | 2 + Assets/Scripts/UVC/input/InputHandler.cs | 58 -- Assets/Scripts/UVC/input/InputHandler.cs.meta | 2 - Assets/Scripts/UVC/input/MouseInputHandler.cs | 79 -- .../UVC/input/MouseInputHandler.cs.meta | 2 - Assets/Scripts/UVC/util/CanvasUtil.cs | 2 +- ProjectSettings/EditorBuildSettings.asset | 2 +- 50 files changed, 1544 insertions(+), 3064 deletions(-) delete mode 100644 Assets/Resources/MouseControls.cs delete mode 100644 Assets/Resources/MouseControls.cs.meta delete mode 100644 Assets/Resources/MouseControls.inputactions delete mode 100644 Assets/Resources/MouseControls.inputactions.meta delete mode 100644 Assets/Scenes/Test.unity delete mode 100644 Assets/Scenes/Test.unity.meta delete mode 100644 Assets/Scenes/Test2.unity delete mode 100644 Assets/Scenes/Test2.unity.meta delete mode 100644 Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs delete mode 100644 Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs.meta delete mode 100644 Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs delete mode 100644 Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs.meta delete mode 100644 Assets/Scripts/SampleProject/RaycastDebugger.cs delete mode 100644 Assets/Scripts/SampleProject/RaycastDebugger.cs.meta create mode 100644 Assets/Scripts/UVC/Data/DataValidator.cs create mode 100644 Assets/Scripts/UVC/Data/DataValidator.cs.meta delete mode 100644 Assets/Scripts/UVC/Factory/CameraController.cs delete mode 100644 Assets/Scripts/UVC/Factory/CameraController.cs.meta delete mode 100644 Assets/Scripts/UVC/Factory/Component/ClickTest.cs delete mode 100644 Assets/Scripts/UVC/Factory/Component/ClickTest.cs.meta rename Assets/Scripts/UVC/{input.meta => Threading.meta} (77%) create mode 100644 Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs create mode 100644 Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs.meta create mode 100644 Assets/Scripts/UVC/Util/CameraController.cs create mode 100644 Assets/Scripts/UVC/Util/CameraController.cs.meta delete mode 100644 Assets/Scripts/UVC/input/InputHandler.cs delete mode 100644 Assets/Scripts/UVC/input/InputHandler.cs.meta delete mode 100644 Assets/Scripts/UVC/input/MouseInputHandler.cs delete mode 100644 Assets/Scripts/UVC/input/MouseInputHandler.cs.meta diff --git a/Assets/Resources/MouseControls.cs b/Assets/Resources/MouseControls.cs deleted file mode 100644 index f0c36e17..00000000 --- a/Assets/Resources/MouseControls.cs +++ /dev/null @@ -1,322 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator -// version 1.11.2 -// from Assets/Resources/MouseControls.inputactions -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine.InputSystem; -using UnityEngine.InputSystem.Utilities; - -public partial class @MouseControls: IInputActionCollection2, IDisposable -{ - public InputActionAsset asset { get; } - public @MouseControls() - { - asset = InputActionAsset.FromJson(@"{ - ""name"": ""MouseControls"", - ""maps"": [ - { - ""name"": ""Player"", - ""id"": ""54cc7dab-d206-44e2-ad28-4018586d47ce"", - ""actions"": [ - { - ""name"": ""Click"", - ""type"": ""Button"", - ""id"": ""88d7d766-1007-472e-ae33-ba8569954222"", - ""expectedControlType"": """", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": false - }, - { - ""name"": ""MiddleClick"", - ""type"": ""Button"", - ""id"": ""09456aa4-612d-40bb-b527-6ab97507fa7f"", - ""expectedControlType"": """", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": false - }, - { - ""name"": ""RightClick"", - ""type"": ""Button"", - ""id"": ""adeced83-0144-442e-b0da-51910c88912b"", - ""expectedControlType"": """", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": false - }, - { - ""name"": ""Point"", - ""type"": ""Value"", - ""id"": ""442cf3c8-0613-416e-9e6f-a92ff2058cd0"", - ""expectedControlType"": ""Vector2"", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": true - }, - { - ""name"": ""Scroll"", - ""type"": ""Value"", - ""id"": ""9012f26b-e301-4340-b05f-eaa8ecea5289"", - ""expectedControlType"": ""Vector2"", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": true - }, - { - ""name"": ""Delta"", - ""type"": ""Value"", - ""id"": ""225a6ad6-f6cf-46c1-b522-96bfb4385441"", - ""expectedControlType"": ""Vector2"", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": true - } - ], - ""bindings"": [ - { - ""name"": """", - ""id"": ""35c4559a-a4ae-467f-90ea-21ba08b8a3f3"", - ""path"": ""/leftButton"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""Click"", - ""isComposite"": false, - ""isPartOfComposite"": false - }, - { - ""name"": """", - ""id"": ""35cbe4ff-6de8-4994-8166-9e56a39681cd"", - ""path"": ""/middleButton"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""MiddleClick"", - ""isComposite"": false, - ""isPartOfComposite"": false - }, - { - ""name"": """", - ""id"": ""ee014a6b-bc0d-453c-b2ab-77735da0f5dc"", - ""path"": ""/rightButton"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""RightClick"", - ""isComposite"": false, - ""isPartOfComposite"": false - }, - { - ""name"": """", - ""id"": ""93c1a3dc-8f7b-4471-ac5f-dc651fcab248"", - ""path"": ""/position"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""Point"", - ""isComposite"": false, - ""isPartOfComposite"": false - }, - { - ""name"": """", - ""id"": ""71fb9f61-0b12-464f-b113-bb6bf3e6dcbf"", - ""path"": ""/scroll"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""Scroll"", - ""isComposite"": false, - ""isPartOfComposite"": false - }, - { - ""name"": """", - ""id"": ""85aed182-6406-466b-a222-f7b0f475075b"", - ""path"": ""/delta"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""Delta"", - ""isComposite"": false, - ""isPartOfComposite"": false - } - ] - } - ], - ""controlSchemes"": [] -}"); - // Player - m_Player = asset.FindActionMap("Player", throwIfNotFound: true); - m_Player_Click = m_Player.FindAction("Click", throwIfNotFound: true); - m_Player_MiddleClick = m_Player.FindAction("MiddleClick", throwIfNotFound: true); - m_Player_RightClick = m_Player.FindAction("RightClick", throwIfNotFound: true); - m_Player_Point = m_Player.FindAction("Point", throwIfNotFound: true); - m_Player_Scroll = m_Player.FindAction("Scroll", throwIfNotFound: true); - m_Player_Delta = m_Player.FindAction("Delta", throwIfNotFound: true); - } - - ~@MouseControls() - { - UnityEngine.Debug.Assert(!m_Player.enabled, "This will cause a leak and performance issues, MouseControls.Player.Disable() has not been called."); - } - - public void Dispose() - { - UnityEngine.Object.Destroy(asset); - } - - public InputBinding? bindingMask - { - get => asset.bindingMask; - set => asset.bindingMask = value; - } - - public ReadOnlyArray? devices - { - get => asset.devices; - set => asset.devices = value; - } - - public ReadOnlyArray controlSchemes => asset.controlSchemes; - - public bool Contains(InputAction action) - { - return asset.Contains(action); - } - - public IEnumerator GetEnumerator() - { - return asset.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Enable() - { - asset.Enable(); - } - - public void Disable() - { - asset.Disable(); - } - - public IEnumerable bindings => asset.bindings; - - public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) - { - return asset.FindAction(actionNameOrId, throwIfNotFound); - } - - public int FindBinding(InputBinding bindingMask, out InputAction action) - { - return asset.FindBinding(bindingMask, out action); - } - - // Player - private readonly InputActionMap m_Player; - private List m_PlayerActionsCallbackInterfaces = new List(); - private readonly InputAction m_Player_Click; - private readonly InputAction m_Player_MiddleClick; - private readonly InputAction m_Player_RightClick; - private readonly InputAction m_Player_Point; - private readonly InputAction m_Player_Scroll; - private readonly InputAction m_Player_Delta; - public struct PlayerActions - { - private @MouseControls m_Wrapper; - public PlayerActions(@MouseControls wrapper) { m_Wrapper = wrapper; } - public InputAction @Click => m_Wrapper.m_Player_Click; - public InputAction @MiddleClick => m_Wrapper.m_Player_MiddleClick; - public InputAction @RightClick => m_Wrapper.m_Player_RightClick; - public InputAction @Point => m_Wrapper.m_Player_Point; - public InputAction @Scroll => m_Wrapper.m_Player_Scroll; - public InputAction @Delta => m_Wrapper.m_Player_Delta; - public InputActionMap Get() { return m_Wrapper.m_Player; } - public void Enable() { Get().Enable(); } - public void Disable() { Get().Disable(); } - public bool enabled => Get().enabled; - public static implicit operator InputActionMap(PlayerActions set) { return set.Get(); } - public void AddCallbacks(IPlayerActions instance) - { - if (instance == null || m_Wrapper.m_PlayerActionsCallbackInterfaces.Contains(instance)) return; - m_Wrapper.m_PlayerActionsCallbackInterfaces.Add(instance); - @Click.started += instance.OnClick; - @Click.performed += instance.OnClick; - @Click.canceled += instance.OnClick; - @MiddleClick.started += instance.OnMiddleClick; - @MiddleClick.performed += instance.OnMiddleClick; - @MiddleClick.canceled += instance.OnMiddleClick; - @RightClick.started += instance.OnRightClick; - @RightClick.performed += instance.OnRightClick; - @RightClick.canceled += instance.OnRightClick; - @Point.started += instance.OnPoint; - @Point.performed += instance.OnPoint; - @Point.canceled += instance.OnPoint; - @Scroll.started += instance.OnScroll; - @Scroll.performed += instance.OnScroll; - @Scroll.canceled += instance.OnScroll; - @Delta.started += instance.OnDelta; - @Delta.performed += instance.OnDelta; - @Delta.canceled += instance.OnDelta; - } - - private void UnregisterCallbacks(IPlayerActions instance) - { - @Click.started -= instance.OnClick; - @Click.performed -= instance.OnClick; - @Click.canceled -= instance.OnClick; - @MiddleClick.started -= instance.OnMiddleClick; - @MiddleClick.performed -= instance.OnMiddleClick; - @MiddleClick.canceled -= instance.OnMiddleClick; - @RightClick.started -= instance.OnRightClick; - @RightClick.performed -= instance.OnRightClick; - @RightClick.canceled -= instance.OnRightClick; - @Point.started -= instance.OnPoint; - @Point.performed -= instance.OnPoint; - @Point.canceled -= instance.OnPoint; - @Scroll.started -= instance.OnScroll; - @Scroll.performed -= instance.OnScroll; - @Scroll.canceled -= instance.OnScroll; - @Delta.started -= instance.OnDelta; - @Delta.performed -= instance.OnDelta; - @Delta.canceled -= instance.OnDelta; - } - - public void RemoveCallbacks(IPlayerActions instance) - { - if (m_Wrapper.m_PlayerActionsCallbackInterfaces.Remove(instance)) - UnregisterCallbacks(instance); - } - - public void SetCallbacks(IPlayerActions instance) - { - foreach (var item in m_Wrapper.m_PlayerActionsCallbackInterfaces) - UnregisterCallbacks(item); - m_Wrapper.m_PlayerActionsCallbackInterfaces.Clear(); - AddCallbacks(instance); - } - } - public PlayerActions @Player => new PlayerActions(this); - public interface IPlayerActions - { - void OnClick(InputAction.CallbackContext context); - void OnMiddleClick(InputAction.CallbackContext context); - void OnRightClick(InputAction.CallbackContext context); - void OnPoint(InputAction.CallbackContext context); - void OnScroll(InputAction.CallbackContext context); - void OnDelta(InputAction.CallbackContext context); - } -} diff --git a/Assets/Resources/MouseControls.cs.meta b/Assets/Resources/MouseControls.cs.meta deleted file mode 100644 index d3a3c76e..00000000 --- a/Assets/Resources/MouseControls.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 877be50a84cd10a4cbe2017ee11c86e7 \ No newline at end of file diff --git a/Assets/Resources/MouseControls.inputactions b/Assets/Resources/MouseControls.inputactions deleted file mode 100644 index 05671a1c..00000000 --- a/Assets/Resources/MouseControls.inputactions +++ /dev/null @@ -1,134 +0,0 @@ -{ - "name": "MouseControls", - "maps": [ - { - "name": "Player", - "id": "54cc7dab-d206-44e2-ad28-4018586d47ce", - "actions": [ - { - "name": "Click", - "type": "Button", - "id": "88d7d766-1007-472e-ae33-ba8569954222", - "expectedControlType": "", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "MiddleClick", - "type": "Button", - "id": "09456aa4-612d-40bb-b527-6ab97507fa7f", - "expectedControlType": "", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "RightClick", - "type": "Button", - "id": "adeced83-0144-442e-b0da-51910c88912b", - "expectedControlType": "", - "processors": "", - "interactions": "", - "initialStateCheck": false - }, - { - "name": "Point", - "type": "Value", - "id": "442cf3c8-0613-416e-9e6f-a92ff2058cd0", - "expectedControlType": "Vector2", - "processors": "", - "interactions": "", - "initialStateCheck": true - }, - { - "name": "Scroll", - "type": "Value", - "id": "9012f26b-e301-4340-b05f-eaa8ecea5289", - "expectedControlType": "Vector2", - "processors": "", - "interactions": "", - "initialStateCheck": true - }, - { - "name": "Delta", - "type": "Value", - "id": "225a6ad6-f6cf-46c1-b522-96bfb4385441", - "expectedControlType": "Vector2", - "processors": "", - "interactions": "", - "initialStateCheck": true - } - ], - "bindings": [ - { - "name": "", - "id": "35c4559a-a4ae-467f-90ea-21ba08b8a3f3", - "path": "/leftButton", - "interactions": "", - "processors": "", - "groups": "", - "action": "Click", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "35cbe4ff-6de8-4994-8166-9e56a39681cd", - "path": "/middleButton", - "interactions": "", - "processors": "", - "groups": "", - "action": "MiddleClick", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "ee014a6b-bc0d-453c-b2ab-77735da0f5dc", - "path": "/rightButton", - "interactions": "", - "processors": "", - "groups": "", - "action": "RightClick", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "93c1a3dc-8f7b-4471-ac5f-dc651fcab248", - "path": "/position", - "interactions": "", - "processors": "", - "groups": "", - "action": "Point", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "71fb9f61-0b12-464f-b113-bb6bf3e6dcbf", - "path": "/scroll", - "interactions": "", - "processors": "", - "groups": "", - "action": "Scroll", - "isComposite": false, - "isPartOfComposite": false - }, - { - "name": "", - "id": "85aed182-6406-466b-a222-f7b0f475075b", - "path": "/delta", - "interactions": "", - "processors": "", - "groups": "", - "action": "Delta", - "isComposite": false, - "isPartOfComposite": false - } - ] - } - ], - "controlSchemes": [] -} \ No newline at end of file diff --git a/Assets/Resources/MouseControls.inputactions.meta b/Assets/Resources/MouseControls.inputactions.meta deleted file mode 100644 index 8bd9cf83..00000000 --- a/Assets/Resources/MouseControls.inputactions.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: 8dd849bbe0fdebe4b839f518c31e21ab -ScriptedImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 2 - userData: - assetBundleName: - assetBundleVariant: - script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3} - generateWrapperCode: 1 - wrapperCodePath: - wrapperClassName: - wrapperCodeNamespace: diff --git a/Assets/Resources/Prefabs/SampleProject/UI/InfoWindow.prefab b/Assets/Resources/Prefabs/SampleProject/UI/InfoWindow.prefab index 05abc137..319795c7 100644 --- a/Assets/Resources/Prefabs/SampleProject/UI/InfoWindow.prefab +++ b/Assets/Resources/Prefabs/SampleProject/UI/InfoWindow.prefab @@ -133,6 +133,142 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2480dc463c63bf945a9488183ffe66d0, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!1 &695708929815469789 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7457226219413938759} + - component: {fileID: 4416386235926923171} + - component: {fileID: 7184852704645535964} + m_Layer: 5 + m_Name: ValueText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7457226219413938759 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 695708929815469789} + 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: 4802890858156259540} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 45, y: -7.5} + m_SizeDelta: {x: -100, y: -25} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4416386235926923171 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 695708929815469789} + m_CullTransparentMesh: 1 +--- !u!114 &7184852704645535964 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 695708929815469789} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: New Text + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2} + m_sharedMaterial: {fileID: 4860575619018115804, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4278190080 + m_fontColor: {r: 0, g: 0, b: 0, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 10 + m_fontSizeBase: 10 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 4 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} --- !u!1 &1267781917027001920 GameObject: m_ObjectHideFlags: 0 @@ -317,12 +453,13 @@ RectTransform: - {fileID: 2993317773174661490} - {fileID: 6308980257678838100} - {fileID: 6685372230643413407} + - {fileID: 7457226219413938759} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 100, y: 150} + m_SizeDelta: {x: 200, y: 150} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &7623125061856383678 CanvasRenderer: @@ -344,9 +481,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 620e52b408949c340adef1110323cb7c, type: 3} m_Name: m_EditorClassIdentifier: - infoText: {fileID: 4202672738064507978} + labelText: {fileID: 4202672738064507978} + valueText: {fileID: 7184852704645535964} closeButton: {fileID: 5925304901667948221} - worldOffset: {x: 0, y: 1.5, z: 0} + screenOffset: {x: 0, y: 0} --- !u!1 &7346391167643616437 GameObject: m_ObjectHideFlags: 0 @@ -359,7 +497,7 @@ GameObject: - component: {fileID: 9166711732528497215} - component: {fileID: 4202672738064507978} m_Layer: 5 - m_Name: Text (TMP) + m_Name: 'LabelText ' m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -381,8 +519,8 @@ RectTransform: 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: -7.5} - m_SizeDelta: {x: -10, y: -25} + m_AnchoredPosition: {x: -52.5, y: -7.5} + m_SizeDelta: {x: -115, y: -25} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &9166711732528497215 CanvasRenderer: diff --git a/Assets/Scenes/SampleProject.unity b/Assets/Scenes/SampleProject.unity index 9c100003..af0c41de 100644 --- a/Assets/Scenes/SampleProject.unity +++ b/Assets/Scenes/SampleProject.unity @@ -119,127 +119,6 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} ---- !u!1 &22597646 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 22597650} - - component: {fileID: 22597649} - - component: {fileID: 22597648} - - component: {fileID: 22597647} - - component: {fileID: 22597651} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &22597647 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 22597646} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &22597648 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 22597646} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &22597649 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 22597646} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &22597650 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 22597646} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 78.07, y: 31.6, z: -6.41} - 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 &22597651 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 22597646} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 2bf81994712147c45b75b5394f2b0aca, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &27812497 GameObject: m_ObjectHideFlags: 0 @@ -256,7 +135,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!4 &27812499 Transform: m_ObjectHideFlags: 0 @@ -553,11 +432,12 @@ MonoBehaviour: m_GameObject: {fileID: 330585543} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 1261d9494e4176a488c4e65b80396de6, type: 3} + m_Script: {fileID: 11500000, guid: 61deddb674c074049a9b43fd58f1b355, type: 3} m_Name: m_EditorClassIdentifier: - moveSpeed: 5 - rotateSpeed: 100 + panSpeed: 20 + rotationSpeed: 300 + zoomSpeed: 10 --- !u!1 &410087039 GameObject: m_ObjectHideFlags: 0 @@ -697,7 +577,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!114 &483439348 MonoBehaviour: m_ObjectHideFlags: 0 @@ -759,7 +639,7 @@ Canvas: m_AdditionalShaderChannelsFlag: 25 m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 - m_SortingOrder: 0 + m_SortingOrder: 1 m_TargetDisplay: 0 --- !u!224 &483439351 RectTransform: @@ -803,7 +683,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!114 &495653795 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1873,7 +1753,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!114 &2030316709 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1935,7 +1815,7 @@ Canvas: m_AdditionalShaderChannelsFlag: 25 m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 - m_SortingOrder: 1 + m_SortingOrder: 0 m_TargetDisplay: 0 --- !u!224 &2030316712 RectTransform: @@ -1965,6 +1845,22 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 2030316712} m_Modifications: + - target: {fileID: 3914245719037572856, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} + propertyPath: worldOffset.x + value: 60 + objectReference: {fileID: 0} + - target: {fileID: 3914245719037572856, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} + propertyPath: worldOffset.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3914245719037572856, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} + propertyPath: screenOffset.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3914245719037572856, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} + propertyPath: screenOffset.y + value: 0 + objectReference: {fileID: 0} - target: {fileID: 4802890858156259540, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} propertyPath: m_Pivot.x value: 0.5 @@ -1991,7 +1887,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 4802890858156259540, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} propertyPath: m_SizeDelta.x - value: 100 + value: 200 objectReference: {fileID: 0} - target: {fileID: 4802890858156259540, guid: 036e56b4c097fc8409ffced10ff53562, type: 3} propertyPath: m_SizeDelta.y @@ -2164,9 +2060,8 @@ SceneRoots: - {fileID: 832575519} - {fileID: 632541407} - {fileID: 27812499} - - {fileID: 483439351} - {fileID: 2030316712} + - {fileID: 483439351} - {fileID: 495653798} - {fileID: 88083293} - {fileID: 1840728471} - - {fileID: 22597650} diff --git a/Assets/Scenes/Test.unity b/Assets/Scenes/Test.unity deleted file mode 100644 index 05be66c4..00000000 --- a/Assets/Scenes/Test.unity +++ /dev/null @@ -1,730 +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: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 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: 1 - 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: 1 - m_PVRFilteringGaussRadiusAO: 1 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 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 &622444010 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 622444014} - - component: {fileID: 622444013} - - component: {fileID: 622444012} - - component: {fileID: 622444011} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &622444011 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 622444010} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &622444012 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 622444010} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &622444013 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 622444010} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &622444014 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 622444010} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.62991, y: 1.83499, z: -3.87921} - 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!1 &1287244951 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1287244955} - - component: {fileID: 1287244954} - - component: {fileID: 1287244953} - - component: {fileID: 1287244952} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1287244952 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1287244951} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1287244953 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1287244951} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &1287244954 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1287244951} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1287244955 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1287244951} - 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!1 &1458109596 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1458109600} - - component: {fileID: 1458109599} - - component: {fileID: 1458109598} - - component: {fileID: 1458109597} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!64 &1458109597 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1458109596} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 5 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &1458109598 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1458109596} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &1458109599 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1458109596} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1458109600 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1458109596} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.62991, y: -0.8, z: -3.87921} - 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!1 &1497370464 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1497370467} - - component: {fileID: 1497370466} - - component: {fileID: 1497370465} - - component: {fileID: 1497370468} - - component: {fileID: 1497370471} - 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 &1497370465 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1497370464} - m_Enabled: 1 ---- !u!20 &1497370466 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1497370464} - 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!224 &1497370467 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1497370464} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, 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} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 1} - m_SizeDelta: {x: 100, y: 100} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1497370468 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1497370464} - 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!114 &1497370471 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1497370464} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9958aa39fc037e74090efe980e62c959, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &1990717422 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1990717424} - - component: {fileID: 1990717423} - - component: {fileID: 1990717425} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1990717423 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1990717422} - m_Enabled: 1 - serializedVersion: 11 - m_Type: 1 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ForceVisible: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 - m_LightUnit: 1 - m_LuxAtDistance: 1 - m_EnableSpotReflector: 1 ---- !u!4 &1990717424 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1990717422} - serializedVersion: 2 - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!114 &1990717425 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1990717422} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Version: 3 - m_UsePipelineSettings: 1 - m_AdditionalLightsShadowResolutionTier: 2 - m_LightLayerMask: 1 - m_RenderingLayers: 1 - m_CustomShadowLayers: 0 - m_ShadowLayerMask: 1 - m_ShadowRenderingLayers: 1 - m_LightCookieSize: {x: 1, y: 1} - m_LightCookieOffset: {x: 0, y: 0} - m_SoftShadowQuality: 0 ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 1990717424} - - {fileID: 1497370467} - - {fileID: 1287244955} - - {fileID: 622444014} - - {fileID: 1458109600} diff --git a/Assets/Scenes/Test.unity.meta b/Assets/Scenes/Test.unity.meta deleted file mode 100644 index 6dc27fd1..00000000 --- a/Assets/Scenes/Test.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 803083c453114db4abb44bd90dfdab50 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scenes/Test2.unity b/Assets/Scenes/Test2.unity deleted file mode 100644 index 189582c3..00000000 --- a/Assets/Scenes/Test2.unity +++ /dev/null @@ -1,726 +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: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 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: 1 - 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: 1 - m_PVRFilteringGaussRadiusAO: 1 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 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 &279343782 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 279343785} - - component: {fileID: 279343784} - - component: {fileID: 279343783} - - component: {fileID: 279343786} - - component: {fileID: 279343787} - 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 &279343783 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279343782} - m_Enabled: 1 ---- !u!20 &279343784 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279343782} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 2 - 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: 20.78461 - 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.000004 - 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 &279343785 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279343782} - 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 &279343786 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279343782} - 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!114 &279343787 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279343782} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9958aa39fc037e74090efe980e62c959, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &359294470 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 359294474} - - component: {fileID: 359294473} - - component: {fileID: 359294472} - - component: {fileID: 359294471} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!64 &359294471 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 359294470} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 5 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &359294472 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 359294470} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &359294473 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 359294470} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &359294474 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 359294470} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.6299052, y: 0.44, z: -3.8792126} - 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!1 &496775621 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 496775625} - - component: {fileID: 496775624} - - component: {fileID: 496775623} - - component: {fileID: 496775622} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &496775622 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 496775621} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &496775623 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 496775621} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &496775624 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 496775621} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &496775625 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 496775621} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 1.02, y: 1.834987, z: -3.8792126} - 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!1 &931183989 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 931183993} - - component: {fileID: 931183992} - - component: {fileID: 931183991} - - component: {fileID: 931183990} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &931183990 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 931183989} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 1 - serializedVersion: 3 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &931183991 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 931183989} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &931183992 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 931183989} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &931183993 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 931183989} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.6299052, y: 1.834987, z: -3.8792126} - 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!1 &1408564287 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1408564289} - - component: {fileID: 1408564288} - - component: {fileID: 1408564290} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1408564288 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1408564287} - m_Enabled: 1 - serializedVersion: 11 - m_Type: 1 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ForceVisible: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 - m_LightUnit: 1 - m_LuxAtDistance: 1 - m_EnableSpotReflector: 1 ---- !u!4 &1408564289 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1408564287} - serializedVersion: 2 - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!114 &1408564290 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1408564287} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Version: 3 - m_UsePipelineSettings: 1 - m_AdditionalLightsShadowResolutionTier: 2 - m_LightLayerMask: 1 - m_RenderingLayers: 1 - m_CustomShadowLayers: 0 - m_ShadowLayerMask: 1 - m_ShadowRenderingLayers: 1 - m_LightCookieSize: {x: 1, y: 1} - m_LightCookieOffset: {x: 0, y: 0} - m_SoftShadowQuality: 0 ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 279343785} - - {fileID: 1408564289} - - {fileID: 931183993} - - {fileID: 496775625} - - {fileID: 359294474} diff --git a/Assets/Scenes/Test2.unity.meta b/Assets/Scenes/Test2.unity.meta deleted file mode 100644 index e9734a24..00000000 --- a/Assets/Scenes/Test2.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: aa0ed8397d304514c9995a8873897e41 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs b/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs deleted file mode 100644 index 5d942811..00000000 --- a/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs +++ /dev/null @@ -1,394 +0,0 @@ -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.InputSystem; - -public class Advanced3DMouseHandler : MonoBehaviour, - IPointerClickHandler, - IPointerDownHandler, - IPointerUpHandler, - IPointerEnterHandler, - IPointerExitHandler, - IBeginDragHandler, - IDragHandler, - IEndDragHandler -{ - [Header("마우스 이벤트 설정")] - [SerializeField] private bool enableHover = true; - [SerializeField] private bool enableDrag = true; - [SerializeField] private bool enableClick = true; - - [Header("드래그 설정")] - [SerializeField] private float dragSensitivity = 1f; - [SerializeField] private bool constrainToScreen = true; - [SerializeField] private bool returnToOriginalPosition = false; - - [Header("시각적 피드백")] - [SerializeField] private Color normalColor = Color.white; - [SerializeField] private Color hoverColor = Color.yellow; - [SerializeField] private Color dragColor = Color.blue; - [SerializeField] private Color clickColor = Color.red; - - [Header("디버그")] - [SerializeField] private bool showDebugLogs = true; - - // 컴포넌트 참조 - private Renderer objectRenderer; - private Color originalColor; - - // 드래그 관련 - private bool isDragging = false; - private Vector3 originalPosition; - private Vector3 dragOffset; - private Camera mainCamera; - - // 이벤트 델리게이트 - public System.Action OnClickEvent; - public System.Action OnHoverEnterEvent; - public System.Action OnHoverExitEvent; - public System.Action OnBeginDragEvent; - public System.Action OnDragEvent; - public System.Action OnEndDragEvent; - - void Start() - { - InitializeComponents(); - ValidateInputSystem(); - } - - void InitializeComponents() - { - objectRenderer = GetComponent(); - if (objectRenderer != null) - { - originalColor = objectRenderer.material.color; - } - - originalPosition = transform.position; - mainCamera = Camera.main; - - // Collider 확인 - if (GetComponent() == null) - { - gameObject.AddComponent(); - if (showDebugLogs) Debug.Log($"✓ {gameObject.name}에 BoxCollider 추가됨"); - } - } - - void ValidateInputSystem() - { - if (showDebugLogs) - { - Debug.Log($"=== {gameObject.name} Input System 검증 ==="); - - // Input System의 Mouse Delta 확인 - if (Mouse.current != null) - { - Debug.Log("✓ Mouse Input Device 감지됨"); - Debug.Log($" 현재 마우스 위치: {Mouse.current.position.ReadValue()}"); - } - else - { - Debug.LogWarning("❌ Mouse Input Device를 찾을 수 없음"); - } - } - } - - #region IPointer 인터페이스 구현 - - public void OnPointerClick(PointerEventData eventData) - { - if (!enableClick) return; - - if (showDebugLogs) - { - Debug.Log($"🖱️ {gameObject.name} 클릭됨!"); - Debug.Log($" 버튼: {eventData.button}"); - Debug.Log($" 위치: {eventData.position}"); - } - - OnClickEvent?.Invoke(eventData); - - // 클릭 효과 - if (objectRenderer != null) - { - StartCoroutine(ClickEffect()); - } - } - - public void OnPointerDown(PointerEventData eventData) - { - if (showDebugLogs) - { - Debug.Log($"⬇️ {gameObject.name} 마우스 다운"); - } - - if (objectRenderer != null) - { - objectRenderer.material.color = clickColor; - } - } - - public void OnPointerUp(PointerEventData eventData) - { - if (showDebugLogs) - { - Debug.Log($"⬆️ {gameObject.name} 마우스 업"); - } - - if (!isDragging && objectRenderer != null) - { - objectRenderer.material.color = hoverColor; - } - } - - public void OnPointerEnter(PointerEventData eventData) - { - if (!enableHover) return; - - if (showDebugLogs) - { - Debug.Log($"➡️ {gameObject.name} 마우스 진입"); - Debug.Log($" 마우스 위치: {eventData.position}"); - Debug.Log($" 월드 위치: {eventData.pointerCurrentRaycast.worldPosition}"); - } - - OnHoverEnterEvent?.Invoke(eventData); - - if (objectRenderer != null && !isDragging) - { - objectRenderer.material.color = hoverColor; - } - - // 커서 변경 (옵션) - Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto); - } - - public void OnPointerExit(PointerEventData eventData) - { - if (!enableHover) return; - - if (showDebugLogs) - { - Debug.Log($"⬅️ {gameObject.name} 마우스 벗어남"); - } - - OnHoverExitEvent?.Invoke(eventData); - - if (objectRenderer != null && !isDragging) - { - objectRenderer.material.color = originalColor; - } - } - - public void OnBeginDrag(PointerEventData eventData) - { - if (!enableDrag) return; - - isDragging = true; - - if (showDebugLogs) - { - Debug.Log($"🔄 {gameObject.name} 드래그 시작"); - Debug.Log($" 시작 위치: {eventData.position}"); - } - - OnBeginDragEvent?.Invoke(eventData); - - // 드래그 시작 시 오프셋 계산 - if (mainCamera != null) - { - Vector3 screenPoint = mainCamera.WorldToScreenPoint(transform.position); - dragOffset = transform.position - mainCamera.ScreenToWorldPoint( - new Vector3(eventData.position.x, eventData.position.y, screenPoint.z)); - } - - if (objectRenderer != null) - { - objectRenderer.material.color = dragColor; - } - } - - public void OnDrag(PointerEventData eventData) - { - if (!enableDrag || !isDragging) return; - - if (showDebugLogs && Time.frameCount % 10 == 0) // 로그 스팸 방지 - { - Debug.Log($"🔄 {gameObject.name} 드래그 중"); - Debug.Log($" 현재 위치: {eventData.position}"); - Debug.Log($" 델타: {eventData.delta}"); - } - - OnDragEvent?.Invoke(eventData); - - // 드래그에 따른 위치 업데이트 - UpdateDragPosition(eventData); - } - - public void OnEndDrag(PointerEventData eventData) - { - if (!enableDrag) return; - - if (showDebugLogs) - { - Debug.Log($"🔄 {gameObject.name} 드래그 종료"); - Debug.Log($" 최종 위치: {eventData.position}"); - } - - OnEndDragEvent?.Invoke(eventData); - - isDragging = false; - - // 원래 위치로 돌아가기 (옵션) - if (returnToOriginalPosition) - { - StartCoroutine(ReturnToOriginalPosition()); - } - - if (objectRenderer != null) - { - objectRenderer.material.color = originalColor; - } - } - - #endregion - - #region 드래그 처리 메서드 - - void UpdateDragPosition(PointerEventData eventData) - { - if (mainCamera == null) return; - - // 화면 좌표를 월드 좌표로 변환 - Vector3 screenPoint = new Vector3(eventData.position.x, eventData.position.y, - mainCamera.WorldToScreenPoint(transform.position).z); - Vector3 worldPoint = mainCamera.ScreenToWorldPoint(screenPoint); - - // 드래그 감도 적용 - Vector3 targetPosition = worldPoint + dragOffset; - targetPosition = Vector3.Lerp(transform.position, targetPosition, dragSensitivity * Time.deltaTime * 10f); - - // 화면 밖으로 나가지 않도록 제한 (옵션) - if (constrainToScreen) - { - targetPosition = ConstrainToScreen(targetPosition); - } - - transform.position = targetPosition; - } - - Vector3 ConstrainToScreen(Vector3 worldPosition) - { - if (mainCamera == null) return worldPosition; - - // 월드 위치를 화면 좌표로 변환 - Vector3 screenPos = mainCamera.WorldToScreenPoint(worldPosition); - - // 화면 경계 내로 제한 - screenPos.x = Mathf.Clamp(screenPos.x, 0, Screen.width); - screenPos.y = Mathf.Clamp(screenPos.y, 0, Screen.height); - - // 다시 월드 좌표로 변환 - return mainCamera.ScreenToWorldPoint(screenPos); - } - - System.Collections.IEnumerator ReturnToOriginalPosition() - { - float elapsedTime = 0f; - float duration = 0.5f; - Vector3 startPosition = transform.position; - - while (elapsedTime < duration) - { - transform.position = Vector3.Lerp(startPosition, originalPosition, elapsedTime / duration); - elapsedTime += Time.deltaTime; - yield return null; - } - - transform.position = originalPosition; - } - - System.Collections.IEnumerator ClickEffect() - { - if (objectRenderer == null) yield break; - - Color startColor = objectRenderer.material.color; - - // 클릭 색상으로 변경 - objectRenderer.material.color = clickColor; - yield return new WaitForSeconds(0.1f); - - // 원래 색상으로 복원 - objectRenderer.material.color = startColor; - } - - #endregion - - #region 공개 메서드 - - public void SetDragEnabled(bool enabled) - { - enableDrag = enabled; - } - - public void SetHoverEnabled(bool enabled) - { - enableHover = enabled; - } - - public void SetClickEnabled(bool enabled) - { - enableClick = enabled; - } - - public void ResetPosition() - { - transform.position = originalPosition; - } - - public void SetColors(Color normal, Color hover, Color drag, Color click) - { - normalColor = normal; - hoverColor = hover; - dragColor = drag; - clickColor = click; - originalColor = normal; - - if (objectRenderer != null && !isDragging) - { - objectRenderer.material.color = normal; - } - } - - #endregion - - #region 디버그 메서드 - - void Update() - { - // 실시간 마우스 입력 모니터링 (디버그용) - if (showDebugLogs && Input.GetKeyDown(KeyCode.F3)) - { - ShowMouseInputStatus(); - } - } - - void ShowMouseInputStatus() - { - Debug.Log("=== 실시간 마우스 입력 상태 ==="); - - if (Mouse.current != null) - { - Debug.Log($"마우스 위치: {Mouse.current.position.ReadValue()}"); - Debug.Log($"마우스 델타: {Mouse.current.delta.ReadValue()}"); - Debug.Log($"좌클릭 상태: {Mouse.current.leftButton.isPressed}"); - Debug.Log($"우클릭 상태: {Mouse.current.rightButton.isPressed}"); - } - - Debug.Log($"현재 객체 상태:"); - Debug.Log($" 드래그 중: {isDragging}"); - Debug.Log($" 위치: {transform.position}"); - } - - #endregion -} \ No newline at end of file diff --git a/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs.meta b/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs.meta deleted file mode 100644 index 2ef3aca7..00000000 --- a/Assets/Scripts/SampleProject/Advanced3DMouseHandler .cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: ebbb4a29a8f33384d9fe56b7ce205040 \ No newline at end of file diff --git a/Assets/Scripts/SampleProject/AppMain.cs b/Assets/Scripts/SampleProject/AppMain.cs index 58ccfaee..5bd7fb0d 100644 --- a/Assets/Scripts/SampleProject/AppMain.cs +++ b/Assets/Scripts/SampleProject/AppMain.cs @@ -1,3 +1,4 @@ +using Cysharp.Threading.Tasks; using System; using UnityEngine; using UVC.Core; @@ -50,7 +51,13 @@ namespace SampleProject mqttPipeLine = new MQTTPipeLine("localhost", 1883); mqttPipeLine.AddTopic("AGV"); - //mqttPipeLine.Execute(); + mqttPipeLine.Execute(); + + //10 + UniTask.Delay(TimeSpan.FromSeconds(10)).ContinueWith(() => + { + mqttPipeLine.Stop(); + }); } } diff --git a/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs b/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs deleted file mode 100644 index ec01f494..00000000 --- a/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs +++ /dev/null @@ -1,142 +0,0 @@ -using UnityEngine; -using UnityEngine.InputSystem; -using UnityEngine.InputSystem.UI; -using UnityEngine.EventSystems; - -public class CompleteMouseInputActionsCreator : MonoBehaviour -{ - [ContextMenu("Create Complete Mouse Input Actions")] - void CreateCompleteMouseInputActions() - { - var asset = ScriptableObject.CreateInstance(); - asset.name = "CompleteMouseUIInputActions"; - - // UI Action Map 생성 - var uiMap = asset.AddActionMap("UI"); - - // 1. Point Action (마우스 위치 추적) - var pointAction = uiMap.AddAction("Point", InputActionType.PassThrough); - pointAction.expectedControlType = "Vector2"; // 마우스 위치는 Vector2 타입 - pointAction.AddBinding("/position"); - pointAction.AddBinding("/position"); - pointAction.AddBinding("/touch*/position"); - - // 2. Left Click Action - var leftClickAction = uiMap.AddAction("LeftClick", InputActionType.Button); - leftClickAction.AddBinding("/leftButton"); - leftClickAction.AddBinding("/tip"); - leftClickAction.AddBinding("/touch*/press"); - - // 3. Right Click Action - var rightClickAction = uiMap.AddAction("RightClick", InputActionType.Button); - rightClickAction.AddBinding("/rightButton"); - rightClickAction.AddBinding("/barrel"); - - // 4. Middle Click Action - var middleClickAction = uiMap.AddAction("MiddleClick", InputActionType.Button); - middleClickAction.AddBinding("/middleButton"); - - // 5. Scroll Wheel Action - var scrollAction = uiMap.AddAction("ScrollWheel", InputActionType.PassThrough); - pointAction.expectedControlType = "Vector2"; - scrollAction.AddBinding("/scroll"); - - // 6. Mouse Delta (드래그용) - var mouseDeltaAction = uiMap.AddAction("MouseDelta", InputActionType.PassThrough); - mouseDeltaAction.expectedControlType = "Vector2"; // 마우스 이동은 Vector2 타입 - mouseDeltaAction.AddBinding("/delta"); - mouseDeltaAction.AddBinding("/delta"); - mouseDeltaAction.AddBinding("/touch*/delta"); - - // 7. Drag Action (드래그 감지용) - var dragAction = uiMap.AddAction("Drag", InputActionType.PassThrough); - dragAction.expectedControlType = "Vector2"; - // 드래그는 마우스 버튼이 눌린 상태에서의 마우스 이동을 감지 - // Composite Binding을 사용하여 복합 입력 생성 - var dragComposite = dragAction.AddCompositeBinding("Vector2"); - dragComposite.With("x", "/delta/x"); - dragComposite.With("y", "/delta/y"); - - // 8. Submit Action (엔터, 스페이스) - var submitAction = uiMap.AddAction("Submit", InputActionType.Button); - submitAction.AddBinding("/enter"); - submitAction.AddBinding("/space"); - submitAction.AddBinding("/buttonSouth"); - - // 9. Cancel Action (ESC) - var cancelAction = uiMap.AddAction("Cancel", InputActionType.Button); - cancelAction.AddBinding("/escape"); - cancelAction.AddBinding("/buttonEast"); - - // 10. Navigate Action (방향키) - var navigateAction = uiMap.AddAction("Navigate", InputActionType.PassThrough); - navigateAction.expectedControlType = "Vector2"; // 방향키 입력은 Vector2 타입 - navigateAction.AddBinding("/arrowKeys"); - navigateAction.AddBinding("/leftStick"); - navigateAction.AddBinding("/dpad"); - - Debug.Log("✓ 완전한 마우스 Input Actions Asset 생성 완료"); - - // Event System에 자동 할당 - AutoAssignToInputModule(asset); - - // 파일로 저장 (에디터에서만) -#if UNITY_EDITOR - SaveAssetToFile(asset); -#endif - } - - void AutoAssignToInputModule(InputActionAsset asset) - { - var eventSystem = FindObjectOfType(); - if (eventSystem == null) - { - var go = new GameObject("EventSystem"); - eventSystem = go.AddComponent(); - } - - var inputModule = eventSystem.GetComponent(); - if (inputModule == null) - { - // 기존 Input Module 제거 - var oldModule = eventSystem.GetComponent(); - if (oldModule != null) - { - DestroyImmediate(oldModule); - } - - inputModule = eventSystem.gameObject.AddComponent(); - } - - // Actions Asset 및 Action References 할당 - inputModule.actionsAsset = asset; - - var uiMap = asset.FindActionMap("UI"); - if (uiMap != null) - { - inputModule.point = InputActionReference.Create(uiMap.FindAction("Point")); - inputModule.leftClick = InputActionReference.Create(uiMap.FindAction("LeftClick")); - inputModule.rightClick = InputActionReference.Create(uiMap.FindAction("RightClick")); - inputModule.middleClick = InputActionReference.Create(uiMap.FindAction("MiddleClick")); - inputModule.scrollWheel = InputActionReference.Create(uiMap.FindAction("ScrollWheel")); - inputModule.submit = InputActionReference.Create(uiMap.FindAction("Submit")); - inputModule.cancel = InputActionReference.Create(uiMap.FindAction("Cancel")); - inputModule.move = InputActionReference.Create(uiMap.FindAction("Navigate")); - - Debug.Log("✓ InputSystemUIInputModule에 Actions 할당 완료"); - } - - // Actions 활성화 - asset.Enable(); - } - -#if UNITY_EDITOR - void SaveAssetToFile(InputActionAsset asset) - { - string path = "Assets/CompleteMouseUIInputActions.inputactions"; - UnityEditor.AssetDatabase.CreateAsset(asset, path); - UnityEditor.AssetDatabase.SaveAssets(); - Debug.Log($"✓ Input Actions Asset 저장: {path}"); - } -#endif -} \ No newline at end of file diff --git a/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs.meta b/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs.meta deleted file mode 100644 index 33d811f8..00000000 --- a/Assets/Scripts/SampleProject/CompleteMouseInputActionsCreator.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: f356dde41ea0a7a4f9b6debea38db74f \ No newline at end of file diff --git a/Assets/Scripts/SampleProject/RaycastDebugger.cs b/Assets/Scripts/SampleProject/RaycastDebugger.cs deleted file mode 100644 index 5809c06f..00000000 --- a/Assets/Scripts/SampleProject/RaycastDebugger.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UnityEngine; - -public class RaycastDebugger : MonoBehaviour -{ - private Camera mainCamera; - - void Start() - { - // Camera.main 대신 시작할 때 한 번만 카메라를 찾아오는 것이 더 안전하고 효율적입니다. - mainCamera = Camera.main; - if (mainCamera == null) - { - Debug.LogError("씬에 'MainCamera' 태그가 붙은 카메라가 없습니다!"); - } - } - - void Update() - { - if (Input.GetMouseButtonDown(0)) - { - if (mainCamera == null) return; - - Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); - RaycastHit hit; - - // Scene 뷰에서 Ray를 시각적으로 확인하기 위한 디버그용 코드 - Debug.DrawRay(ray.origin, ray.direction * 100f, Color.yellow, 120f); - - // Ray 객체를 직접 넘기는 것이 더 간단합니다. - // 거리는 무한대(Mathf.Infinity)로 설정합니다. - if (Physics.Raycast(ray, out hit)) - { - Debug.Log("Raycast Hit! 맞은 객체: " + hit.collider.name); - // 여기에 원하는 로직을 추가하세요. - } - else - { - Debug.Log("Raycast Missed. 아무것도 맞지 않았습니다."); - } - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/SampleProject/RaycastDebugger.cs.meta b/Assets/Scripts/SampleProject/RaycastDebugger.cs.meta deleted file mode 100644 index 7cf0f4f2..00000000 --- a/Assets/Scripts/SampleProject/RaycastDebugger.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 9958aa39fc037e74090efe980e62c959 \ No newline at end of file diff --git a/Assets/Scripts/UVC/Data/DataMapper.cs b/Assets/Scripts/UVC/Data/DataMapper.cs index a946a92e..fb0dd2b7 100644 --- a/Assets/Scripts/UVC/Data/DataMapper.cs +++ b/Assets/Scripts/UVC/Data/DataMapper.cs @@ -58,6 +58,7 @@ namespace UVC.Data /// private DataMask mask; + /// /// 병렬 처리를 적용할 배열의 최소 크기 /// diff --git a/Assets/Scripts/UVC/Data/DataMask.cs b/Assets/Scripts/UVC/Data/DataMask.cs index 2ebd3576..c60fd8f4 100644 --- a/Assets/Scripts/UVC/Data/DataMask.cs +++ b/Assets/Scripts/UVC/Data/DataMask.cs @@ -4,7 +4,6 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; -using Unity.VisualScripting.Antlr3.Runtime; namespace UVC.Data { diff --git a/Assets/Scripts/UVC/Data/DataValidator.cs b/Assets/Scripts/UVC/Data/DataValidator.cs new file mode 100644 index 00000000..f4436d7b --- /dev/null +++ b/Assets/Scripts/UVC/Data/DataValidator.cs @@ -0,0 +1,358 @@ +#nullable enable +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace UVC.Data +{ + /// + /// JSON 데이터의 유효성을 검사하는 클래스입니다. + /// 이 클래스는 특정 속성(프로퍼티)에 대한 유효성 검사 규칙을 추가하고, + /// 데이터가 해당 규칙을 모두 충족하는지 확인할 수 있습니다. + /// + /// + /// + /// // 유효성 검사기 생성 + /// var _validator = new DataValidator(); + /// + /// // 검증 규칙 추가: name 속성은 비어있지 않아야 함 + /// _validator.AddValidator("name", value => value is string name && !string.IsNullOrEmpty(name)); + /// + /// // 검증 규칙 추가: age 속성은 18 이상이어야 함 + /// _validator.AddValidator("age", value => value is long age && age >= 18); + /// + /// // 데이터 검증 예시 + /// var userData = new JObject { + /// { "name", "홍길동" }, + /// { "age", 20 } + /// }; + /// + /// if (_validator.IsValid(userData)) + /// { + /// Console.WriteLine("유효한 사용자 데이터입니다."); + /// } + /// else + /// { + /// Console.WriteLine("유효하지 않은 사용자 데이터입니다."); + /// } + /// + /// + public class DataValidator + { + /// + /// 유효성 검사 규칙의 목록입니다. + /// 각 사전은 속성 이름(string)과 해당 속성의 검증 함수(Func<object, bool>)를 포함합니다. + /// + private List>> validaters = new List>>(); + + /// + /// 대용량 JSON 데이터를 스트리밍 방식으로 처리할지 여부를 나타내는 속성입니다. + /// 스트리밍 방식은 메모리 사용량을 줄이기 위해 대용량 데이터를 처리할 때 유용합니다. + /// + /// + /// true로 설정하면 대용량 JSON 데이터를 처리할 때 스트리밍 방식을 사용합니다. + /// false로 설정하면 항상 전체 데이터를 메모리에 로드합니다. + /// + public bool SupportsStreamParsing { get; internal set; } = true; + + /// + /// 스트리밍 방식을 적용할 JSON 데이터의 최소 길이(바이트)입니다. + /// 데이터 길이가 이 값보다 크면 스트리밍 방식으로 처리합니다. + /// + /// + /// 기본값은 10,000바이트입니다. 작은 데이터의 경우 스트리밍 처리가 오히려 + /// 오버헤드를 발생시킬 수 있으므로, 특정 크기 이상일 때만 스트리밍 방식을 적용합니다. + /// + public int SupportsStreamLength { get; internal set; } = 10000; + + /// + /// 새로운 유효성 검사 규칙을 추가합니다. + /// + /// 검사할 속성 이름 + /// 유효성 검사 함수 (매개변수: 속성값, 반환값: 유효성 여부) + /// + /// + /// var _validator = new DataValidator(); + /// + /// // 문자열 속성이 비어있지 않은지 확인하는 규칙 + /// _validator.AddValidator("username", value => + /// { + /// if (value is string str) + /// return !string.IsNullOrEmpty(str); + /// return false; + /// }); + /// + /// // 숫자 속성이 특정 범위 내에 있는지 확인하는 규칙 + /// _validator.AddValidator("score", value => + /// { + /// if (value is long num) + /// return num >= 0 && num <= 100; + /// return false; + /// }); + /// + /// + public void AddValidator(string propertyName, Func validator) + { + // 유효성 검사기를 추가합니다. + validaters.Add(new Dictionary> { { propertyName, validator } }); + } + + /// + /// 특정 속성에 대한 모든 유효성 검사 규칙을 제거합니다. + /// + /// 규칙을 제거할 속성 이름 + /// + /// + /// var _validator = new DataValidator(); + /// _validator.AddValidator("age", value => (long)value >= 18); + /// + /// // 검증 과정 중에 'age' 속성 검사가 더 이상 필요하지 않을 경우 + /// _validator.RemoveValidator("age"); + /// + /// + public void RemoveValidator(string propertyName) + { + // 유효성 검사기를 제거합니다. + validaters.RemoveAll(v => v.ContainsKey(propertyName)); + } + + /// + /// DataObject 객체가 모든 유효성 검사 규칙을 통과하는지 확인합니다. + /// + /// 검사할 DataObject + /// 모든 규칙을 통과하면 true, 하나라도 실패하면 false + /// + /// + /// var _validator = new DataValidator(); + /// _validator.AddValidator("email", value => { + /// var emailStr = value as string; + /// return emailStr != null && emailStr.Contains("@"); + /// }); + /// + /// var userData = new DataObject(); + /// userData["name"] = "홍길동"; + /// userData["email"] = "hong@example.com"; + /// + /// bool isValid = _validator.IsValid(userData); // true 반환 + /// + /// + public bool IsValid(DataObject? data) + { + // 데이터가 null인 경우 유효하지 않음 + if (data == null) + { + return false; + } + // 각 유효성 검사기를 순회하며 검증을 수행합니다. + foreach (var validator in validaters) + { + foreach (var kvp in validator) + { + // 해당 속성이 데이터에 존재하는지 확인 + if (!data.ContainsKey(kvp.Key)) + { + continue; // 속성이 없으면 검증을 건너뜀 + } + // 속성 값에 대한 검증을 수행 + if (!kvp.Value(data[kvp.Key])) + { + // 검증에 실패하면 false를 반환 + return false; + } + } + } + + // 모든 검증을 통과하면 유효함 + return true; + } + + /// + /// JObject가 모든 유효성 검사 규칙을 통과하는지 확인합니다. + /// + /// 검사할 JObject + /// 모든 규칙을 통과하면 true, 하나라도 실패하면 false + /// + /// + /// var _validator = new DataValidator(); + /// + /// // 사용자 나이가 18세 이상인지 확인하는 규칙 + /// _validator.AddValidator("age", value => + /// value is long age && age >= 18 + /// ); + /// + /// // JSON 데이터 생성 + /// var jsonObject = JObject.Parse(@"{ + /// ""name"": ""김철수"", + /// ""age"": 16 + /// }"); + /// + /// bool isValid = _validator.IsValid(jsonObject); // false 반환 (age가 18 미만) + /// + /// + public bool IsValid(JObject? data) + { + // 데이터가 null인 경우 유효하지 않음 + if (data == null) + { + return false; + } + // 각 유효성 검사기를 순회하며 검증을 수행합니다. + foreach (var validator in validaters) + { + foreach (var kvp in validator) + { + // 해당 속성이 데이터에 존재하는지 확인 + if (!data.ContainsKey(kvp.Key)) + { + continue; // 속성이 없으면 검증을 건너뜀 + } + // 속성 값에 대한 검증을 수행 + if (!kvp.Value(data[kvp.Key])) + { + // 검증에 실패하면 false를 반환 + return false; + } + } + } + + // 모든 검증을 통과하면 유효함 + return true; + } + + /// + /// JSON 데이터 스트림이 모든 유효성 검사 규칙을 통과하는지 확인합니다. + /// 대용량 JSON 데이터를 메모리 효율적으로 처리할 수 있습니다. + /// + /// 검사할 JSON 데이터 스트림 + /// 모든 규칙을 통과하면 true, 하나라도 실패하면 false + /// + /// + /// var _validator = new DataValidator(); + /// _validator.AddValidator("isActive", value => value is bool active && active == true); + /// + /// // 파일에서 JSON 데이터 스트림을 읽어 유효성 검사 + /// using (var fileStream = File.OpenRead("user-data.json")) + /// { + /// bool isValid = _validator.IsValid(fileStream); + /// Console.WriteLine($"데이터 유효성: {isValid}"); + /// } + /// + /// + public bool IsValid(System.IO.Stream jsonStream) + { + if (jsonStream == null) return false; + + // 스트림 처리 최적화를 위해 청크 단위로 읽을 수 있지만, + // 현재는 Newtonsoft.Json의 기본 역직렬화 사용 + using (var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(jsonStream))) + { + // 청크 읽기 설정 - 메모리 사용량 최적화 + reader.SupportMultipleContent = true; + + var serializer = new Newtonsoft.Json.JsonSerializer(); + var sourceObject = serializer.Deserialize(reader); + + return IsValid(sourceObject); + } + } + + /// + /// JSON 배열에서 유효성 검사 규칙을 통과하는 항목만 필터링하여 반환합니다. + /// + /// 필터링할 JSON 배열 + /// 유효한 항목만 포함된 새 JSON 배열 (유효한 항목이 없으면 null) + /// + /// + /// var _validator = new DataValidator(); + /// + /// // 유효성 검사 규칙: status가 'active'인 항목만 유효 + /// _validator.AddValidator("status", value => + /// value is string status && status == "active" + /// ); + /// + /// // 필터링할 JSON 배열 생성 + /// var usersArray = JArray.Parse(@"[ + /// {""id"": 1, ""name"": ""홍길동"", ""status"": ""active""}, + /// {""id"": 2, ""name"": ""김철수"", ""status"": ""inactive""}, + /// {""id"": 3, ""name"": ""이영희"", ""status"": ""active""} + /// ]"); + /// + /// // 유효한 항목(status가 'active'인 항목)만 필터링 + /// JArray? validUsers = _validator.GetValidData(usersArray); + /// + /// // validUsers는 홍길동과 이영희의 데이터만 포함 (2개 항목) + /// Console.WriteLine($"유효한 사용자 수: {validUsers?.Count ?? 0}"); + /// + /// + public JArray? GetValidData(JArray? data) + { + if (data == null || data.Count == 0) + { + return data; // 빈 배열은 유효하지 않음 + } + + JArray validData = new JArray(); + foreach (var item in data) + { + if (item is JObject jObject && IsValid(jObject)) + { + validData.Add(jObject); + } + } + return validData.Count > 0 ? validData : null; // 유효한 데이터가 없으면 null 반환 + } + + /// + /// JSON 데이터 스트림에서 유효성 검사 규칙을 통과하는 항목만 필터링하여 반환합니다. + /// 대용량 JSON 배열을 메모리 효율적으로 처리하기 위해 스트리밍 방식을 사용합니다. + /// + /// 필터링할 JSON 배열 데이터 스트림 + /// 유효한 항목만 포함된 JSON 배열 (유효한 항목이 없으면 null) + /// + /// + /// var _validator = new DataValidator(); + /// + /// // 필수 필드가 모두 있는지 확인하는 규칙 추가 + /// _validator.AddValidator("name", value => value != null && !string.IsNullOrEmpty(value.ToString())); + /// _validator.AddValidator("email", value => value != null && value.ToString().Contains("@")); + /// + /// // 파일에서 JSON 배열 데이터 스트림을 읽어 유효한 항목만 필터링 + /// using (var fileStream = File.OpenRead("users-data.json")) + /// { + /// JArray? validUsers = _validator.GetValidData(fileStream); + /// + /// if (validUsers != null) + /// { + /// Console.WriteLine($"유효한 사용자 수: {validUsers.Count}"); + /// + /// // 첫 번째 유효한 사용자 정보 출력 + /// if (validUsers.Count > 0) + /// { + /// var firstUser = validUsers[0]; + /// Console.WriteLine($"첫 번째 유효 사용자: {firstUser["name"]}"); + /// } + /// } + /// else + /// { + /// Console.WriteLine("유효한 사용자가 없습니다."); + /// } + /// } + /// + /// + public JArray? GetValidData(System.IO.Stream jsonStream) + { + if (jsonStream == null) return null; + + using (var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(jsonStream))) + { + // 청크 읽기 설정 - 메모리 사용량 최적화 + reader.SupportMultipleContent = true; + + var serializer = new Newtonsoft.Json.JsonSerializer(); + var sourceArray = serializer.Deserialize(reader); + + return GetValidData(sourceArray); + } + } + } +} diff --git a/Assets/Scripts/UVC/Data/DataValidator.cs.meta b/Assets/Scripts/UVC/Data/DataValidator.cs.meta new file mode 100644 index 00000000..44ad0207 --- /dev/null +++ b/Assets/Scripts/UVC/Data/DataValidator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 74866795406b7c74a86591446c9b455a \ No newline at end of file diff --git a/Assets/Scripts/UVC/Data/HttpPipeLine.cs b/Assets/Scripts/UVC/Data/HttpPipeLine.cs index 8e8bfa7c..2701ce84 100644 --- a/Assets/Scripts/UVC/Data/HttpPipeLine.cs +++ b/Assets/Scripts/UVC/Data/HttpPipeLine.cs @@ -12,6 +12,7 @@ using UnityEngine; using UVC.Log; using UVC.Network; using UVC.Tests; +using UVC.Threading; namespace UVC.Data { @@ -29,6 +30,11 @@ namespace UVC.Data /// - 안전한 요청 취소 및 자원 정리 /// - 테스트를 위한 목업 기능 지원 /// + /// 모든 HTTP 요청은 백그라운드 스레드(스레드풀)에서 처리되어 메인 스레드 차단을 방지합니다. + /// 요청 결과 처리 시 핸들러(SuccessHandler, FailHandler)는 자동으로 메인 스레드에서 호출됩니다. + /// 이를 통해 UI 스레드 차단 없이 효율적인 네트워크 작업을 수행하면서도, + /// UI 업데이트는 안전하게 메인 스레드에서 처리할 수 있습니다. + /// /// 모든 반복 실행은 CancellationTokenSource를 통해 취소할 수 있으며, /// 취소 후 현재 진행 중인 모든 요청이 안전하게 완료되는 것을 보장합니다. /// @@ -142,22 +148,33 @@ namespace UVC.Data /// 지정한 키의 HTTP 요청을 실행합니다. /// /// 실행할 요청의 키 + /// 메인 스레드로 전환할지 여부 /// 비동기 작업 /// /// 요청 정보의 repeat 속성에 따라 단일 실행 또는 반복 실행을 시작합니다. /// 이미 실행 중인 반복 작업이 있다면 먼저 중지하고 완료를 대기한 후 새로운 요청을 시작합니다. /// 단일 실행의 경우 완료될 때까지 대기하지만, 반복 실행은 백그라운드에서 실행됩니다. + /// + /// 모든 HTTP 요청 처리는 백그라운드 스레드에서 수행되며, 핸들러만 메인 스레드에서 호출됩니다. /// /// 지정된 키가 등록되어 있지 않은 경우 - public async UniTask Excute(string key) + public async UniTask Excute(string key, bool switchToMainThread = false) { - if (infoList.ContainsKey(key)) + if (!infoList.ContainsKey(key)) { - HttpPipeLineInfo info = infoList[key]; + throw new KeyNotFoundException($"No HTTP request found with key '{key}'."); + } - // 반복 설정에 관계없이 이전에 실행 중인 반복 작업이 있다면 중지 - await StopRepeat(key); + HttpPipeLineInfo info = infoList[key]; + // 반복 설정에 관계없이 이전에 실행 중인 반복 작업이 있다면 중지 + await StopRepeat(key); + + // 스레드풀에서 요청 처리 실행 + await UniTask.SwitchToThreadPool(); + + try + { if (!info.Repeat) { // 단일 실행 로직 호출 @@ -166,12 +183,19 @@ namespace UVC.Data else { // 반복 설정이 있는 경우에만 StartRepeat 호출 + // Forget()을 호출하지 않고 StartRepeat가 스레드풀에서 계속 실행되도록 함 StartRepeat(key).Forget(); } } - else + finally { - throw new KeyNotFoundException($"No HTTP request found with key '{key}'."); + // ExecuteSingle 또는 StartRepeat.Forget() 후 메인 스레드로 복귀하는 것은 선택 사항 + // 여기서는 원래 실행 컨텍스트로 돌아가기 위해 메인 스레드로 전환 + // 만약 계속해서 백그라운드 스레드에서 실행하려면 이 코드를 제거할 수 있음 + if (switchToMainThread) + { + await UniTask.SwitchToMainThread(); + } } } @@ -183,8 +207,9 @@ namespace UVC.Data /// 요청 취소를 위한 취소 토큰 /// 비동기 작업 /// - /// 이 메서드는 HTTP 요청을 보내고, 응답 데이터를 파싱하여 IDataObject로 변환합니다. + /// 이 메서드는 백그라운드 스레드에서 HTTP 요청을 보내고, 응답 데이터를 파싱하여 IDataObject로 변환합니다. /// JSON 객체 또는 배열 형식의 응답을 처리할 수 있으며, 취소 토큰을 통해 언제든지 작업을 취소할 수 있습니다. + /// 모든 핸들러 호출은 메인 스레드에서 이루어져 UI 업데이트를 안전하게 수행할 수 있습니다. /// /// 작업이 취소된 경우 발생 /// JSON 응답 파싱 중 오류가 발생한 경우 @@ -237,7 +262,16 @@ namespace UVC.Data // 응답 마스크 적용 결과가 성공이 아니면 실패 핸들러 호출 후 반환 if (!responseResult.IsSuccess) { - info.FailHandler?.Invoke(responseResult.Message!); + if (info.FailHandler != null) + { + string errorMessage = responseResult.Message!; + + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke(errorMessage); + }); + } return; } else @@ -248,6 +282,44 @@ namespace UVC.Data if (result.StartsWith("{")) { + if (info.Validator != null) + { + if (info.Validator.SupportsStreamParsing && result.Length > info.Validator.SupportsStreamLength) + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(result))) + { + if (info.Validator != null && !info.Validator.IsValid(stream)) + { + if (info.FailHandler != null) + { + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke("Data is not Valid"); + }); + } + return; + } + } + } + else + { + JObject source = JObject.Parse(result); + if (info.Validator != null && !info.Validator.IsValid(source)) + { + if (info.FailHandler != null) + { + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke("Data is not Valid"); + }); + } + return; + } + } + } + if (info.DataMapper != null) { if (info.DataMapper.SupportsStreamParsing && result.Length > info.DataMapper.SupportsStreamLength) @@ -266,19 +338,81 @@ namespace UVC.Data } else if (result.StartsWith("[")) { + if (info.Validator != null) + { + if (info.Validator.SupportsStreamParsing && result.Length > info.Validator.SupportsStreamLength) + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(result))) + { + JArray? validSource = info.Validator.GetValidData(stream); + if (validSource == null) + { + if (info.FailHandler != null) + { + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke("Data is not Valid"); + }); + } + return; + } + } + } + else + { + JArray source = JArray.Parse(result); + JArray? validSource = info.Validator.GetValidData(source); + if (validSource == null) + { + if (info.FailHandler != null) + { + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke("Data is not Valid"); + }); + } + return; + } + } + } + if (info.DataMapper != null) { if (info.DataMapper.SupportsStreamParsing && result.Length > info.DataMapper.SupportsStreamLength) { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(result))) { - dataObject = info.DataMapper.MapArrayStream(stream); + if (info.Validator != null) + { + JArray? validSource = info.Validator.GetValidData(stream); + if (validSource != null) + { + dataObject = info.DataMapper.Map(validSource); + } + } + else + { + dataObject = info.DataMapper.MapArrayStream(stream); + } } } else { JArray source = JArray.Parse(result); - dataObject = info.DataMapper.Map(source); + if (info.Validator != null) + { + JArray? validSource = info.Validator.GetValidData(source); + if (validSource != null) + { + dataObject = info.DataMapper.Map(validSource); + } + } + else + { + dataObject = info.DataMapper.Map(source); + } } } } @@ -300,12 +434,47 @@ namespace UVC.Data // 갱신 된 데이터가 있는 경우 핸들러 호출 if (info.UpdatedDataOnly) { - if (dataObject != null && dataObject.UpdatedCount > 0) info.SuccessHandler?.Invoke(dataObject); + if (dataObject != null && dataObject.UpdatedCount > 0) + { + if (info.SuccessHandler != null) + { + // 로컬 변수로 복사하여 클로저에서 안전하게 사용 + var handlerData = dataObject; + // UI 스레드에서 성공 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.SuccessHandler.Invoke(handlerData); + }); + } + return; + } + } + + if (dataObject != null) + { + if (info.SuccessHandler != null) + { + // 로컬 변수로 복사하여 클로저에서 안전하게 사용 + var handlerData = dataObject; + // UI 스레드에서 성공 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.SuccessHandler.Invoke(handlerData); + }); + } } else { - info.SuccessHandler?.Invoke(dataObject); + if (info.FailHandler != null) + { + // UI 스레드에서 실패 핸들러 호출 + MainThreadDispatcher.Instance.SendToMainThread(() => + { + info.FailHandler.Invoke("Data is Null"); + }); + } } + return; } catch (OperationCanceledException) @@ -349,10 +518,12 @@ namespace UVC.Data /// 반복 실행할 요청의 키 /// 비동기 작업 /// - /// 지정된 간격(repeatInterval)으로 HTTP 요청을 반복 실행합니다. + /// 지정된 간격(repeatInterval)으로 HTTP 요청을 백그라운드 스레드에서 반복 실행합니다. /// repeatCount가 0인 경우 무한 반복하며, 0보다 큰 경우 지정된 횟수만큼만 실행합니다. /// 작업 실행 중 예외가 발생하면 로그를 기록하고 다음 실행을 시도합니다. /// 취소 요청이 있거나 최대 실행 횟수에 도달하면 반복이 종료됩니다. + /// + /// 이 메서드는 백그라운드 스레드에서 실행되며, 모든 핸들러 호출은 메인 스레드에서 이루어집니다. /// /// 지정된 키가 등록되어 있지 않은 경우 private async UniTask StartRepeat(string key) diff --git a/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs b/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs index 0ea686c0..0870b9ad 100644 --- a/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs +++ b/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs @@ -42,6 +42,42 @@ namespace UVC.Data private int _retryDelay = 1000; // 밀리초 private bool _updatedDataOnly = false; // 업데이트된 데이터만 받을 여부 + /// + /// HTTP 응답 데이터의 유효성을 검사하는 데 사용되는 검사기입니다. + /// 이 검사기를 통해 특정 조건을 만족하는 데이터만 처리하도록 필터링할 수 있습니다. + /// + /// + /// 데이터 유효성 검사는 HTTP 응답이 성공적으로 수신되고 JSON으로 파싱된 후, + /// 성공 핸들러에 전달되기 전에 수행됩니다. + /// 검사기가 null이 아닌 경우에만 유효성 검사가 실행됩니다. + /// + /// + /// + /// // DataValidator 생성 및 규칙 추가 + /// var validator = new DataValidator(); + /// + /// // "status" 필드가 "active"인 데이터만 유효하도록 설정 + /// validator.AddValidator("status", value => + /// value is string status && status.Equals("active", StringComparison.OrdinalIgnoreCase)); + /// + /// // "temperature" 필드가 유효한 범위 내에 있는지 확인 + /// validator.AddValidator("temperature", value => { + /// if (value is double temp) + /// return temp >= -50 && temp <= 100; + /// return false; + /// }); + /// + /// // 파이프라인에 validator 설정 + /// var pipeline = new HttpPipeLineInfo("https://api.weather.com/current") + /// .setValidator(validator) + /// .setSuccessHandler(data => { + /// // 여기에 전달되는 데이터는 이미 유효성 검사를 통과한 데이터만 포함됩니다. + /// Console.WriteLine($"유효한 온도: {data["temperature"]}°C"); + /// }); + /// + /// + private DataValidator? _validator; + /// /// 요청을 보낼 URL 주소 /// @@ -92,6 +128,16 @@ namespace UVC.Data /// public DataMapper? DataMapper => _dataMapper; + /// + /// HTTP 응답 데이터의 유효성을 검사하는 검사기입니다. + /// 이 속성을 통해 설정된 규칙에 따라 HTTP 응답 데이터를 필터링할 수 있습니다. + /// + /// + /// null이 아닌 경우, HTTP 응답이 파싱된 후 데이터가 핸들러에 전달되기 전에 + /// 데이터가 검사기의 모든 규칙을 통과하는지 확인합니다. + /// + public DataValidator? Validator => _validator; + /// /// HTTP 응답의 성공 여부를 확인하고, 성공 시 실제 데이터 페이로드를 추출하는 데 사용되는 입니다. /// 이 객체에 정의된 규칙에 따라 원시 응답 문자열이 처리됩니다. @@ -140,6 +186,55 @@ namespace UVC.Data return this; } + /// + /// HTTP 응답 데이터의 유효성을 검사하는 검사기를 설정합니다. + /// + /// HTTP 응답 데이터의 유효성 검사에 사용할 DataValidator 객체 + /// 현재 HttpPipeLineInfo 인스턴스 (메서드 체이닝용) + /// + /// 이 메서드로 설정된 검사기는 HTTP 응답이 성공적으로 파싱된 후, + /// 성공 핸들러에 전달되기 전에 데이터의 유효성을 검사합니다. + /// 데이터가 모든 유효성 검사 규칙을 통과하지 못하면 성공 핸들러가 호출되지 않습니다. + /// + /// + /// + /// // 1. DataValidator 생성 및 규칙 추가 + /// var validator = new DataValidator(); + /// + /// // 2. 유효성 검사 규칙 정의 + /// // 사용자 데이터에 이메일이 포함되어 있는지 확인 + /// validator.AddValidator("email", value => { + /// if (value is string email) + /// return email.Contains("@") && email.Contains("."); + /// return false; + /// }); + /// + /// // 사용자 나이가 18세 이상인지 확인 + /// validator.AddValidator("age", value => { + /// if (value is long age) + /// return age >= 18; + /// return false; + /// }); + /// + /// // 3. 검사기를 HTTP 파이프라인에 설정 + /// var pipelineInfo = new HttpPipeLineInfo("https://api.example.com/users", "get") + /// .setDataMapper(userDataMapper) + /// .setValidator(validator) + /// .setSuccessHandler(userData => { + /// // 여기에 도달하는 사용자 데이터는 모두 이메일이 유효하고 18세 이상입니다. + /// Console.WriteLine($"유효한 사용자: {userData["name"]}, {userData["email"]}"); + /// }) + /// .setFailHandler(errorMsg => { + /// Console.WriteLine($"요청 실패: {errorMsg}"); + /// }); + /// + /// + public HttpPipeLineInfo setValidator(DataValidator validator) + { + this._validator = validator; + return this; + } + /// /// HTTP 파이프라인에 적용할 ResponseMask를 설정하고 업데이트된 파이프라인 구성을 반환합니다. /// diff --git a/Assets/Scripts/UVC/Data/MQTTPipeLine.cs b/Assets/Scripts/UVC/Data/MQTTPipeLine.cs index 632fe293..c3754c77 100644 --- a/Assets/Scripts/UVC/Data/MQTTPipeLine.cs +++ b/Assets/Scripts/UVC/Data/MQTTPipeLine.cs @@ -205,12 +205,32 @@ namespace UVC.Data if (message.StartsWith("{")) { JObject source = JObject.Parse(message); + if (info.Validator != null && !info.Validator.IsValid(source)) + { + return; // 유효성 검사 실패 시 핸들러 호출을 중단 + } if (info.DataMapper != null) dataObject = info.DataMapper.Map(source); } else if (message.StartsWith("[")) { JArray source = JArray.Parse(message); - if (info.DataMapper != null) dataObject = info.DataMapper.Map(source); + if (info.Validator != null) + { + JArray? validSource = info.Validator.GetValidData(source); + if (validSource != null && validSource.Count > 0) + { + // 유효한 데이터가 있는 경우에만 매핑 + if (info.DataMapper != null) dataObject = info.DataMapper.Map(validSource); + } + else + { + return; // 유효성 검사 실패 시 핸들러 호출을 중단 + } + } + else + { + if (info.DataMapper != null) dataObject = info.DataMapper.Map(source); + } } if (dataObject != null) dataObject = DataRepository.Instance.AddData(topic, dataObject, info.UpdatedDataOnly); diff --git a/Assets/Scripts/UVC/Data/MQTTPipeLineInfo.cs b/Assets/Scripts/UVC/Data/MQTTPipeLineInfo.cs index 4f2a466e..6b1d7738 100644 --- a/Assets/Scripts/UVC/Data/MQTTPipeLineInfo.cs +++ b/Assets/Scripts/UVC/Data/MQTTPipeLineInfo.cs @@ -32,6 +32,37 @@ namespace UVC.Data private DataMapper? _dataMapper = null; // 데이터 매퍼 private bool _updatedDataOnly = false; // 업데이트된 데이터만 받을 여부 + /// + /// MQTT 메시지 데이터의 유효성을 검사하는 데 사용되는 검사기입니다. + /// 메시지가 특정 조건이나 규칙을 만족하는지 확인하는 데 활용됩니다. + /// + /// + /// 데이터 유효성 검사는 메시지를 필터링하여 유효한 데이터만 처리하도록 합니다. + /// 예를 들어, 필수 필드가 있는지, 값의 범위가 적절한지 등을 검사할 수 있습니다. + /// null인 경우 유효성 검사를 수행하지 않습니다. + /// + /// + /// + /// // DataValidator 생성 및 규칙 추가 + /// var _validator = new DataValidator(); + /// + /// // 온도 값이 -50°C ~ 100°C 범위 내에 있는지 검사 + /// _validator.AddValidator("temperature", value => + /// value is double temp && temp >= -50 && temp <= 100); + /// + /// // 습도 값이 0% ~ 100% 범위 내에 있는지 검사 + /// validator.AddValidator("humidity", value => + /// value is double humidity && humidity >= 0 && humidity <= 100); + /// + /// // 파이프라인에 validator 설정 + /// var pipelineInfo = new MQTTPipeLineInfo("sensors/readings") + /// .setDataMapper(dataMapper) + /// .setValidator(validator) + /// .setHandler(data => ProcessValidSensorData(data)); + /// + /// + private DataValidator? _validator; + /// /// MQTT 토픽 /// @@ -47,6 +78,11 @@ namespace UVC.Data /// public DataMapper? DataMapper => _dataMapper; + /// + /// 인스턴스를 사용하여 데이터 유효성을 검사합니다. + /// + public DataValidator? Validator => _validator; + /// /// 업데이트된 데이터만 받을 여부 (true로 설정하면, 데이터가 변경된 경우에만 핸들러가 호출됩니다) /// @@ -110,5 +146,49 @@ namespace UVC.Data return this; } + + /// + /// MQTT 메시지 데이터의 유효성을 검사하는 데 사용할 Validator를 설정합니다. + /// + /// 데이터 유효성 검사기 + /// 현재 MQTTPipeLineInfo 인스턴스 (메서드 체이닝용) + /// + /// 유효성 검사기는 수신된 MQTT 메시지 데이터가 유효한지 확인하는 역할을 합니다. + /// 데이터가 특정 조건을 만족하는지 확인하고, 유효하지 않은 메시지는 필터링할 수 있습니다. + /// 파이프라인 내에서 DataMapper가 데이터를 변환한 후, Validator가 유효성을 검사하고, + /// 유효한 데이터만 Handler에게 전달됩니다. + /// + /// + /// + /// // DataValidator 생성 및 설정 + /// var _validator = new DataValidator(); + /// + /// // 온도 값이 -50°C ~ 100°C 범위 내에 있는지 검사 + /// _validator.AddValidator("temperature", value => { + /// if (value is double temp) + /// return temp >= -50 && temp <= 100; + /// return false; + /// }); + /// + /// // deviceId가 null이 아니고 비어있지 않은지 검사 + /// validator.AddValidator("deviceId", value => + /// value is string id && !string.IsNullOrEmpty(id)); + /// + /// // Validator를 파이프라인에 설정 + /// var pipelineInfo = new MQTTPipeLineInfo("sensors/data") + /// .setDataMapper(dataMapper) + /// .setValidator(_validator) + /// .setHandler(data => { + /// // 여기서 처리되는 데이터는 모두 유효성 검사를 통과한 데이터 + /// Console.WriteLine($"유효한 센서 데이터: {data["deviceId"]} - {data["temperature"]}°C"); + /// }); + /// + /// + public MQTTPipeLineInfo setValidator(DataValidator validator) + { + this._validator = validator; + return this; + } + } } diff --git a/Assets/Scripts/UVC/Extention/TransformEx.cs b/Assets/Scripts/UVC/Extention/TransformEx.cs index b401d326..5944773c 100644 --- a/Assets/Scripts/UVC/Extention/TransformEx.cs +++ b/Assets/Scripts/UVC/Extention/TransformEx.cs @@ -174,5 +174,15 @@ namespace UVC.Extension return t; } + /// + /// 지정된 의 로컬 위치를 월드 공간 좌표로 변환합니다. + /// + /// 로컬 위치를 변환할 입니다. + /// 로컬 위치의 월드 공간 좌표를 나타내는 입니다. + public static Vector3 ToWorldPosition(this Transform t) + { + return t.TransformPoint(t.localPosition); + } + } } diff --git a/Assets/Scripts/UVC/Factory/Alarm/AlarmUIController.cs b/Assets/Scripts/UVC/Factory/Alarm/AlarmUIController.cs index 4b9d1c37..452c4318 100644 --- a/Assets/Scripts/UVC/Factory/Alarm/AlarmUIController.cs +++ b/Assets/Scripts/UVC/Factory/Alarm/AlarmUIController.cs @@ -2,6 +2,7 @@ using TMPro; using UnityEngine; using UVC.Factory.Component; +using UVC.Util; namespace UVC.Factory.Alarm { diff --git a/Assets/Scripts/UVC/Factory/Alarm/SingleAlarmIcon.cs b/Assets/Scripts/UVC/Factory/Alarm/SingleAlarmIcon.cs index f3805cb5..8734cce3 100644 --- a/Assets/Scripts/UVC/Factory/Alarm/SingleAlarmIcon.cs +++ b/Assets/Scripts/UVC/Factory/Alarm/SingleAlarmIcon.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UVC.Util; namespace UVC.Factory.Alarm { diff --git a/Assets/Scripts/UVC/Factory/CameraController.cs b/Assets/Scripts/UVC/Factory/CameraController.cs deleted file mode 100644 index 9d7e3ec3..00000000 --- a/Assets/Scripts/UVC/Factory/CameraController.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using UnityEngine; -using UVC.Core; - -namespace UVC.Factory -{ - public class CameraController : SingletonScene - { - public float moveSpeed = 5.0f; - public float rotateSpeed = 100.0f; - - private Coroutine focusCoroutine; - - - public void FocusOnTarget(Transform target, float distance) - { - if (focusCoroutine != null) - { - StopCoroutine(focusCoroutine); - } - focusCoroutine = StartCoroutine(FocusRoutine(target, distance)); - } - - private IEnumerator FocusRoutine(Transform target, float distance) - { - Vector3 targetPosition = target.position - transform.forward * distance; - Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position); - - while (Vector3.Distance(transform.position, targetPosition) > 0.01f) - { - transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * moveSpeed); - transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotateSpeed); - yield return null; - } - } - } -} diff --git a/Assets/Scripts/UVC/Factory/CameraController.cs.meta b/Assets/Scripts/UVC/Factory/CameraController.cs.meta deleted file mode 100644 index 093013c4..00000000 --- a/Assets/Scripts/UVC/Factory/CameraController.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 1261d9494e4176a488c4e65b80396de6 \ No newline at end of file diff --git a/Assets/Scripts/UVC/Factory/Component/AGV.cs b/Assets/Scripts/UVC/Factory/Component/AGV.cs index e1751bd3..3d0f36b2 100644 --- a/Assets/Scripts/UVC/Factory/Component/AGV.cs +++ b/Assets/Scripts/UVC/Factory/Component/AGV.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UVC.Data; @@ -16,33 +17,31 @@ namespace UVC.Factory.Component // 움직임과 회전의 부드러움을 조절할 속도 변수 // Unity 인스펙터 창에서 실시간으로 값을 조절하며 테스트할 수 있습니다. [Tooltip("목표 지점까지의 이동 속도를 조절합니다.")] - public float moveSpeed = 2.0f; + public float moveSpeed = 1.0f; [Tooltip("목표 방향까지의 회전 속도를 조절합니다.")] - public float rotationSpeed = 5.0f; + public float rotationSpeed = 2.0f; [Tooltip("이 거리(미터)를 초과하면 보간 없이 즉시 위치를 변경합니다.")] public float teleportDistanceThreshold = 5.0f; // 5미터 이상 차이나면 순간이동 private void Start() { + targetPosition = transform.position; + targetRotation = transform.rotation; + DataOrderedMask = new List { - "Name", - "Type", - "Status", - "BatteryLevel", - "Location", - "LastMaintenance" + "VHL_NAME", + "NODE_ID", + "REAL_ID", + "VHL_STATE", + "BATT", + "JOB_ID", + "TIMESTAMP", }; } - public override void OnPointerClick(PointerEventData eventData) - { - Debug.Log($"OnPointerClick3: {gameObject.name}"); - base.OnPointerClick(eventData); - } - /// /// 내부 상태를 업데이트하고 정렬된 마스크에 정의된 특정 키에 대한 작업을 수행하여 제공된 데이터 객체를 처리합니다. // @@ -119,11 +118,32 @@ namespace UVC.Factory.Component void Update() { - // 매 프레임마다 현재 위치에서 목표 위치로 부드럽게 이동시킵니다. - transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * moveSpeed); + if (transform.position != targetPosition) + { + if (Vector3.Distance(transform.position, targetPosition) < 0.1f) + { + // 현재 위치와 목표 위치 사이의 거리가 임계값을 초과하면 순간이동합니다. + transform.position = targetPosition; + } + else + { + // 매 프레임마다 현재 위치에서 목표 위치로 부드럽게 이동시킵니다. + transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * moveSpeed); + } + } - // 매 프레임마다 현재 회전에서 목표 회전으로 부드럽게 회전시킵니다. - transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed); + if (transform.rotation != targetRotation) + { + if (Quaternion.Angle(transform.rotation, targetRotation) < 0.1f) + { + transform.rotation = targetRotation; + } + else + { + // 매 프레임마다 현재 회전에서 목표 회전으로 부드럽게 회전시킵니다. + transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed); + } + } } } } diff --git a/Assets/Scripts/UVC/Factory/Component/ClickTest.cs b/Assets/Scripts/UVC/Factory/Component/ClickTest.cs deleted file mode 100644 index 555cddf2..00000000 --- a/Assets/Scripts/UVC/Factory/Component/ClickTest.cs +++ /dev/null @@ -1,156 +0,0 @@ -using UnityEngine; -using UnityEngine.EventSystems; - -namespace UVC.Factory.Component -{ - [RequireComponent(typeof(Collider))] - public class ClickTest : MonoBehaviour - { - - private InputSystemActions inputSystemActions; - private Camera mainCamera; - - //void Start() - //{ - // Collider col = GetComponent(); - // if (col != null) - // { - // // 콜라이더의 중심과 크기 출력 (BoxCollider의 경우) - // if (col is BoxCollider boxCollider) - // { - // Debug.Log($"BoxCollider - Center: {boxCollider.center}, Size: {boxCollider.size}"); - // } - - // // 콜라이더의 월드 바운드 출력 - // Debug.Log($"콜라이더의 월드 바운드: {col.bounds}"); - // } - // else - // { - // Debug.LogError($"{gameObject.name}에 콜라이더가 없습니다!"); - // } - //} - - void OnMouseDown() - { - Debug.Log($"OnMouseDown: {gameObject.name}"); - transform.localScale -= new Vector3(0.05f, 0.05f, 0); - //or - //transform.GetComponent().color += new Color(40, 40, 40); - } - - void OnMouseUp() - { - Debug.Log($"OnMouseUp: {gameObject.name}"); - transform.localScale += new Vector3(0.05f, 0.05f, 0); - //or - //transform.GetComponent().color -= new Color(40, 40, 40); - } - - void Update() - { - if (UnityEngine.Input.GetMouseButtonDown(0)) // 0 represents the left mouse button - { - - Ray ray = Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition); - RaycastHit hit; - - // 레이 시작점과 방향 로깅 - Debug.Log($"Ray 원점: {ray.origin}, 방향: {ray.direction}"); - - // 디버그용 레이를 씬 뷰에 그립니다 - Debug.DrawRay(ray.origin, ray.direction * 100, Color.red, 60f); - - bool hitSomething = Physics.Raycast(ray, out hit); - Debug.Log($"Mouse button clicked - hit something: {hitSomething}"); - - if (hitSomething) - { - Debug.Log($"Hit object: {hit.collider.gameObject.name}, distance: {hit.distance}, point: {hit.point}"); - } - else - { - // 모든 콜라이더 로깅 - Collider[] allColliders = FindObjectsByType(FindObjectsSortMode.None); - Debug.Log($"씬에 있는 콜라이더 수: {allColliders.Length}"); - - foreach (var collider in allColliders) - { - if (collider.gameObject.activeInHierarchy && collider.enabled) - Debug.Log($"활성화된 콜라이더: {collider.gameObject.name}, 레이어: {LayerMask.LayerToName(collider.gameObject.layer)}"); - } - } - - ray = Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition); - RaycastHit[] tempinfo = new RaycastHit[100]; - var hitcount = Physics.RaycastNonAlloc(ray, tempinfo, Mathf.Infinity); - Debug.Log($"Mouse button clicked hitcount:{hitcount} {Physics.Raycast(ray, out hit)}"); - - if (Physics.Raycast(ray, out hit)) - { - // Check if the hit object has the ClickableObject script - ClickTest clickableObject = hit.collider.GetComponent(); - if (clickableObject != null) - { - // 수동으로 이벤트 호출 - PointerEventData pointerData = new PointerEventData(EventSystem.current); - pointerData.position = UnityEngine.Input.mousePosition; - OnPointerClick(pointerData); - } - else - { - Debug.Log("Clicked on: " + hit.collider.gameObject.name + ", but it's not clickable."); - } - } - } - - //if (Mouse.current.leftButton.wasPressedThisFrame) - //{ - // Debug.Log("마우스 클릭 감지"); - //} - } - - public void OnPointerClick(PointerEventData eventData) - { - Debug.Log($"OnPointerClick1: {gameObject.name}"); - - } - - /// - /// 포인터가 이 객체 위로 들어왔을 때 호출됩니다. 하이라이트 효과 등에 사용할 수 있습니다. - /// - /// 포인터 이벤트와 관련된 데이터입니다. - public void OnPointerEnter(PointerEventData eventData) - { - Debug.Log($"OnPointerEnter: {gameObject.name}"); - } - - /// - /// 포인터가 이 객체에서 벗어났을 때 호출됩니다. - /// - /// 포인터 이벤트와 관련된 데이터입니다. - public void OnPointerExit(PointerEventData eventData) - { - Debug.Log($"OnPointerExit: {gameObject.name}"); - } - - public void OnMouseClick() - { - Debug.Log($"OnClick: {gameObject.name}"); - } - public void OnMouseEnter() - { - Debug.Log($"OnMouseEnter: {gameObject.name}"); - } - - public void OnMouseExit() - { - Debug.Log($"OnMouseExit: {gameObject.name}"); - } - - public void OnMouseWheel() - { - Debug.Log($"OnMouseWheel: {gameObject.name}"); - } - - } -} diff --git a/Assets/Scripts/UVC/Factory/Component/ClickTest.cs.meta b/Assets/Scripts/UVC/Factory/Component/ClickTest.cs.meta deleted file mode 100644 index d4d30ed9..00000000 --- a/Assets/Scripts/UVC/Factory/Component/ClickTest.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 2bf81994712147c45b75b5394f2b0aca \ No newline at end of file diff --git a/Assets/Scripts/UVC/Factory/Component/FactoryObject.cs b/Assets/Scripts/UVC/Factory/Component/FactoryObject.cs index 5559870d..a43df9cb 100644 --- a/Assets/Scripts/UVC/Factory/Component/FactoryObject.cs +++ b/Assets/Scripts/UVC/Factory/Component/FactoryObject.cs @@ -61,7 +61,6 @@ namespace UVC.Factory.Component /// 포인터 클릭과 관련된 이벤트 데이터입니다. public override void OnPointerClick(PointerEventData eventData) { - Debug.Log($"OnPointerClick2: {gameObject.name}"); if (data != null && data.Count > 0) { Dictionary info = new Dictionary(); @@ -81,7 +80,6 @@ namespace UVC.Factory.Component // dataOrderedMask가 설정되어 있지 않으면 모든 데이터를 사용합니다. info = new Dictionary(data); } - Debug.Log($"OnPointerClick: {gameObject.name} - {info.Count} items"); InfoWindow.Instance.Show(transform, info); } } diff --git a/Assets/Scripts/UVC/Object3d/InteractiveObject.cs b/Assets/Scripts/UVC/Object3d/InteractiveObject.cs index 2d3c10c7..c4aa8341 100644 --- a/Assets/Scripts/UVC/Object3d/InteractiveObject.cs +++ b/Assets/Scripts/UVC/Object3d/InteractiveObject.cs @@ -20,25 +20,18 @@ namespace UVC.Object3d /// 포인터로 이 객체를 클릭했을 때 호출됩니다. /// /// 클릭 이벤트와 관련된 데이터입니다. - public virtual void OnPointerClick(PointerEventData eventData) - { - Debug.Log($"OnPointerClick1: {gameObject.name}"); - } + public virtual void OnPointerClick(PointerEventData eventData) {} /// /// 포인터가 이 객체 위로 들어왔을 때 호출됩니다. 하이라이트 효과 등에 사용할 수 있습니다. /// /// 포인터 이벤트와 관련된 데이터입니다. - public virtual void OnPointerEnter(PointerEventData eventData) { - Debug.Log($"OnPointerEnter: {gameObject.name}"); - } + public virtual void OnPointerEnter(PointerEventData eventData) {} /// /// 포인터가 이 객체에서 벗어났을 때 호출됩니다. /// /// 포인터 이벤트와 관련된 데이터입니다. - public virtual void OnPointerExit(PointerEventData eventData) { - Debug.Log($"OnPointerExit: {gameObject.name}"); - } + public virtual void OnPointerExit(PointerEventData eventData) {} } } diff --git a/Assets/Scripts/UVC/input.meta b/Assets/Scripts/UVC/Threading.meta similarity index 77% rename from Assets/Scripts/UVC/input.meta rename to Assets/Scripts/UVC/Threading.meta index c2cff400..e099baca 100644 --- a/Assets/Scripts/UVC/input.meta +++ b/Assets/Scripts/UVC/Threading.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 745da5f00db92f84cb12049e0ca9cd85 +guid: 1ea984474e64af94d8fa097f80657cca folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs b/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs new file mode 100644 index 00000000..ec920a92 --- /dev/null +++ b/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs @@ -0,0 +1,218 @@ +#nullable enable + +using System; +using System.Collections.Concurrent; +using System.Threading; +using UnityEngine; + +namespace UVC.Threading +{ + /// + /// Unity 메인 스레드에서 작업을 실행하기 위한 디스패처 클래스입니다. + /// + /// + /// 이 클래스는 싱글톤 패턴으로 구현되어 있으며, 백그라운드 스레드에서 메인 스레드(UI 스레드)로 + /// 작업을 디스패치하는 기능을 제공합니다. + /// + /// + /// + /// // 백그라운드 스레드에서 UI 업데이트를 해야 하는 경우 (Task 사용) + /// await Task.Run(() => + /// { + /// // 백그라운드 작업 수행 + /// var result = ComputeIntensiveTask(); + /// + /// // UI 업데이트는 메인 스레드에서 수행 + /// MainThreadDispatcher.Instance.Enqueue(() => { + /// UpdateUIWithResult(result); + /// }); + /// }); + /// + /// // UniTask를 사용한 비동기 작업과 메인 스레드 디스패치 예제 + /// async UniTask ProcessDataInBackgroundAsync() + /// { + /// // 스레드풀에서 실행 + /// await UniTask.SwitchToThreadPool(); + /// + /// try + /// { + /// // 백그라운드에서 시간이 걸리는 작업 수행 + /// var data = await FetchDataFromServerAsync(); + /// var processedData = ProcessLargeData(data); + /// + /// // 결과를 메인 스레드로 전달하여 UI 업데이트 + /// MainThreadDispatcher.Instance.SendToMainThread(() => { + /// // 여기에서 UI 컴포넌트를 안전하게 업데이트 + /// UpdateUI(processedData); + /// ShowSuccessMessage("데이터 처리 완료"); + /// }); + /// } + /// catch (Exception ex) + /// { + /// // 오류 발생 시에도 메인 스레드에서 UI 관련 작업 처리 + /// MainThreadDispatcher.Instance.SendToMainThread(() => { + /// ShowErrorDialog($"오류 발생: {ex.Message}"); + /// Debug.LogException(ex); + /// }); + /// } + /// finally + /// { + /// // 작업 완료 후 필요한 경우 다시 메인 스레드로 전환 + /// await UniTask.SwitchToMainThread(); + /// // 여기서부터는 다시 메인 스레드에서 실행됨 + /// CleanupResources(); + /// } + /// } + /// + /// // MainThreadDispatcher와 UniTask를 함께 활용한 이벤트 핸들러 예제 + /// public async void OnButtonClick() + /// { + /// // UI 상태 업데이트 + /// loadingIndicator.SetActive(true); + /// + /// try + /// { + /// // 스레드풀로 전환하여 무거운 작업 수행 + /// await UniTask.SwitchToThreadPool(); + /// + /// // 시간이 걸리는 작업 수행 + /// var result = await PerformHeavyComputationAsync(); + /// + /// // 결과를 UI에 반영 (메인 스레드에서) + /// MainThreadDispatcher.Instance.SendToMainThread(() => { + /// resultText.text = result.ToString(); + /// loadingIndicator.SetActive(false); + /// }); + /// } + /// catch (Exception ex) + /// { + /// // 예외 처리도 메인 스레드에서 + /// MainThreadDispatcher.Instance.SendToMainThread(() => { + /// errorText.text = ex.Message; + /// loadingIndicator.SetActive(false); + /// }); + /// } + /// } + /// + /// + public class MainThreadDispatcher : MonoBehaviour + { + private static MainThreadDispatcher _instance; + private static bool _instantiated; + private static SynchronizationContext _mainThreadContext; + + /// + /// MainThreadDispatcher의 단일 인스턴스를 가져옵니다. + /// + /// + /// 인스턴스가 아직 생성되지 않은 경우, 새로운 GameObject를 생성하고 + /// 그 GameObject에 MainThreadDispatcher 컴포넌트를 추가합니다. + /// + public static MainThreadDispatcher Instance + { + get + { + if (!_instantiated) + { + Initialize(); + } + return _instance; + } + } + + /// + /// 메인 스레드 디스패처를 초기화합니다. + /// + private static void Initialize() + { + if (!_instantiated) + { + // 이미 존재하는지 확인 + _instance = FindFirstObjectByType(); + + // 없으면 새로 생성 + if (_instance == null) + { + var go = new GameObject("MainThreadDispatcher"); + _instance = go.AddComponent(); + DontDestroyOnLoad(go); // 씬 전환 시에도 유지 + } + + _instantiated = true; + _mainThreadContext = SynchronizationContext.Current; + } + } + + private readonly ConcurrentQueue _actionQueue = new ConcurrentQueue(); + + /// + /// 메인 스레드에서 실행할 액션을 큐에 추가합니다. + /// + /// 메인 스레드에서 실행할 액션 + public void Enqueue(Action action) + { + if (action == null) return; + + // 현재 스레드가 메인 스레드면 바로 실행 + if (Thread.CurrentThread.ManagedThreadId == 1) + { + action.Invoke(); + return; + } + + // 아니면 큐에 추가하여 나중에 실행 + _actionQueue.Enqueue(action); + } + + /// + /// SynchronizationContext를 통해 메인 스레드에서 액션을 실행합니다. + /// + /// 메인 스레드에서 실행할 액션 + public void SendToMainThread(Action action) + { + if (action == null) return; + + // SynchronizationContext가 있으면 사용 + if (_mainThreadContext != null) + { + _mainThreadContext.Post(_ => action(), null); + } + else + { + // SynchronizationContext가 없으면 큐에 추가 + Enqueue(action); + } + } + + private void Update() + { + // 큐에 있는 모든 액션 처리 + while (_actionQueue.TryDequeue(out Action action)) + { + try + { + action.Invoke(); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + } + + private void Awake() + { + if (_instance == null) + { + _instance = this; + _mainThreadContext = SynchronizationContext.Current; + _instantiated = true; + DontDestroyOnLoad(gameObject); + } + else if (_instance != this) + { + Destroy(gameObject); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs.meta b/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs.meta new file mode 100644 index 00000000..190f30fa --- /dev/null +++ b/Assets/Scripts/UVC/Threading/MainThreadDispatcher.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 116a97c0eb67f214388de1a4c61c6046 \ No newline at end of file diff --git a/Assets/Scripts/UVC/UI/Info/InfoWindow.cs b/Assets/Scripts/UVC/UI/Info/InfoWindow.cs index 2bcd823e..0bb7028f 100644 --- a/Assets/Scripts/UVC/UI/Info/InfoWindow.cs +++ b/Assets/Scripts/UVC/UI/Info/InfoWindow.cs @@ -15,9 +15,13 @@ namespace UVC.UI.Info public class InfoWindow : SingletonScene { - [Tooltip("정보 텍스트를 표시할 UI 요소")] + [Tooltip("Label 정보 텍스트를 표시할 UI 요소")] [SerializeField] - private TextMeshProUGUI infoText; + private TextMeshProUGUI labelText; + + [Tooltip("Value 정보 텍스트를 표시할 UI 요소")] + [SerializeField] + private TextMeshProUGUI valueText; [Tooltip("정보 창을 닫을 버튼")] [SerializeField] @@ -25,7 +29,7 @@ namespace UVC.UI.Info [Tooltip("UI가 객체를 가리지 않도록 할 월드 좌표계 오프셋")] [SerializeField] - private Vector3 worldOffset = new Vector3(0, 1.5f, 0); + private Vector2 screenOffset = new Vector2(0f, 0f); // 정보 창이 따라다닐 3D 객체의 Transform private Transform? target; @@ -47,6 +51,9 @@ namespace UVC.UI.Info closeButton.onClick.AddListener(Hide); } + RectTransform? rectTransform = transform as RectTransform; + if (rectTransform != null && screenOffset == Vector2.zero) screenOffset = new Vector2(rectTransform.rect.width / 2 + 10f, - rectTransform.rect.height / 2); + // 처음에는 정보 창을 숨깁니다. if (gameObject.activeSelf) { @@ -57,10 +64,73 @@ namespace UVC.UI.Info private void LateUpdate() { // target이 설정되어 있고 활성화 상태일 때만 위치와 방향을 업데이트합니다. - if (target != null && gameObject.activeSelf) + if (target != null && gameObject.activeSelf && Camera.main != null) { - // 위치 업데이트 - transform.position = target.position + worldOffset; + // 타겟의 렌더러 또는 콜라이더를 가져와 화면 상의 크기를 계산 + Bounds bounds = new Bounds(target.position, Vector3.one); + Renderer? renderer = target.GetComponent(); + Collider? collider = target.GetComponent(); + + // 렌더러가 있으면 렌더러의 바운드를, 없으면 콜라이더의 바운드를 사용 + if (renderer != null) + { + bounds = renderer.bounds; + } + else if (collider != null) + { + bounds = collider.bounds; + } + + // 바운드의 오른쪽 지점을 월드 좌표로 계산 + Vector3 rightPoint = bounds.center + new Vector3(bounds.extents.x, 0, 0); + + // 바운드의 오른쪽 지점을 스크린 좌표로 변환 + Vector3 screenPosRight = Camera.main.WorldToScreenPoint(rightPoint); + + // 추가 오프셋 적용 + screenPosRight.x += screenOffset.x; + screenPosRight.y += screenOffset.y; + + // 메뉴바 영역(상단 70픽셀) 고려 및 화면 밖으로 나가지 않도록 제한 + float menuBarHeight = 70f; + screenPosRight.x = Mathf.Clamp(screenPosRight.x, 100f, Screen.width - 100f); + screenPosRight.y = Mathf.Clamp(screenPosRight.y, 100f, Screen.height - menuBarHeight); + + // RectTransform을 사용하여 UI 위치 설정 + RectTransform? rectTransform = transform as RectTransform; + if (rectTransform != null) + { + // 캔버스의 렌더링 모드에 따라 다르게 처리 + Canvas canvas = GetComponentInParent(); + if (canvas != null) + { + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) + { + rectTransform.position = screenPosRight; + } + else if (canvas.renderMode == RenderMode.ScreenSpaceCamera || + canvas.renderMode == RenderMode.WorldSpace) + { + // 스크린 좌표를 캔버스 상의 로컬 좌표로 변환 + Vector2 localPoint; + RectTransformUtility.ScreenPointToLocalPointInRectangle( + canvas.GetComponent(), + screenPosRight, + canvas.renderMode == RenderMode.ScreenSpaceCamera ? canvas.worldCamera : Camera.main, + out localPoint); + + rectTransform.localPosition = new Vector3(localPoint.x, localPoint.y, rectTransform.localPosition.z); + } + } + } + + // UI가 항상 보이도록 카메라를 향하게 설정 (World Space Canvas인 경우에만 필요) + Canvas parentCanvas = GetComponentInParent(); + if (parentCanvas != null && parentCanvas.renderMode == RenderMode.WorldSpace) + { + transform.LookAt(transform.position + Camera.main.transform.rotation * Vector3.forward, + Camera.main.transform.rotation * Vector3.up); + } } } @@ -72,10 +142,29 @@ namespace UVC.UI.Info public void Show(Transform targetObject, Dictionary information) { target = targetObject; - if (infoText != null) + if (labelText != null) { - infoText.text = information.ToString(); + string labelString = string.Empty; + string valueString = string.Empty; + foreach (var kvp in information) + { + labelString += $"{kvp.Key}\n"; + valueString += $"{kvp.Value ?? "null"}\n"; + } + labelString = labelString.TrimEnd('\n'); // 마지막 줄바꿈 제거 + valueString = valueString.TrimEnd('\n'); // 마지막 줄바꿈 제거 + Debug.Log($"InfoWindow: {labelString}, {valueString}"); + labelText.text = labelString; + valueText.text = valueString; } + + //size를 text에 맞게 조정합니다. + RectTransform? rect = GetComponent(); + if (rect != null) + { + rect.sizeDelta = new Vector2(rect.rect.width, valueText.preferredHeight + 25f); + } + gameObject.SetActive(true); // 즉시 위치와 방향을 업데이트합니다. diff --git a/Assets/Scripts/UVC/UI/Modal/Modal.cs b/Assets/Scripts/UVC/UI/Modal/Modal.cs index e9aa35c2..4eeceaa1 100644 --- a/Assets/Scripts/UVC/UI/Modal/Modal.cs +++ b/Assets/Scripts/UVC/UI/Modal/Modal.cs @@ -4,7 +4,7 @@ using System; // System.Type 사용을 위해 추가 using System.Threading; using UnityEngine; using UVC.Log; -using UVC.util; +using UVC.Util; namespace UVC.UI.Modal { diff --git a/Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs b/Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs index 338d2294..551abdfa 100644 --- a/Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs +++ b/Assets/Scripts/UVC/UI/ToolBar/View/ToolbarView.cs @@ -7,7 +7,7 @@ using UVC.Extension; using UVC.Locale; using UVC.UI.Toolbar.Model; using UVC.UI.Tooltip; -using UVC.util; +using UVC.Util; namespace UVC.UI.Toolbar.View { diff --git a/Assets/Scripts/UVC/UI/Tooltip/TooltipManager.cs b/Assets/Scripts/UVC/UI/Tooltip/TooltipManager.cs index 4d70db55..1c210133 100644 --- a/Assets/Scripts/UVC/UI/Tooltip/TooltipManager.cs +++ b/Assets/Scripts/UVC/UI/Tooltip/TooltipManager.cs @@ -2,7 +2,7 @@ using TMPro; using UnityEngine; using UVC.Locale; -using UVC.util; // LocalizationManager를 사용한다면 필요합니다. +using UVC.Util; // LocalizationManager를 사용한다면 필요합니다. namespace UVC.UI.Tooltip { diff --git a/Assets/Scripts/UVC/Util/CameraController.cs b/Assets/Scripts/UVC/Util/CameraController.cs new file mode 100644 index 00000000..196a2c34 --- /dev/null +++ b/Assets/Scripts/UVC/Util/CameraController.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections; +using UnityEngine; +using UVC.Core; + +namespace UVC.Util +{ + /// + /// 마우스 입력에 따라 카메라를 이동, 회전, 줌하는 컨트롤러입니다. + /// - 마우스 가운데 버튼 드래그: 카메라 평행 이동 (Pan) + /// - 마우스 오른쪽 버튼 드래그: 카메라 회전 (Orbit) + /// - 마우스 휠 스크롤: 카메라 줌 (Zoom) + /// + public class CameraController : SingletonScene + { + [Tooltip("카메라 평행 이동 속도")] + public float panSpeed = 20f; + + [Tooltip("카메라 회전 속도")] + public float rotationSpeed = 300f; + + [Tooltip("카메라 줌 속도")] + public float zoomSpeed = 10f; + + [Header("Movement Smoothing")] + [Tooltip("패닝 시 마우스 이동량의 최대값을 제한하여, 프레임 드랍 시 카메라가 급격하게 튀는 현상을 방지합니다.")] + public float maxPanDelta = 50f; + + private Vector3 lastPanPosition; + private Vector3 rotationPivot; + private bool isRotating = false; + + void Start() + { + // 스크립트 시작 시, 회전의 기준이 되는 중심점을 카메라 앞쪽으로 초기화합니다. + rotationPivot = transform.position + transform.forward * 10f; + } + + // Update 대신 LateUpdate를 사용하여 카메라 움직임이 다른 모든 업데이트 이후에 처리되도록 합니다. + // 이를 통해 카메라의 떨림이나 끊김 현상을 줄일 수 있습니다. + void LateUpdate() + { + HandlePanning(); + HandleRotation(); + HandleZoom(); + } + + /// + /// 마우스 가운데 버튼으로 카메라를 평행 이동시킵니다. + /// 프레임 지연으로 인한 급격한 이동을 방지하기 위해 이동량을 제한합니다. + /// + private void HandlePanning() + { + if (Input.GetMouseButtonDown(2)) + { + lastPanPosition = Input.mousePosition; + } + + if (Input.GetMouseButton(2)) + { + Vector3 delta = Input.mousePosition - lastPanPosition; + + // 프레임 드랍 시 델타 값이 너무 커져서 카메라가 튀는 것을 방지하기 위해 최대값을 제한합니다. + if (delta.magnitude > maxPanDelta) + { + delta = delta.normalized * maxPanDelta; + } + + // 카메라의 로컬 좌표계를 기준으로 이동량을 변환하여 월드 좌표계에서 이동시킵니다. + transform.Translate(transform.right * -delta.x * panSpeed * Time.deltaTime, Space.World); + transform.Translate(transform.up * -delta.y * panSpeed * Time.deltaTime, Space.World); + + lastPanPosition = Input.mousePosition; + } + } + + /// + /// 마우스 오른쪽 버튼으로 카메라를 회전시킵니다. + /// 회전 축이 변하는 것을 방지하여 안정적인 회전을 구현합니다. + /// + private void HandleRotation() + { + if (Input.GetMouseButtonDown(1)) + { + isRotating = true; + // 마우스 클릭 지점으로 Ray를 쏴서 회전의 중심점(pivot)을 설정합니다. + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + if (Physics.Raycast(ray, out RaycastHit hit, 1000f)) + { + rotationPivot = hit.point; + } + else + { + // Ray가 아무 오브젝트에도 맞지 않았다면, 카메라 앞쪽의 특정 거리를 중심점으로 사용합니다. + rotationPivot = transform.position + transform.forward * 10f; + } + } + + if (Input.GetMouseButtonUp(1)) + { + isRotating = false; + } + + if (isRotating && Input.GetMouseButton(1)) + { + float mouseX = Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime; + float mouseY = Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime; + + // 수평 회전으로 인해 수직 회전 축(transform.right)이 변질되는 것을 방지하기 위해 + // 회전 전의 right 벡터를 미리 저장해 둡니다. + Vector3 verticalRotationAxis = transform.right; + + // 설정된 중심점을 기준으로 카메라를 회전시킵니다. + // 1. 수평 회전 (월드 Y축 기준) + transform.RotateAround(rotationPivot, Vector3.up, -mouseX); + // 2. 수직 회전 (미리 저장해 둔 카메라의 오른쪽 축 기준) + transform.RotateAround(rotationPivot, verticalRotationAxis, mouseY); + } + } + + /// + /// 마우스 휠로 카메라를 줌 인/아웃합니다. + /// + private void HandleZoom() + { + float scroll = Input.GetAxis("Mouse ScrollWheel"); + if (scroll != 0f) + { + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + Vector3 zoomTarget; + + if (Physics.Raycast(ray, out RaycastHit hit)) + { + zoomTarget = hit.point; + } + else + { + zoomTarget = ray.GetPoint(1000); + } + + Vector3 direction = zoomTarget - transform.position; + + // 줌 실행 + transform.position += direction.normalized * scroll * zoomSpeed; + } + } + + + /// + /// 지정된 Transform을 중심으로 카메라를 포커싱합니다. + /// + /// 포커스할 대상의 Transform + /// 대상과의 거리 + public void FocusOnTargetFast(Transform equipmentTransform, float distance) + { + if (equipmentTransform == null) + return; + + // 카메라가 바라볼 대상의 중심점 + Vector3 targetPosition = equipmentTransform.position; + + // 현재 카메라의 회전각을 유지하면서 타겟을 바라보는 방향 설정 + Vector3 directionToTarget = (targetPosition - transform.position).normalized; + + // 타겟으로부터 지정된 거리만큼 떨어진 위치 계산 + Vector3 newPosition = targetPosition - directionToTarget * distance; + + // 카메라 위치 설정 및 타겟을 바라보도록 함 + transform.position = newPosition; + transform.LookAt(targetPosition); + + // 회전 피봇 포인트 업데이트 + rotationPivot = targetPosition; + } + + /// + /// 지정된 Transform을 중심으로 카메라를 포커싱합니다. + /// + /// 포커스할 대상의 Transform + /// 대상과의 거리 + /// 이동에 걸리는 시간(초), 기본값 1초 + public void FocusOnTarget(Transform equipmentTransform, float distance, float duration = 1.0f) + { + if (equipmentTransform == null) + return; + + // 코루틴을 사용하여 부드러운 이동 구현 + StartCoroutine(SmoothFocusOnTarget(equipmentTransform, distance, duration)); + } + + /// + /// 부드럽게 타겟까지 이동하는 코루틴 + /// + private IEnumerator SmoothFocusOnTarget(Transform targetTransform, float distance, float duration) + { + // 카메라가 바라볼 대상의 중심점 + Vector3 targetPosition = targetTransform.position; + + // 시작 위치와 회전 저장 + Vector3 startPosition = transform.position; + Quaternion startRotation = transform.rotation; + + // 타겟을 보는 최종 위치와 회전 계산 + Vector3 directionToTarget = (targetPosition - startPosition).normalized; + Vector3 endPosition = targetPosition - directionToTarget * distance; + + // 최종 회전값 계산 + Quaternion endRotation = Quaternion.LookRotation(targetPosition - endPosition); + + // 이동 시간 계산을 위한 변수 + float elapsedTime = 0f; + + while (elapsedTime < duration) + { + elapsedTime += Time.deltaTime; + float t = Mathf.Clamp01(elapsedTime / duration); + + // 부드러운 이동을 위한 Easing 함수 적용 + float smoothT = EaseInOutCubic(t); + + // 위치와 회전 보간 + transform.position = Vector3.Lerp(startPosition, endPosition, smoothT); + transform.rotation = Quaternion.Slerp(startRotation, endRotation, smoothT); + + yield return null; + } + + // 정확한 최종 위치와 회전 설정 + transform.position = endPosition; + transform.LookAt(targetPosition); + + // 회전 피봇 포인트 업데이트 + rotationPivot = targetPosition; + } + + /// + /// Cubic ease-in/out 함수로 부드러운 이동 효과를 줍니다. + /// + private float EaseInOutCubic(float t) + { + return t < 0.5f ? 4f * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 3f) / 2f; + } + } +} diff --git a/Assets/Scripts/UVC/Util/CameraController.cs.meta b/Assets/Scripts/UVC/Util/CameraController.cs.meta new file mode 100644 index 00000000..b790daac --- /dev/null +++ b/Assets/Scripts/UVC/Util/CameraController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 61deddb674c074049a9b43fd58f1b355 \ No newline at end of file diff --git a/Assets/Scripts/UVC/input/InputHandler.cs b/Assets/Scripts/UVC/input/InputHandler.cs deleted file mode 100644 index 57c5598a..00000000 --- a/Assets/Scripts/UVC/input/InputHandler.cs +++ /dev/null @@ -1,58 +0,0 @@ -using UnityEngine; - -namespace UVC.input -{ - public class InputHandler : MonoBehaviour - { - public Transform clickedObject; - - // 프레임당 한 번씩 업데이트가 호출됩니다 - void Update() - { - // 터치 입력 확인 - if (UnityEngine.Input.touchCount > 0) - { - if (UnityEngine.Input.GetTouch(0).phase == TouchPhase.Began) - { - handleClick(UnityEngine.Input.GetTouch(0).position); - } - } - // 왼쪽 마우스 버튼 클릭 확인 - if (UnityEngine.Input.GetMouseButtonDown(0)) - { - handleClick(UnityEngine.Input.mousePosition); - } - } - - void handleClick(Vector3 screenClickPosition) - { - // 클릭한 위치에서 카메라에 수직인 Ray를 그립니다 - // Ray가 교차하는 첫 번째 객체를 캡처하기 위해 RayHit를 생성합니다 - Ray ray = Camera.main.ScreenPointToRay(screenClickPosition); - RaycastHit rayHit; - if (Physics.Raycast(ray.origin, ray.direction, out rayHit)) - { - Debug.Log($"Ray Origin: {ray.origin}, Direction: {ray.direction}"); - if (rayHit.transform.tag == "Clickable") - { - // 클릭한 객체에 어떤 작업을 합니다. - clickedObject = rayHit.transform; - // 다음 클릭을 위해 ray와 rayHit을 재설정합니다. - ray = new Ray(); - rayHit = new RaycastHit(); - } - else if (clickedObject != null) - { - // 클릭한 객체의 y 위치에서 xz 축에 평면을 그립니다. - Plane xzPlane = new Plane(Vector3.up, clickedObject.position); - float distance; // 클릭과 평면이 교차 하는 지점을 찾습니다. - // 그리고 클릭한 객체를 새로운 위치로 이동합니다. - if (xzPlane.Raycast(ray, out distance)) - { - clickedObject.position = ray.GetPoint(distance); - } - } - } - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/UVC/input/InputHandler.cs.meta b/Assets/Scripts/UVC/input/InputHandler.cs.meta deleted file mode 100644 index 8dda507d..00000000 --- a/Assets/Scripts/UVC/input/InputHandler.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 8de502d6dd9c6114f993b104854864c5 \ No newline at end of file diff --git a/Assets/Scripts/UVC/input/MouseInputHandler.cs b/Assets/Scripts/UVC/input/MouseInputHandler.cs deleted file mode 100644 index 313079b7..00000000 --- a/Assets/Scripts/UVC/input/MouseInputHandler.cs +++ /dev/null @@ -1,79 +0,0 @@ -using UnityEngine; -using UnityEngine.InputSystem; - -namespace UVC.input -{ - public class MouseInputHandler : MonoBehaviour - { - private MouseControls mouseControls; - private Camera mainCamera; - - private GameObject lastHoveredObject = null; - - private void Awake() - { - mainCamera = Camera.main; - mouseControls = new MouseControls(); - } - - private void OnEnable() - { - mouseControls.Player.Enable(); - mouseControls.Player.Click.performed += OnClick; - } - - private void OnDisable() - { - mouseControls.Player.Disable(); - mouseControls.Player.Click.performed -= OnClick; - } - - void Update() - { - // 마우스 위치로 Ray 발사 - Ray ray = mainCamera.ScreenPointToRay(mouseControls.Player.Point.ReadValue()); - RaycastHit hit; - - GameObject currentHoveredObject = null; - - if (Physics.Raycast(ray, out hit)) - { - // Ray에 맞은 객체가 있을 경우 - currentHoveredObject = hit.collider.gameObject; - } - - // 마우스 오버/아웃 상태 변경 감지 - if (currentHoveredObject != lastHoveredObject) - { - // 이전에 가리키던 객체가 있었다면 Mouse Out 이벤트 호출 - if (lastHoveredObject != null) - { - // 여기에 Mouse Out 로직을 추가하세요. - Debug.Log("Mouse Out: " + lastHoveredObject.name); - // 예: lastHoveredObject.GetComponent().material.color = Color.white; - } - - // 현재 가리키는 객체가 있다면 Mouse Over 이벤트 호출 - if (currentHoveredObject != null) - { - // 여기에 Mouse Over 로직을 추가하세요. - Debug.Log("Mouse Over: " + currentHoveredObject.name); - // 예: currentHoveredObject.GetComponent().material.color = Color.red; - } - - lastHoveredObject = currentHoveredObject; - } - } - - private void OnClick(InputAction.CallbackContext context) - { - Debug.Log("Clicked"); - // 현재 마우스가 가리키고 있는 객체가 있을 때만 클릭 이벤트 처리 - if (lastHoveredObject != null) - { - // 여기에 Mouse Click 로직을 추가하세요. - Debug.Log("Clicked on: " + lastHoveredObject.name); - } - } - } -} diff --git a/Assets/Scripts/UVC/input/MouseInputHandler.cs.meta b/Assets/Scripts/UVC/input/MouseInputHandler.cs.meta deleted file mode 100644 index 82d34f87..00000000 --- a/Assets/Scripts/UVC/input/MouseInputHandler.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 72b9b338934540349a2d195547344dab \ No newline at end of file diff --git a/Assets/Scripts/UVC/util/CanvasUtil.cs b/Assets/Scripts/UVC/util/CanvasUtil.cs index ac264a05..273b76af 100644 --- a/Assets/Scripts/UVC/util/CanvasUtil.cs +++ b/Assets/Scripts/UVC/util/CanvasUtil.cs @@ -2,7 +2,7 @@ using UnityEngine; using UnityEngine.UI; -namespace UVC.util +namespace UVC.Util { public static class CanvasUtil { diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index d057ba3d..23c00db8 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -6,7 +6,7 @@ EditorBuildSettings: serializedVersion: 2 m_Scenes: - enabled: 1 - path: Assets/Scenes/SampleScene.unity + path: Assets/Scenes/SampleProject.unity guid: 99c9720ab356a0642a771bea13969a05 m_configObjects: com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}