diff --git a/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset b/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset index db1314a20..a793b242d 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:af9dba1f3a650104808ecdbc956ad4af8327efcf0fe782348b231eb103f7469b -size 66226 +oid sha256:277f8b3b25cfe078e4838cab1222b85e5dae0bc036cb39e5f84b6e3b3fce1cd0 +size 68048 diff --git a/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset b/Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset index 8e6a2bf26..7e7bb95e0 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:1e863335f3752df069447ebc0fee597d6f366d88edd12d70db68b45923a4f87c -size 20475 +oid sha256:6da8678bc90f664244b89aa26dc5c6b01c51567387ea3414b916fb27082f752b +size 16520 diff --git a/Assets/_DDD/_Addressables/Prefabs/CustomerNpc.prefab b/Assets/_DDD/_Addressables/Prefabs/CustomerNpc.prefab index 80cdc789c..d16acedec 100644 --- a/Assets/_DDD/_Addressables/Prefabs/CustomerNpc.prefab +++ b/Assets/_DDD/_Addressables/Prefabs/CustomerNpc.prefab @@ -1210,9 +1210,6 @@ PrefabInstance: - targetCorrespondingSourceObject: {fileID: 7462519206451630147, guid: ceeea618d8ee23642a0e56b3f963448c, type: 3} insertIndex: -1 addedObject: {fileID: 3825874317044733320} - - targetCorrespondingSourceObject: {fileID: 7462519206451630147, guid: ceeea618d8ee23642a0e56b3f963448c, type: 3} - insertIndex: -1 - addedObject: {fileID: 1122074513716966771} m_SourcePrefab: {fileID: 100100000, guid: ceeea618d8ee23642a0e56b3f963448c, type: 3} --- !u!1 &4266090516809920735 stripped GameObject: @@ -1255,23 +1252,3 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: af69e82818254bfa9cabb2dbf9430850, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!114 &1122074513716966771 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4266090516809920735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 201f9e6d7ca7404baa9945950292a392, type: 3} - m_Name: - m_EditorClassIdentifier: - _interactionType: 4 - _executionParameters: - _holdTime: 0 - _displayParameters: - _messageKey: - _interactionAvailableFlows: 2 - _aiInteractionPoints: [] - autoInitialize: 1 diff --git a/Assets/_DDD/_Addressables/Prefabs/RestaurantPlayer.prefab b/Assets/_DDD/_Addressables/Prefabs/RestaurantPlayer.prefab index f842662b8..bb8720305 100644 --- a/Assets/_DDD/_Addressables/Prefabs/RestaurantPlayer.prefab +++ b/Assets/_DDD/_Addressables/Prefabs/RestaurantPlayer.prefab @@ -426,7 +426,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 81e01dd8c1cc3404d805400eba1bb4ae, type: 3} m_Name: m_EditorClassIdentifier: - _availableInteractions: 5 + _availableInteractions: 7 _nearColliders: - {fileID: 0} - {fileID: 0} diff --git a/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs b/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs index 154eebd47..8136be741 100644 --- a/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs +++ b/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs @@ -9,7 +9,7 @@ namespace DDD /// public interface IAISharedBlackboard { - void SetCurrentInteractionTarget(GameObject targetGameObject); - GameObject GetCurrentInteractionTarget(); + void SetBlackboardGameObject(string key, GameObject inGameObject); + GameObject GetBlackboardGameObject(string key); } } diff --git a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs index c386e8e2a..72831c1fd 100644 --- a/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs +++ b/Assets/_DDD/_Scripts/Game/GameEvent/IInteractable.cs @@ -10,7 +10,6 @@ public enum InteractionType : uint None = 0u, RestaurantManagement = 1u << 0, RestaurantOrder = 1u << 1, - RestaurantMeal = 1u << 2, RestaurantCook = 1u << 3, All = 0xFFFFFFFFu } diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs index e00335603..68058dfd2 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs @@ -12,11 +12,7 @@ public class LookAtInteractionTarget : Action { [Header("Target Settings")] [Tooltip("InteractionPoints를 사용해 가장 적절한 지점을 바라봄")] - [SerializeField] private bool useInteractionPoints = true; - - [Header("Update Settings")] - [Tooltip("프레임마다 갱신하여 지속적으로 바라볼지 (Running 반환) 여부. 비활성화 시 1회만 시도하고 성공 처리")] - [SerializeField] private bool continuousUpdate = true; + [SerializeField] private bool _useInteractionPoints = true; // Visual 전용 컴포넌트(나중 구현)를 위한 최소 인터페이스 // 실제 구현은 Spine/애니메이션 제어 컴포넌트에서 이 인터페이스를 구현하세요. @@ -30,84 +26,63 @@ public interface ILookAtVisual void EndLookAt(); } - private ILookAtVisual visual; - private GameObject cachedTarget; - private bool isLooking; - private Vector3 currentLookPosition; + private ILookAtVisual _visual; + private GameObject _cachedTarget; + private bool _isLooking; + private Vector3 _currentLookPosition; public override void OnStart() { - visual = gameObject.GetComponentInParent(); - cachedTarget = null; - isLooking = false; + _visual = gameObject.GetComponentInParent(); + _isLooking = false; + + var blackboard = gameObject.GetComponent(); + _cachedTarget = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); } public override TaskStatus OnUpdate() - { - var target = GetTarget(); - if (target == null) + { + if (_cachedTarget == null) { - if (isLooking) + if (_isLooking) { // 타겟이 사라졌다면 정리 - visual?.EndLookAt(); - isLooking = false; + _visual?.EndLookAt(); + _isLooking = false; } return TaskStatus.Success; } - currentLookPosition = CalculateLookPosition(target); + _currentLookPosition = CalculateLookPosition(_cachedTarget); - if (!isLooking) + if (!_isLooking) { - visual?.TryBeginLookAt(currentLookPosition); - isLooking = true; + _visual?.TryBeginLookAt(_currentLookPosition); + _isLooking = true; } else { - visual?.UpdateLookAt(currentLookPosition); + _visual?.UpdateLookAt(_currentLookPosition); } - - // 연속 업데이트면 Running, 아니면 1회만 시도 후 Success 반환 - return continuousUpdate ? TaskStatus.Running : TaskStatus.Success; + + return TaskStatus.Success; } public override void OnEnd() { - if (isLooking) + if (_isLooking) { - visual?.EndLookAt(); - isLooking = false; + _visual?.EndLookAt(); + _isLooking = false; } - cachedTarget = null; - } - - private GameObject GetTarget() - { - // 캐시된 타겟이 유효하면 재사용 - if (IsValidTarget(cachedTarget)) - return cachedTarget; - - // 블랙보드에서 타겟 검색 - cachedTarget = gameObject.GetComponent() - ?.GetCurrentInteractionTarget(); - - if (IsValidTarget(cachedTarget)) - return cachedTarget; - - // Interactor의 포커스된 타겟 검색 - var interactor = gameObject.GetComponent(); - var focusedInteractable = interactor?.GetFocusedInteractable(); - cachedTarget = focusedInteractable?.GetInteractableGameObject(); - - return cachedTarget; + _cachedTarget = null; } private static bool IsValidTarget(GameObject target) => target != null && target; private Vector3 CalculateLookPosition(GameObject target) { - if (!useInteractionPoints) + if (!_useInteractionPoints) return target.transform.position; if (target.TryGetComponent(out var ric)) diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs index 58a3ce5a7..602f24ab2 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs @@ -1,5 +1,6 @@ using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.BehaviorDesigner.Runtime.Tasks.Actions; +using Unity.VisualScripting; using UnityEngine; namespace DDD.Restaurant @@ -19,39 +20,45 @@ public class MoveToInteractionTarget : Action [Tooltip("목적지 재계산 주기(초), 0 이하면 비활성화")] [SerializeField] private float repathInterval = 0.5f; + [Header("Debug Settings")] + [Tooltip("디버그 드로우 활성화")] + [SerializeField] private bool enableDebugDraw = true; + [Tooltip("디버그 선 색상")] + [SerializeField] private Color debugLineColor = Color.red; + [Tooltip("타겟 위치 기즈모 색상")] + [SerializeField] private Color targetGizmoColor = Color.yellow; + private IAiMovement _movement; private float _repathTimer; private Vector3 _currentDestination; private bool _isMoving; + private GameObject _target; public override void OnStart() { _movement = gameObject.GetComponent(); _repathTimer = 0f; _isMoving = false; - - Debug.Log($"MoveToInteractionTarget - GameObject: {gameObject.name}"); + + var blackboard = gameObject.GetComponent(); + _target = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); } public override TaskStatus OnUpdate() { if (_movement == null) return TaskStatus.Failure; - - var target = GetTarget(); - if (target == null) + if (_target == null) { - return TaskStatus.Running; // If has no target, stuck in this state + return TaskStatus.Failure; } - - Debug.Log(target.name); - + if (ShouldUpdateDestination()) { - _currentDestination = CalculateDestination(target); + _currentDestination = CalculateDestination(_target); StartOrUpdateMovement(); } - + return CheckMovementCompletion(); } @@ -59,14 +66,72 @@ public override void OnEnd() { StopMovement(); } - - private GameObject GetTarget() + + protected override void OnDrawGizmos() { - // Interactor의 포커스된 타겟 검색 - var interactor = gameObject.GetComponent(); - var focusedInteractable = interactor?.GetFocusedInteractable(); - if (focusedInteractable != null) return focusedInteractable.GetInteractableGameObject(); - return null; + if (!enableDebugDraw || _target == null) return; + + // 타겟 이름을 자신의 게임오브젝트 위에 표시 +#if UNITY_EDITOR + UnityEditor.Handles.Label(transform.position + Vector3.up * 2f, + $"Target: {_target.name}"); +#endif + + // 타겟 위치에 기즈모 그리기 + Gizmos.color = targetGizmoColor; + if (_isMoving && _currentDestination != Vector3.zero) + { + Gizmos.DrawWireSphere(_currentDestination, 0.5f); + } + else if (_target != null) + { + Gizmos.DrawWireSphere(_target.transform.position, 0.5f); + } + + // 현재 위치에서 타겟까지 직선 그리기 + Gizmos.color = debugLineColor; + Vector3 targetPos = _isMoving && _currentDestination != Vector3.zero + ? _currentDestination + : (_target != null ? _target.transform.position : Vector3.zero); + + if (targetPos != Vector3.zero) + { + Gizmos.DrawLine(transform.position, targetPos); + } + + // 현재 오브젝트 위치에 작은 기즈모 그리기 + Gizmos.color = Color.blue; + Gizmos.DrawWireCube(transform.position, Vector3.one * 0.3f); + } + + protected override void OnDrawGizmosSelected() + { + if (!enableDebugDraw || _target == null) return; + + // 선택되었을 때 추가 정보 표시 +#if UNITY_EDITOR + Vector3 targetPos = _isMoving && _currentDestination != Vector3.zero + ? _currentDestination + : _target.transform.position; + + float distance = Vector3.Distance(transform.position, targetPos); + UnityEditor.Handles.Label(targetPos + Vector3.up * 1f, + $"Distance: {distance:F2}m\nStopping: {stoppingDistance:F2}m"); + + // InteractionPoints가 있다면 모두 표시 + if (useInteractionPoints && _target.TryGetComponent(out var ric)) + { + var points = ric.GetInteractionPoints(); + if (points != null && points.Length > 0) + { + Gizmos.color = Color.cyan; + foreach (var point in points) + { + Gizmos.DrawWireSphere(point, 0.2f); + } + } + } +#endif } private bool ShouldUpdateDestination() diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs index ec725c587..15c13cd29 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs @@ -188,7 +188,7 @@ public void Execute(ref DynamicBuffer branchComponents, branchComponents[taskComponent.BranchIndex] = branchComponent; continue; } - else if (taskComponent.Status != TaskStatus.Running) + if (taskComponent.Status != TaskStatus.Running) { continue; } 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 f7b8a1acf..b954d1bf7 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs @@ -12,6 +12,8 @@ public class StartRestaurantOrder : Action [SerializeField] private bool _requireCanInteract = true; [Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")] [SerializeField] private bool _registerOnBlackboard = true; + [Tooltip("성공 시 블랙보드에 현재 인터랙션 대상을 등록합니다")] + [SerializeField] private bool _UnregisterOnBlackboard = false; private IInteractor _interactor; private bool _isGetInteractor; @@ -19,6 +21,7 @@ public class StartRestaurantOrder : Action public override void OnStart() { _isGetInteractor = gameObject.TryGetComponent(out _interactor); + if (!_isGetInteractor) Debug.LogError($"[{GetType().Name}] IInteractor를 찾을 수 없습니다: {gameObject.name}"); } @@ -43,9 +46,14 @@ public override TaskStatus OnUpdate() if (_registerOnBlackboard) { - // 하위 호환: 고객 전용 블랙보드 지원 - var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetCurrentInteractionTarget(outInteractable.gameObject); + var customerBlackboard = gameObject.GetComponent(); + customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), outInteractable.gameObject); + } + + if (_UnregisterOnBlackboard) + { + var customerBlackboard = gameObject.GetComponent(); + customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null); } return TaskStatus.Success; 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 b8da8cbf0..30feb0826 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs @@ -8,78 +8,42 @@ namespace DDD.Restaurant //차후 제네릭으로 변경 가능성 있음 public class WaitForPlayerInteraction : Action { - [Tooltip("기다릴 상호작용 타입")] - [SerializeField] private RestaurantMealType _targetOrderType = RestaurantMealType.WaitForOrder; - - private IInteractionSubsystemObject _interactionSubsystem; + [SerializeField] private RestaurantOrderType _targetOrderType; + private IInteractionSubsystemObject _interactionSubsystem; private bool _isGetInteractionSubsystem; public override void OnStart() { - // 의자가 복합 상태를 가지게 될 경우 - // GameObject interactionTarget = null; - // var shared = gameObject.GetComponentInChildren(); - // if (shared != null) - // { - // interactionTarget = shared.GetCurrentInteractionTarget(); - // } - // else - // { - // // 하위 호환: 고객 전용 블랙보드 지원 - // var customerBb = gameObject.GetComponentInParent(); - // interactionTarget = customerBb?.GetCurrentInteractionTarget(); - // } - // - // if (interactionTarget == null) - // { - // Debug.LogError($"[{GetType().Name}] interactionTarget을 찾을 수 없습니다: {gameObject.name}"); - // return; - // } - // - // if (!interactionTarget.TryGetComponent(out var interactionComponent)) - // Debug.LogError($"[{interactionTarget.name}] {nameof(interactionComponent)}를 찾을 수 없습니다: {gameObject.name}"); - // if (interactionComponent is IInteractionSubsystemOwner subsystemOwner) - // { - // if (!subsystemOwner.TryGetSubsystemObject(out var subsystem)) - // { - // Debug.LogError($"[{GetType().Name}] {nameof(_targetOrderType)}의 Subsystem을 찾을 수 없습니다: {gameObject.name}"); - // _isGetInteractionSubsystem = false; - // return; - // } - // - // _isGetInteractionSubsystem = true; - // subsystem.SetInteractionSubsystemType(_targetOrderType); - // - // if (!gameObject.TryGetComponent(out var interactor)) - // { - // Debug.LogError($"[{GetType().Name}] IInteractor를 찾을 수 없습니다: {gameObject.name}"); - // return; - // } - // - // interactor.CanInteractTo(interactionComponent); - // - // _interactionSubsystem = subsystem; - // } + GameObject interactionTarget = null; + if (!gameObject.TryGetComponent(out var sharedBlackboard)) return; + interactionTarget = + sharedBlackboard.GetBlackboardGameObject( + nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); - if (!gameObject.TryGetComponent(out var interactionComponent)) + if (interactionTarget == null) { - Debug.LogError($"[{GetType().Name}]에서 interactionComponent를 찾을 수 없습니다: {gameObject.name}"); + Debug.LogError($"[{GetType().Name}] interactionTarget을 찾을 수 없습니다: {gameObject.name}"); return; } + if (!interactionTarget.TryGetComponent(out var interactionComponent)) + Debug.LogError( + $"[{interactionTarget.name}] {nameof(interactionComponent)}를 찾을 수 없습니다: {gameObject.name}"); + if (interactionComponent is not IInteractionSubsystemOwner subsystemOwner) { - Debug.LogError($"[{GetType().Name}]에서 {nameof(IInteractionSubsystemOwner)}를 찾을 수 없습니다: {gameObject.name}"); + Debug.LogError( + $"[{GetType().Name}]에서 {nameof(IInteractionSubsystemOwner)}를 찾을 수 없습니다: {gameObject.name}"); return; } if (!subsystemOwner.TryGetSubsystemObject(out _interactionSubsystem)) { - Debug.LogError($"[{GetType().Name}]에서 {nameof(IInteractionSubsystemObject)}를 찾을 수 없습니다: {gameObject.name}"); + Debug.LogError( + $"[{GetType().Name}]에서 {nameof(IInteractionSubsystemObject)}를 찾을 수 없습니다: {gameObject.name}"); return; } - - _interactionSubsystem.SetInteractionSubsystemType(_targetOrderType); + _isGetInteractionSubsystem = true; } @@ -91,7 +55,7 @@ public override TaskStatus OnUpdate() if (result == TaskStatus.Success) Debug.Log($"[{GetType().Name}] Success"); return result; } - + private TaskStatus CheckToSubsystemStatus() { return _interactionSubsystem.GetInteractionSubsystemType() == _targetOrderType diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerAiComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerAiComponent.cs index aa9cfeb93..64c65fa36 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerAiComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerAiComponent.cs @@ -47,8 +47,8 @@ private async Task InitializeAiInternal(CustomerDataEntry inCustomerDataEntry) } _behaviorTree.Subgraph = subtree; - _blackboardComponent.InitializeWithBehaviorTree(subtree); - _blackboardComponent.SetCustomerData(inCustomerDataEntry); + _blackboardComponent.InitializeWithBehaviorTree(_behaviorTree); + _blackboardComponent.SetCustomerData(inCustomerDataEntry.Id); // TODO : 1. Subtree - Action, Condition // TODO : 2. Blackboard _behaviorTree.StartBehavior(); diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs index 408f35def..41aee0f18 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs @@ -5,35 +5,34 @@ namespace DDD { public class CustomerBlackboardComponent : MonoBehaviour, ICustomerBlackboard, IAISharedBlackboard { - private Subtree _subtree; - private GameObject _currentInteractionTarget; - - public void InitializeWithBehaviorTree(Subtree subtree) + // private Subtree _behaviorTree; + private BehaviorTree _behaviorTree; + + public void InitializeWithBehaviorTree(BehaviorTree inBehaviorTree) { - _subtree = subtree; - if (_subtree != null) + _behaviorTree = inBehaviorTree; + if (_behaviorTree) { - _subtree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.SelfGameObject), gameObject); + _behaviorTree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.SelfGameObject), gameObject); } } - public void SetCustomerData(CustomerDataEntry inCustomerDataEntry) + public void SetCustomerData(string inCustomerDataId) { - if (_subtree == null) return; - _subtree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CustomerData), inCustomerDataEntry); + if (!_behaviorTree) return; + _behaviorTree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CustomerDataId), inCustomerDataId); + } + + public void SetBlackboardGameObject(string key, GameObject inGameObject) + { + if (_behaviorTree == null) return; + _behaviorTree.SetVariableValue(key, inGameObject); } - public void SetCurrentInteractionTarget(GameObject targetGameObject) + public GameObject GetBlackboardGameObject(string key) { - _currentInteractionTarget = targetGameObject; - if (_subtree == null) return; - _subtree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), targetGameObject); - } - - public GameObject GetCurrentInteractionTarget() - { - // 캐시 우선 반환. 필요 시 Subtree에서 직접 조회하도록 확장 가능. - return _currentInteractionTarget; + if (_behaviorTree == null) return null; + return _behaviorTree.GetVariable(key)?.Value; } } } \ 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 d6b1530a5..5ec7c67ac 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine; @@ -99,5 +100,27 @@ public bool CanInteractTo(IInteractable interactable, ScriptableObject payloadSo if (TryGetSolverFor(interactable, out var solver) == false) return false; return solver.CanExecuteInteraction(this, interactable, payloadSo); } + + public virtual void InitializeSolvers() + { + var typesToSolver = RestaurantInteractionEventSolvers.TypeToSolver; + InitializeInteractionSolvers(typesToSolver); + } + + protected void InitializeInteractionSolvers(Dictionary typesToSolver) + { + foreach (var typeToSolver in typesToSolver) + { + var flag = typeToSolver.Key; + if (flag == InteractionType.None) continue; + + if ((AvailableInteractions & flag) == 0) continue; + + if (!TryGetComponent(typeToSolver.Value, out _)) + { + gameObject.AddComponent(typeToSolver.Value); + } + } + } } } diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs index 42105fd49..f3a32003e 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/RestaurantCharacter.cs @@ -13,19 +13,8 @@ public class RestaurantCharacter : MonoBehaviour, IGameCharacter, IInteractor protected virtual void Awake() { _interactionComponent = GetComponent(); + _interactionComponent.InitializeSolvers(); _spineController = GetComponent(); - foreach (var typeToSolver in RestaurantInteractionEventSolvers.TypeToSolver) - { - var flag = typeToSolver.Key; - if (flag == InteractionType.None) continue; - - if ((_interactionComponent.AvailableInteractions & flag) == 0) continue; - - if (!TryGetComponent(typeToSolver.Value, out _)) - { - gameObject.AddComponent(typeToSolver.Value); - } - } } protected virtual void Start() diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs index bec4db845..8754ec832 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs @@ -5,14 +5,12 @@ namespace DDD public enum RestaurantCustomerBlackboardKey { SelfGameObject, - CustomerData, + CustomerDataId, CurrentInteractionTarget, } public interface ICustomerBlackboard { - void SetCustomerData(CustomerDataEntry inCustomerDataEntry); - void SetCurrentInteractionTarget(GameObject targetGameObject); - GameObject GetCurrentInteractionTarget(); + void SetCustomerData(string inCustomerDataId); } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs index 4162945a1..21832e1ea 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Player/PlayerInteraction.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.InputSystem; @@ -35,6 +37,18 @@ private Task Initialize() return Task.CompletedTask; } + public override void InitializeSolvers() + { + var typesToSolver = RestaurantInteractionEventSolvers.TypeToSolver; + var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver; + foreach(var pair in playerSolver) + { + typesToSolver.Remove(pair.Key); + } + InitializeInteractionSolvers(typesToSolver); + InitializeInteractionSolvers(playerSolver); + } + protected override void OnDestroy() { base.OnDestroy(); diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Meal.cs b/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Meal.cs index 25433d327..48b1b410d 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Meal.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/Interactions/InteractionSubsystem_Meal.cs @@ -1,4 +1,5 @@ using System; +using Unity.VisualScripting; using UnityEngine; namespace DDD @@ -23,11 +24,13 @@ public RestaurantMealType GetInteractionSubsystemType() public void SetInteractionSubsystemType(RestaurantMealType inValue) { + Debug.Log($"[{gameObject.GetHashCode()}, {GetType().Name}] SetInteractionSubsystemType {inValue.ToString()}"); _currentRestaurantMealType = inValue; } public void InitializeSubsystem() { + Debug.Log($"[{gameObject.GetHashCode()}, {GetType().Name}] InitializeSubsystem"); _currentRestaurantMealType = RestaurantMealType.None; } @@ -38,6 +41,7 @@ public bool CanInteract() public bool OnInteracted(IInteractor interactor, ScriptableObject payloadSo = null) { + Debug.Log($"[{gameObject.GetHashCode()}, {GetType().Name}] OnInteracted"); var prev = _currentRestaurantMealType; _currentRestaurantMealType = GetNextState(prev); return true; diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs index 34bb0a1c3..422daa866 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionComponent.cs @@ -13,7 +13,6 @@ public static class RestaurantInteractionSubsystems { {InteractionType.RestaurantOrder, typeof(InteractionSubsystem_Order)}, {InteractionType.RestaurantManagement, typeof(InteractionSubsystem_Management)}, - {InteractionType.RestaurantMeal, typeof(InteractionSubsystem_Meal)} }; } diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs index 9fe0c5cef..f006c3e85 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs @@ -10,9 +10,12 @@ public static class RestaurantInteractionEventSolvers { {InteractionType.RestaurantManagement, typeof(RestaurantManagementSolver)}, {InteractionType.RestaurantOrder, typeof(RestaurantOrderSolver)}, - {InteractionType.RestaurantMeal, typeof(RestaurantMealSolver)}, {InteractionType.RestaurantCook, typeof(RestaurantCookSolver)} }; + public static Dictionary TypeToPlayerSolver = new() + { + {InteractionType.RestaurantOrder, typeof(RestaurantOrderPlayerSolver)}, + }; } public class RestaurantInteractionEvent : IEvent diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver.cs b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver.cs index a0f2bab02..b752ebdda 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/Solvers/RestaurantOrders/RestaurantOrderSolver.cs @@ -10,9 +10,19 @@ public class RestaurantOrderSolver : RestaurantSubsystemSolver GetSubsystemSolverTypeMappings() + { + return _typeToOrderSolver; + } + } + public class RestaurantOrderPlayerSolver : RestaurantSubsystemSolver + { + private Dictionary _typeToOrderSolver = new() + { { RestaurantOrderType.Order, typeof(RestaurantOrderSolver_Order) }, { RestaurantOrderType.Serve, typeof(RestaurantOrderSolver_Serve) }, - { RestaurantOrderType.Busy, typeof(RestaurantOrderSolver_Busy) }, { RestaurantOrderType.Dirty, typeof(RestaurantOrderSolver_Dirty) } }; protected override Dictionary GetSubsystemSolverTypeMappings() diff --git a/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs new file mode 100644 index 000000000..817d2635c --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs @@ -0,0 +1,9 @@ +using UnityEngine; + +namespace DDD.Restaurant +{ + public class PropUiDisplayComponent : MonoBehaviour + { + + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs.meta new file mode 100644 index 000000000..2b5b6d8ec --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Ui/PropUiDisplayComponent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 37e749c7ec5440d587f83c715f29ca8f +timeCreated: 1756353198 \ No newline at end of file