From a7d741b81ece6c28e6a939680ec7c23bb76017fb Mon Sep 17 00:00:00 2001 From: Jeonghyeon Ha Date: Thu, 28 Aug 2025 14:52:21 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EB=A0=88=EC=8A=A4=ED=86=A0=EB=9E=91=20?= =?UTF-8?q?=EC=83=81=ED=98=B8=EC=9E=91=EC=9A=A9=20=EC=8B=9C=EC=8A=A4?= =?UTF-8?q?=ED=85=9C=20=EA=B0=9C=EC=84=A0:=20-=20=EA=B3=A0=EA=B0=9D=20AI?= =?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=20=EC=8B=9C=EC=9E=91/=EB=8C=80=EA=B8=B0/?= =?UTF-8?q?=EA=B0=80=EC=9A=A9=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=95=88=EC=A0=95=EC=84=B1=20=ED=96=A5?= =?UTF-8?q?=EC=83=81=20-=20IInteractionSubsystemOwner=20=EB=B0=8F=20Order?= =?UTF-8?q?=20Subsystem=20=EC=97=B0=EB=8F=99=20=EB=B3=B4=EA=B0=95=20-=20Pl?= =?UTF-8?q?ayerInteraction/InteractionComponent=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=9D=90=EB=A6=84=20=EC=88=98=EC=A0=95=20-=20Wait?= =?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=20=EC=86=94=EB=B2=84=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EB=B3=B4=EC=A0=95=20-=20=EA=B3=A0=EA=B0=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8/=EC=A3=BC=EB=AC=B8=20=EC=84=9C=EB=B8=8C=ED=8A=B8?= =?UTF-8?q?=EB=A6=AC=20=EC=97=90=EC=85=8B=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AI/Customer/Subtree/CustomerDefault.asset | 4 +- .../AI/Customer/Subtree/OrderSubtree.asset | 4 +- .../Customer/Actions/StartRestaurantOrder.cs | 58 +++++++++++++------ .../Actions/WaitForPlayerInteraction.cs | 22 ++++--- .../Conditionals/RestaurantOrderAvailable.cs | 20 ++----- .../Character/Player/PlayerInteraction.cs | 11 ++-- .../Environment/IInteractionSubsystemOwner.cs | 1 + .../InteractionSubsystem_Order.cs | 9 +-- .../Event/RestaurantInteractionComponent.cs | 15 +++++ .../RestaurantOrderSolver_Wait.cs | 4 +- 10 files changed, 90 insertions(+), 58 deletions(-) diff --git a/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset b/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset index a793b242d..fdfd90ada 100644 --- a/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset +++ b/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:277f8b3b25cfe078e4838cab1222b85e5dae0bc036cb39e5f84b6e3b3fce1cd0 -size 68048 +oid sha256:4d98b77206ba374a44c488e0c83a0970ea49d46ab9e1802277e48352d9cc1a98 +size 66395 diff --git a/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset b/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset index 7e7bb95e0..6ff001db6 100644 --- a/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset +++ b/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6da8678bc90f664244b89aa26dc5c6b01c51567387ea3414b916fb27082f752b -size 16520 +oid sha256:28c1a3c2113f824ca9b3493aa71a73bffa3040160b830e2fde428b5c7bbe1610 +size 16553 diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs index b954d1bf7..0e5cd3b9d 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs @@ -8,12 +8,6 @@ public class StartRestaurantOrder : Action { [Tooltip("상호작용할 RestaurantOrderType")] [SerializeField] private RestaurantOrderType _targetOrderType = RestaurantOrderType.Wait; - [Tooltip("실제 상호작용 가능 여부를 확인하고 수행합니다")] - [SerializeField] private bool _requireCanInteract = true; - [Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")] - [SerializeField] private bool _registerOnBlackboard = true; - [Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")] - [SerializeField] private bool _UnregisterOnBlackboard = false; private IInteractor _interactor; private bool _isGetInteractor; @@ -28,29 +22,55 @@ public override void OnStart() public override TaskStatus OnUpdate() { - // 레스토랑 주문 인터랙션 후보를 가져옴 - TaskStatus targetSearchSuccess = RestaurantOrderAvailable.FindAvailableOrderInteractable(_requireCanInteract, _targetOrderType, out var - outInteractable); - if (targetSearchSuccess == TaskStatus.Failure) + var blackboard = gameObject.GetComponent(); + var target = blackboard?.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + IInteractable currentInteractable = target?.GetComponent(); + + if (_targetOrderType == RestaurantOrderType.Wait) { + // 레스토랑 주문 인터랙션 후보를 가져옴 + TaskStatus targetSearchSuccess = RestaurantOrderAvailable.FindAvailableOrderInteractable(_targetOrderType, out currentInteractable); + if (targetSearchSuccess == TaskStatus.Failure) + { + return TaskStatus.Failure; + } + var customerBlackboard = gameObject.GetComponent(); + customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), currentInteractable.GetInteractableGameObject()); + } + + // Check order type of the current interactable + if (currentInteractable is IInteractionSubsystemOwner subsystemOwner) + { + if (subsystemOwner.TryGetSubsystemEnumType(out var subsystemType)) + { + if (subsystemType != _targetOrderType) + { + Debug.LogWarning($"[{GetType().Name}] 상호작용할 RestaurantOrderType이 다릅니다: {subsystemType} != {_targetOrderType}"); + return TaskStatus.Failure; + } + } + else + { + return TaskStatus.Failure; + } + } + + + if (currentInteractable == null) + { + Debug.Assert(false); return TaskStatus.Failure; } // 상호작용 수행: 액션이 붙은 에이전트를 Interactor로 사용 - if (!_isGetInteractor || !_interactor.CanInteractTo(outInteractable)) + if (!_isGetInteractor) { return TaskStatus.Failure; } - RestaurantEvents.InteractionEvent.RequestInteraction(_interactor.GetInteractorGameObject(), outInteractable.gameObject, outInteractable.GetInteractionType()); + RestaurantEvents.InteractionEvent.RequestInteraction(_interactor.GetInteractorGameObject(), currentInteractable.GetInteractableGameObject(), currentInteractable.GetInteractionType()); - if (_registerOnBlackboard) - { - var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), outInteractable.gameObject); - } - - if (_UnregisterOnBlackboard) + if (_targetOrderType == RestaurantOrderType.Busy) { var customerBlackboard = gameObject.GetComponent(); customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null); diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs index 30feb0826..c661a508d 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs @@ -9,8 +9,9 @@ namespace DDD.Restaurant public class WaitForPlayerInteraction : Action { [SerializeField] private RestaurantOrderType _targetOrderType; + [SerializeField] private RestaurantOrderType _nextOrderType; private IInteractionSubsystemObject _interactionSubsystem; - private bool _isGetInteractionSubsystem; + private bool _isSubsystemExist; public override void OnStart() { @@ -43,13 +44,19 @@ public override void OnStart() $"[{GetType().Name}]에서 {nameof(IInteractionSubsystemObject)}를 찾을 수 없습니다: {gameObject.name}"); return; } - - _isGetInteractionSubsystem = true; + + if (_interactionSubsystem?.GetInteractionSubsystemType() != _targetOrderType) + { + Debug.Log($"[{GetType().Name}] 다른 Order Type: {_interactionSubsystem?.GetInteractionSubsystemType()} != {_targetOrderType}"); + return; + } + + _isSubsystemExist = true; } public override TaskStatus OnUpdate() { - if (!_isGetInteractionSubsystem) return TaskStatus.Failure; + if (!_isSubsystemExist) return TaskStatus.Failure; TaskStatus result = CheckToSubsystemStatus(); if (result == TaskStatus.Success) Debug.Log($"[{GetType().Name}] Success"); @@ -58,9 +65,10 @@ public override TaskStatus OnUpdate() private TaskStatus CheckToSubsystemStatus() { - return _interactionSubsystem.GetInteractionSubsystemType() == _targetOrderType - ? TaskStatus.Running - : TaskStatus.Success; + var currentSubsystemType = _interactionSubsystem.GetInteractionSubsystemType(); + if (currentSubsystemType == _nextOrderType) + return TaskStatus.Success; + return TaskStatus.Running; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Conditionals/RestaurantOrderAvailable.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Conditionals/RestaurantOrderAvailable.cs index da16bc590..1ee79b586 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Conditionals/RestaurantOrderAvailable.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Conditionals/RestaurantOrderAvailable.cs @@ -28,13 +28,13 @@ public bool CheckCanInteract public override TaskStatus OnUpdate() { - TaskStatus targetSearchSuccess = FindAvailableOrderInteractable(_checkCanInteract, _targetOrderType, out var + TaskStatus targetSearchSuccess = FindAvailableOrderInteractable(_targetOrderType, out var outInteractable); return targetSearchSuccess; } - public static TaskStatus FindAvailableOrderInteractable(bool checkCanInteract, T targetOrderType, out RestaurantInteractionComponent outInteractable) where T : Enum + public static TaskStatus FindAvailableOrderInteractable(RestaurantOrderType targetOrderType, out IInteractable outInteractable) { outInteractable = null; @@ -45,25 +45,17 @@ public static TaskStatus FindAvailableOrderInteractable(bool checkCanInteract } var interactables = environmentState.GetInteractablesByType(InteractionType.RestaurantOrder); - foreach (var interactable in interactables) { // 서브시스템에서 RestaurantOrderType을 가져와 비교 - outInteractable = interactable as RestaurantInteractionComponent; - if (outInteractable == null) continue; - if (!outInteractable.TryGetSubsystemObject(out var subsystem)) continue; - - if (EqualityComparer.Default.Equals(subsystem.GetInteractionSubsystemType(), targetOrderType)) + if (interactable is not IInteractionSubsystemOwner subsystemOwner) continue; + if (!subsystemOwner.TryGetSubsystemObject(out var subsystem)) continue; + if (subsystem.GetInteractionSubsystemType() == targetOrderType) { - // CheckCanInteract이 false면 타입만 맞으면 성공 - if (!checkCanInteract) - { - return TaskStatus.Success; - } - // CheckCanInteract이 true면 실제 인터랙션 가능 여부까지 확인 if (interactable.CanInteract()) { + outInteractable = interactable; return TaskStatus.Success; } } diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs index 21832e1ea..6053e032b 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs @@ -39,14 +39,17 @@ private Task Initialize() public override void InitializeSolvers() { - var typesToSolver = RestaurantInteractionEventSolvers.TypeToSolver; var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver; - foreach(var pair in playerSolver) + Dictionary typesToSolver = new(); + foreach (var typeToSolver in RestaurantInteractionEventSolvers.TypeToSolver) { - typesToSolver.Remove(pair.Key); + typesToSolver.Add(typeToSolver.Key, typeToSolver.Value); + } + foreach (var typeToSolver in playerSolver) + { + typesToSolver[typeToSolver.Key] = typeToSolver.Value; } InitializeInteractionSolvers(typesToSolver); - InitializeInteractionSolvers(playerSolver); } protected override void OnDestroy() diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/IInteractionSubsystemOwner.cs b/Assets/_DDD/_Scripts/Restaurant/Environment/IInteractionSubsystemOwner.cs index bd99e64be..69d57ccec 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Environment/IInteractionSubsystemOwner.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/IInteractionSubsystemOwner.cs @@ -6,5 +6,6 @@ namespace DDD public interface IInteractionSubsystemOwner { public bool TryGetSubsystemObject(out IInteractionSubsystemObject subsystemObject) where T : Enum; + public bool TryGetSubsystemEnumType(out T subsystemType) where T : Enum; } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Order.cs b/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Order.cs index fde3d3f3c..968306869 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Order.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Order.cs @@ -21,13 +21,7 @@ public interface IRestaurantOrderObject public class InteractionSubsystem_Order : MonoBehaviour, IInteractionSubsystemObject, IRestaurantOrderObject { - [FormerlySerializedAs("orderType")] [SerializeField] protected RestaurantOrderType _orderType = RestaurantOrderType.Wait; - private RestaurantOrderType _currentRestaurantOrderType; - - private void Start() - { - _currentRestaurantOrderType = _orderType; - } + [SerializeField] private RestaurantOrderType _currentRestaurantOrderType = RestaurantOrderType.Wait; public bool CanInteract() { @@ -58,7 +52,6 @@ public ScriptableObject GetPayload() public void InitializeSubsystem() { - _currentRestaurantOrderType = _orderType; } public RestaurantOrderType GetInteractionSubsystemType() diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs index 422daa866..f13b03a20 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs @@ -185,5 +185,20 @@ public bool TryGetSubsystemObject(out IInteractionSubsystemObject subsyste subsystemObject = null; return false; } + + public bool TryGetSubsystemEnumType(out T enumValue) where T : Enum + { + foreach (var interactionSubsystemObject in _subsystems.Values) + { + if (interactionSubsystemObject is IInteractionSubsystemObject subsystem) + { + enumValue = subsystem.GetInteractionSubsystemType(); + return true; + } + } + + enumValue = default; + return false; + } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver_Wait.cs b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver_Wait.cs index 62dc989e4..536232103 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver_Wait.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver_Wait.cs @@ -7,8 +7,8 @@ public class RestaurantOrderSolver_Wait : MonoBehaviour, IInteractionSubsystemSo { public bool ExecuteInteractionSubsystem(IInteractor interactor, IInteractable interactable, ScriptableObject payload = null) { - if (CanExecuteInteractionSubsystem(interactor, interactable, payload) == false) return false; - + if (CanExecuteInteractionSubsystem(interactor, interactable, payload) == false) + return false; if (interactable is not IInteractionSubsystemOwner subsystemOwner) return false; if (!subsystemOwner.TryGetSubsystemObject(out var subsystem)) From ab734e8081d7909423652b84cda9c906f58b35a5 Mon Sep 17 00:00:00 2001 From: Jeonghyeon Ha Date: Thu, 28 Aug 2025 16:52:18 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=9D=B8=ED=84=B0=EB=9E=99=EC=85=98=20?= =?UTF-8?q?=EC=88=A8=EA=B9=80=20=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/RestaurantOrder.prefab | 266 +++++++++++++++++- .../_Scripts/Game/GameEvent/IInteractable.cs | 2 +- .../Customer/Actions/StartRestaurantOrder.cs | 2 - .../Character/Core/CharacterInteraction.cs | 9 +- .../Character/Player/PlayerInteraction.cs | 12 +- .../Event/Cosmetic/InteractableHighlight.cs | 5 +- .../Event/RestaurantInteractionComponent.cs | 21 +- 7 files changed, 305 insertions(+), 12 deletions(-) diff --git a/Assets/_DDD/Restaurant/Environments/Interactables/Common/RestaurantOrder.prefab b/Assets/_DDD/Restaurant/Environments/Interactables/Common/RestaurantOrder.prefab index 546d96553..6220a9d00 100644 --- a/Assets/_DDD/Restaurant/Environments/Interactables/Common/RestaurantOrder.prefab +++ b/Assets/_DDD/Restaurant/Environments/Interactables/Common/RestaurantOrder.prefab @@ -98,6 +98,9 @@ GameObject: - component: {fileID: 3697702677815423220} - component: {fileID: 3591347921553422000} - component: {fileID: 4456475204957017828} + - component: {fileID: 2950132940454135295} + - component: {fileID: 29040892075516248} + - component: {fileID: 1332098886975329103} m_Layer: 7 m_Name: RestaurantOrder m_TagString: Untagged @@ -154,4 +157,265 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c0b1e0992510498b8d33d5b6094b8f4b, type: 3} m_Name: m_EditorClassIdentifier: - orderType: 0 + _currentRestaurantOrderType: 0 +--- !u!135 &2950132940454135295 +SphereCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Radius: 0.2 + m_Center: {x: -0.4, y: 0, z: 0} +--- !u!114 &29040892075516248 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 888380afc233049ce9e618f9f36c8ba8, type: 3} + m_Name: + m_EditorClassIdentifier: + profile: {fileID: 0} + profileSync: 0 + camerasLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + effectGroup: 0 + effectTarget: {fileID: 0} + effectGroupLayer: + serializedVersion: 2 + m_Bits: 4294967295 + effectNameFilter: + effectNameUseRegEx: 0 + combineMeshes: 0 + alphaCutOff: 0.5 + cullBackFaces: 0 + padding: 0 + ignoreObjectVisibility: 0 + reflectionProbes: 0 + GPUInstancing: 1 + sortingPriority: 0 + optimizeSkinnedMesh: 1 + depthClip: 0 + cameraDistanceFade: 0 + cameraDistanceFadeNear: 0 + cameraDistanceFadeFar: 1000 + normalsOption: 0 + ignore: 0 + _highlighted: 0 + fadeInDuration: 0 + fadeOutDuration: 0 + flipY: 0 + constantWidth: 1 + extraCoveragePixels: 0 + minimumWidth: 0 + subMeshMask: -1 + overlay: 0 + overlayMode: 0 + overlayColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} + overlayAnimationSpeed: 1 + overlayMinIntensity: 0.5 + overlayBlending: 1 + overlayTexture: {fileID: 0} + overlayTextureUVSpace: 0 + overlayTextureScale: 1 + overlayTextureScrolling: {x: 0, y: 0} + overlayVisibility: 0 + outline: 1 + outlineColor: {r: 0, g: 0, b: 0, a: 1} + outlineColorStyle: 0 + outlineGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_ColorSpace: -1 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + outlineGradientInLocalSpace: 0 + outlineWidth: 0.45 + outlineBlurPasses: 2 + outlineQuality: 2 + outlineEdgeMode: 0 + outlineEdgeThreshold: 0.995 + outlineSharpness: 1 + outlineDownsampling: 1 + outlineVisibility: 0 + glowBlendMode: 0 + outlineBlitDebug: 0 + outlineIndependent: 0 + outlineContourStyle: 0 + outlineMaskMode: 0 + glow: 0 + glowWidth: 0.4 + glowQuality: 2 + glowBlurMethod: 0 + glowDownsampling: 2 + glowHQColor: {r: 0.64, g: 1, b: 0, a: 1} + glowDithering: 1 + glowDitheringStyle: 0 + glowMagicNumber1: 0.75 + glowMagicNumber2: 0.5 + glowAnimationSpeed: 1 + glowVisibility: 0 + glowBlitDebug: 0 + glowBlendPasses: 1 + glowPasses: + - offset: 4 + alpha: 0.1 + color: {r: 0.64, g: 1, b: 0, a: 1} + - offset: 3 + alpha: 0.2 + color: {r: 0.64, g: 1, b: 0, a: 1} + - offset: 2 + alpha: 0.3 + color: {r: 0.64, g: 1, b: 0, a: 1} + - offset: 1 + alpha: 0.4 + color: {r: 0.64, g: 1, b: 0, a: 1} + glowMaskMode: 0 + innerGlow: 0 + innerGlowWidth: 1 + innerGlowColor: {r: 1, g: 1, b: 1, a: 1} + innerGlowBlendMode: 0 + innerGlowVisibility: 0 + targetFX: 0 + targetFXTexture: {fileID: 0} + targetFXColor: {r: 1, g: 1, b: 1, a: 1} + targetFXCenter: {fileID: 0} + targetFXRotationSpeed: 50 + targetFXInitialScale: 4 + targetFXEndScale: 1.5 + targetFXScaleToRenderBounds: 1 + targetFXUseEnclosingBounds: 0 + targetFXAlignToGround: 0 + targetFXOffset: {x: 0, y: 0, z: 0} + targetFXFadePower: 32 + targetFXGroundMaxDistance: 10 + targetFXGroundLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + targetFXTransitionDuration: 0.5 + targetFXStayDuration: 1.5 + targetFXVisibility: 1 + iconFX: 0 + iconFXMesh: {fileID: 0} + iconFXLightColor: {r: 1, g: 1, b: 1, a: 1} + iconFXDarkColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + iconFXCenter: {fileID: 0} + iconFXRotationSpeed: 50 + iconFXAnimationOption: 0 + iconFXAnimationAmount: 0.1 + iconFXAnimationSpeed: 3 + iconFXScale: 1 + iconFXScaleToRenderBounds: 0 + iconFXOffset: {x: 0, y: 1, z: 0} + iconFXTransitionDuration: 0.5 + iconFXStayDuration: 1.5 + seeThrough: 2 + seeThroughOccluderMask: + serializedVersion: 2 + m_Bits: 4294967295 + seeThroughOccluderThreshold: 0.3 + seeThroughOccluderMaskAccurate: 0 + seeThroughOccluderCheckInterval: 1 + seeThroughOccluderCheckIndividualObjects: 0 + seeThroughDepthOffset: 0 + seeThroughMaxDepth: 0 + seeThroughIntensity: 0.8 + seeThroughTintAlpha: 0.5 + seeThroughTintColor: {r: 1, g: 0, b: 0, a: 1} + seeThroughNoise: 1 + seeThroughBorder: 0 + seeThroughBorderColor: {r: 0, g: 0, b: 0, a: 1} + seeThroughBorderOnly: 0 + seeThroughBorderWidth: 0.45 + seeThroughOrdered: 0 + seeThroughTexture: {fileID: 0} + seeThroughTextureUVSpace: 0 + seeThroughTextureScale: 1 + seeThroughChildrenSortingMode: 0 + rmsCount: 1 + hitFxInitialIntensity: 0 + hitFxMode: 0 + hitFxFadeOutDuration: 0.25 + hitFxColor: {r: 1, g: 1, b: 1, a: 1} + hitFxRadius: 0.5 +--- !u!114 &1332098886975329103 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f0feb22ab60a4d1885271637838f43b9, type: 3} + m_Name: + m_EditorClassIdentifier: + _availableStyle: + Color: {r: 1, g: 1, b: 1, a: 1} + Width: 1 + Opacity: 1 + _focusedStyle: + Color: {r: 1, g: 0.92156863, b: 0.015686275, a: 1} + Width: 1 + Opacity: 1 + _unavailableStyle: + Color: {r: 0.5, g: 0.5, b: 0.5, a: 1} + Width: 0.5 + Opacity: 1 + _objectiveStyle: + Color: {r: 0, g: 1, b: 1, a: 1} + Width: 1 + Opacity: 1 + _breathingSpeed: 2 + _breathingRange: 0.3 + _enableBreathingEffect: 1 + _alphaCutOff: 0.5 + _combineMeshes: 1 + _constantWidth: 1 + _outlineQuality: 2 + _outlineIndependent: 1 + _outlineBlurPasses: 1 + _outlineSharpness: 8 + _currentOutlineType: 0 + _currentOpacityMultiplier: 1 diff --git a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs index 72831c1fd..8131ac6dd 100644 --- a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs @@ -39,7 +39,7 @@ public InteractionDisplayParameters(string messageKey = "") public interface IInteractable { bool CanInteract(); - bool IsInteractionHidden(); + bool IsInteractionHidden(IInteractor interactor = null); void OnInteracted(IInteractor interactor, ScriptableObject causerPayload = null); InteractionType GetInteractionType(); GameObject GetInteractableGameObject(); diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs index 0e5cd3b9d..f294c5c79 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs @@ -25,7 +25,6 @@ public override TaskStatus OnUpdate() var blackboard = gameObject.GetComponent(); var target = blackboard?.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); IInteractable currentInteractable = target?.GetComponent(); - if (_targetOrderType == RestaurantOrderType.Wait) { // 레스토랑 주문 인터랙션 후보를 가져옴 @@ -54,7 +53,6 @@ public override TaskStatus OnUpdate() return TaskStatus.Failure; } } - if (currentInteractable == null) { diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs index 5ec7c67ac..c8352108f 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs @@ -84,7 +84,7 @@ public bool CanSolveInteractionType(InteractionType type) { if (_cachedSolvers.TryGetValue(type, out var cachedSolver)) return cachedSolver != null; - if (RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(type, out var solverType) == false) return false; + if (!FetchSolverTypeForInteraction(type, out var solverType)) return false; if (transform.TryGetComponent(solverType, out var component) == false) return false; @@ -92,7 +92,12 @@ public bool CanSolveInteractionType(InteractionType type) _cachedSolvers[type] = solver; return solver != null; } - + + protected virtual bool FetchSolverTypeForInteraction(InteractionType type, out Type solverType) + { + return RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(type, out solverType); + } + public bool CanInteractTo(IInteractable interactable, ScriptableObject payloadSo = null) { if (interactable == null) return false; diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs index 6053e032b..c9db8be25 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs @@ -185,7 +185,7 @@ protected IInteractable GetNearestInteractable() if (col.TryGetComponent(out var interactable) == false) continue; var type = interactable.GetInteractionType(); - if (interactable.IsInteractionHidden()) continue; + if (interactable.IsInteractionHidden(this)) continue; if (CanSolveInteractionType(type) == false) continue; float distance = Vector3.Distance(transform.position, col.transform.position); @@ -198,5 +198,15 @@ protected IInteractable GetNearestInteractable() return closest; } + + protected override bool FetchSolverTypeForInteraction(InteractionType type, out Type solverType) + { + if (RestaurantInteractionEventSolvers.TypeToPlayerSolver.TryGetValue(type, out solverType)) + { + return true; + } + + return base.FetchSolverTypeForInteraction(type, out solverType); + } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs b/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs index 8d6272b14..24006ed2f 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using UnityEngine; using Sirenix.OdinInspector; @@ -157,8 +158,8 @@ private InteractionOutlineType GetCurrentOutlineType() // IInteractable 인터페이스로 캐스팅하여 상태 확인 if (_interactionComponent is not IInteractable interactable) return InteractionOutlineType.None; - - if (_interactionComponent.IsInteractionHidden()) + + if (_interactionComponent.IsInteractionHidden(_interactor)) { return InteractionOutlineType.None; } diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs index f13b03a20..7d757bfdd 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs @@ -67,11 +67,26 @@ public virtual bool CanInteract() return isInteractionVisible && hasValidSubsystem; } - public virtual bool IsInteractionHidden() + public virtual bool IsInteractionHidden(IInteractor interactor = null) { var currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState; var flowDisabled = (currentGameFlowState & _interactionAvailableFlows) == 0; - return flowDisabled; + if (flowDisabled) + { + return true; + } + + // only check if interactor is valid. if not, pass the check. + if (interactor != null && HasSubsystem(_interactionType)) + { + bool canSolve = interactor.CanSolveInteractionType(_interactionType); + if (!canSolve) + { + return true; + } + } + + return false; } public virtual void OnInteracted(IInteractor interactor, ScriptableObject payload = null) @@ -119,7 +134,7 @@ private bool HasSubsystem(InteractionType interactionType) private IInteractionSubsystemObject GetSubsystem(InteractionType interactionType) { - return _subsystems.GetValueOrDefault(interactionType) as IInteractionSubsystemObject; + return _subsystems.GetValueOrDefault(interactionType); } private bool TryGetSubsystem(InteractionType interactionType, out IInteractionSubsystemObject subsystem) From 3eeed819b2386cffbb07888d89c74de69745fca3 Mon Sep 17 00:00:00 2001 From: Jeonghyeon Ha Date: Thu, 28 Aug 2025 18:16:46 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EC=9D=B8=ED=84=B0=EB=9E=99=EC=85=98=20hidd?= =?UTF-8?q?en(=20interactor=20side=20)=EA=B3=BC=20available(=20interactabl?= =?UTF-8?q?e=20side=20)=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_Scripts/Game/GameEvent/IInteractable.cs | 4 +++- .../Game/GameEvent/InteractionSubsystem.cs | 6 +++--- .../Character/Core/CharacterInteraction.cs | 19 +++++++++++++++-- .../Character/Core/RestaurantCharacter.cs | 5 +++++ .../Character/Player/PlayerInteraction.cs | 3 ++- .../Event/Cosmetic/InteractableHighlight.cs | 6 +++++- .../Event/RestaurantInteractionComponent.cs | 21 ++++++------------- .../Solvers/RestaurantSubsystemSolver.cs | 13 ++++++++++++ 8 files changed, 54 insertions(+), 23 deletions(-) diff --git a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs index 8131ac6dd..886cfc8f9 100644 --- a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs @@ -39,7 +39,7 @@ public InteractionDisplayParameters(string messageKey = "") public interface IInteractable { bool CanInteract(); - bool IsInteractionHidden(IInteractor interactor = null); + bool IsInteractionAvailable(); void OnInteracted(IInteractor interactor, ScriptableObject causerPayload = null); InteractionType GetInteractionType(); GameObject GetInteractableGameObject(); @@ -54,6 +54,7 @@ public interface IInteractor GameObject GetInteractorGameObject(); IInteractable GetFocusedInteractable(); bool CanSolveInteractionType(InteractionType interactionType); + bool IsInteractionHidden(IInteractable interactable); bool CanInteractTo(IInteractable interactable, ScriptableObject payloadSo = null); } @@ -62,5 +63,6 @@ public interface IInteractionSolver { bool ExecuteInteraction(IInteractor interactor, IInteractable interactable, ScriptableObject payload = null); bool CanExecuteInteraction(IInteractor interactor = null, IInteractable interactable = null, ScriptableObject payload = null); + bool CanSolveInteraction(IInteractor interactor, IInteractable interactable); } } diff --git a/Assets/_DDD/_Scripts/Game/GameEvent/InteractionSubsystem.cs b/Assets/_DDD/_Scripts/Game/GameEvent/InteractionSubsystem.cs index cbdc7a8c0..d3165af45 100644 --- a/Assets/_DDD/_Scripts/Game/GameEvent/InteractionSubsystem.cs +++ b/Assets/_DDD/_Scripts/Game/GameEvent/InteractionSubsystem.cs @@ -16,11 +16,11 @@ public interface IInteractionSubsystemObject : IInteractionSubsystemObject wh } public interface IInteractionSubsystemSolver - { - } - public interface IInteractionSubsystemSolver : IInteractionSubsystemSolver where T : Enum { bool ExecuteInteractionSubsystem(IInteractor interactor, IInteractable interactable, ScriptableObject payload = null); bool CanExecuteInteractionSubsystem(IInteractor interactor = null, IInteractable interactable = null, ScriptableObject payload = null); } + public interface IInteractionSubsystemSolver : IInteractionSubsystemSolver where T : Enum + { + } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs index c8352108f..ee8e89e6b 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs @@ -82,8 +82,10 @@ private bool TryGetSolverForType(InteractionType type, out IInteractionSolver so public bool CanSolveInteractionType(InteractionType type) { - if (_cachedSolvers.TryGetValue(type, out var cachedSolver)) return cachedSolver != null; - + if (_cachedSolvers.TryGetValue(type, out var cachedSolver)) + { + return cachedSolver != null; + } if (!FetchSolverTypeForInteraction(type, out var solverType)) return false; if (transform.TryGetComponent(solverType, out var component) == false) return false; @@ -93,6 +95,19 @@ public bool CanSolveInteractionType(InteractionType type) return solver != null; } + public bool IsInteractionHidden(IInteractable interactable) + { + var interactionType = interactable.GetInteractionType(); + if (GetInteractionSolver(interactionType) is var solver) + { + if (solver != null && solver.CanSolveInteraction(this, interactable)) + { + return false; + } + } + return true; + } + protected virtual bool FetchSolverTypeForInteraction(InteractionType type, out Type solverType) { return RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(type, out solverType); diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs index f3a32003e..5599e61ac 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs @@ -37,6 +37,11 @@ public bool CanSolveInteractionType(InteractionType interactionType) return _interactionComponent.CanSolveInteractionType(interactionType); } + public bool IsInteractionHidden(IInteractable interactable) + { + return _interactionComponent.IsInteractionHidden(interactable); + } + public bool CanInteractTo(IInteractable interactable, ScriptableObject payloadSo = null) { return _interactionComponent.CanInteractTo(interactable, payloadSo); diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs index c9db8be25..093f2ddc1 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs @@ -185,8 +185,9 @@ protected IInteractable GetNearestInteractable() if (col.TryGetComponent(out var interactable) == false) continue; var type = interactable.GetInteractionType(); - if (interactable.IsInteractionHidden(this)) continue; + if (!interactable.IsInteractionAvailable()) continue; if (CanSolveInteractionType(type) == false) continue; + if (IsInteractionHidden(interactable)) continue; float distance = Vector3.Distance(transform.position, col.transform.position); if (distance < closestDistance) diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs b/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs index 24006ed2f..a31f62ced 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/Cosmetic/InteractableHighlight.cs @@ -159,7 +159,11 @@ private InteractionOutlineType GetCurrentOutlineType() if (_interactionComponent is not IInteractable interactable) return InteractionOutlineType.None; - if (_interactionComponent.IsInteractionHidden(_interactor)) + if (!_interactionComponent.IsInteractionAvailable()) + { + return InteractionOutlineType.None; + } + if (_interactor.IsInteractionHidden(_interactionComponent)) { return InteractionOutlineType.None; } diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs index 7d757bfdd..8a8c447a5 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs @@ -58,35 +58,26 @@ private static IEnumerable GetAllInteractionTypes() public virtual bool CanInteract() { - bool isInteractionVisible = !IsInteractionHidden(); + bool isInteractionAvailable = IsInteractionAvailable(); bool hasValidSubsystem = true; if (HasSubsystem(_interactionType)) { hasValidSubsystem = GetSubsystem(_interactionType).CanInteract(); } - return isInteractionVisible && hasValidSubsystem; + return isInteractionAvailable && hasValidSubsystem; } - public virtual bool IsInteractionHidden(IInteractor interactor = null) + public virtual bool IsInteractionAvailable() { + var currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState; var flowDisabled = (currentGameFlowState & _interactionAvailableFlows) == 0; if (flowDisabled) { - return true; - } - - // only check if interactor is valid. if not, pass the check. - if (interactor != null && HasSubsystem(_interactionType)) - { - bool canSolve = interactor.CanSolveInteractionType(_interactionType); - if (!canSolve) - { - return true; - } + return false; } - return false; + return true; } public virtual void OnInteracted(IInteractor interactor, ScriptableObject payload = null) diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantSubsystemSolver.cs b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantSubsystemSolver.cs index 1e6326cde..60be7f94c 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantSubsystemSolver.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantSubsystemSolver.cs @@ -30,6 +30,19 @@ public bool CanExecuteInteraction(IInteractor interactor = null, IInteractable i solver.CanExecuteInteractionSubsystem(interactor, interactable, payload); } + public bool CanSolveInteraction(IInteractor interactor, IInteractable interactable) + { + if (interactable is IInteractionSubsystemOwner subsystemOwner) + { + if (subsystemOwner.TryGetSubsystemEnumType(out T subsystemType)) + { + return _solvers.ContainsKey(subsystemType); + } + } + + return false; + } + // Solver를 가져오는 공통 로직 private bool TryGetSolver(IInteractable interactable, out IInteractionSubsystemSolver solver) {