레스토랑 상호작용 시스템 개선:
- 고객 AI 주문 시작/대기/가용성 로직 정리 및 안정성 향상 - IInteractionSubsystemOwner 및 Order Subsystem 연동 보강 - PlayerInteraction/InteractionComponent 이벤트 흐름 수정 - Wait 주문 솔버 로직 보정 - 고객 기본/주문 서브트리 에셋 업데이트
This commit is contained in:
parent
86c0f67c7c
commit
a7d741b81e
BIN
Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Addressables/AI/Customer/Subtree/OrderSubtree.asset
(Stored with Git LFS)
Binary file not shown.
@ -8,12 +8,6 @@ public class StartRestaurantOrder : Action
|
|||||||
{
|
{
|
||||||
[Tooltip("상호작용할 RestaurantOrderType")]
|
[Tooltip("상호작용할 RestaurantOrderType")]
|
||||||
[SerializeField] private RestaurantOrderType _targetOrderType = RestaurantOrderType.Wait;
|
[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 IInteractor _interactor;
|
||||||
private bool _isGetInteractor;
|
private bool _isGetInteractor;
|
||||||
@ -27,30 +21,56 @@ public override void OnStart()
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override TaskStatus OnUpdate()
|
public override TaskStatus OnUpdate()
|
||||||
|
{
|
||||||
|
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||||
|
var target = blackboard?.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
|
||||||
|
IInteractable currentInteractable = target?.GetComponent<IInteractable>();
|
||||||
|
|
||||||
|
if (_targetOrderType == RestaurantOrderType.Wait)
|
||||||
{
|
{
|
||||||
// 레스토랑 주문 인터랙션 후보를 가져옴
|
// 레스토랑 주문 인터랙션 후보를 가져옴
|
||||||
TaskStatus targetSearchSuccess = RestaurantOrderAvailable.FindAvailableOrderInteractable(_requireCanInteract, _targetOrderType, out var
|
TaskStatus targetSearchSuccess = RestaurantOrderAvailable.FindAvailableOrderInteractable(_targetOrderType, out currentInteractable);
|
||||||
outInteractable);
|
|
||||||
if (targetSearchSuccess == TaskStatus.Failure)
|
if (targetSearchSuccess == TaskStatus.Failure)
|
||||||
{
|
{
|
||||||
return TaskStatus.Failure;
|
return TaskStatus.Failure;
|
||||||
}
|
}
|
||||||
|
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||||
|
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), currentInteractable.GetInteractableGameObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check order type of the current interactable
|
||||||
|
if (currentInteractable is IInteractionSubsystemOwner subsystemOwner)
|
||||||
|
{
|
||||||
|
if (subsystemOwner.TryGetSubsystemEnumType<RestaurantOrderType>(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로 사용
|
// 상호작용 수행: 액션이 붙은 에이전트를 Interactor로 사용
|
||||||
if (!_isGetInteractor || !_interactor.CanInteractTo(outInteractable))
|
if (!_isGetInteractor)
|
||||||
{
|
{
|
||||||
return TaskStatus.Failure;
|
return TaskStatus.Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
RestaurantEvents.InteractionEvent.RequestInteraction(_interactor.GetInteractorGameObject(), outInteractable.gameObject, outInteractable.GetInteractionType());
|
RestaurantEvents.InteractionEvent.RequestInteraction(_interactor.GetInteractorGameObject(), currentInteractable.GetInteractableGameObject(), currentInteractable.GetInteractionType());
|
||||||
|
|
||||||
if (_registerOnBlackboard)
|
if (_targetOrderType == RestaurantOrderType.Busy)
|
||||||
{
|
|
||||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
|
||||||
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), outInteractable.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_UnregisterOnBlackboard)
|
|
||||||
{
|
{
|
||||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||||
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null);
|
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null);
|
||||||
|
@ -9,8 +9,9 @@ namespace DDD.Restaurant
|
|||||||
public class WaitForPlayerInteraction : Action
|
public class WaitForPlayerInteraction : Action
|
||||||
{
|
{
|
||||||
[SerializeField] private RestaurantOrderType _targetOrderType;
|
[SerializeField] private RestaurantOrderType _targetOrderType;
|
||||||
|
[SerializeField] private RestaurantOrderType _nextOrderType;
|
||||||
private IInteractionSubsystemObject<RestaurantOrderType> _interactionSubsystem;
|
private IInteractionSubsystemObject<RestaurantOrderType> _interactionSubsystem;
|
||||||
private bool _isGetInteractionSubsystem;
|
private bool _isSubsystemExist;
|
||||||
|
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
@ -44,12 +45,18 @@ public override void OnStart()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isGetInteractionSubsystem = true;
|
if (_interactionSubsystem?.GetInteractionSubsystemType() != _targetOrderType)
|
||||||
|
{
|
||||||
|
Debug.Log($"[{GetType().Name}] 다른 Order Type: {_interactionSubsystem?.GetInteractionSubsystemType()} != {_targetOrderType}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isSubsystemExist = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TaskStatus OnUpdate()
|
public override TaskStatus OnUpdate()
|
||||||
{
|
{
|
||||||
if (!_isGetInteractionSubsystem) return TaskStatus.Failure;
|
if (!_isSubsystemExist) return TaskStatus.Failure;
|
||||||
|
|
||||||
TaskStatus result = CheckToSubsystemStatus();
|
TaskStatus result = CheckToSubsystemStatus();
|
||||||
if (result == TaskStatus.Success) Debug.Log($"[{GetType().Name}] Success");
|
if (result == TaskStatus.Success) Debug.Log($"[{GetType().Name}] Success");
|
||||||
@ -58,9 +65,10 @@ public override TaskStatus OnUpdate()
|
|||||||
|
|
||||||
private TaskStatus CheckToSubsystemStatus()
|
private TaskStatus CheckToSubsystemStatus()
|
||||||
{
|
{
|
||||||
return _interactionSubsystem.GetInteractionSubsystemType() == _targetOrderType
|
var currentSubsystemType = _interactionSubsystem.GetInteractionSubsystemType();
|
||||||
? TaskStatus.Running
|
if (currentSubsystemType == _nextOrderType)
|
||||||
: TaskStatus.Success;
|
return TaskStatus.Success;
|
||||||
|
return TaskStatus.Running;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,13 +28,13 @@ public bool CheckCanInteract
|
|||||||
|
|
||||||
public override TaskStatus OnUpdate()
|
public override TaskStatus OnUpdate()
|
||||||
{
|
{
|
||||||
TaskStatus targetSearchSuccess = FindAvailableOrderInteractable(_checkCanInteract, _targetOrderType, out var
|
TaskStatus targetSearchSuccess = FindAvailableOrderInteractable(_targetOrderType, out var
|
||||||
outInteractable);
|
outInteractable);
|
||||||
return targetSearchSuccess;
|
return targetSearchSuccess;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskStatus FindAvailableOrderInteractable<T>(bool checkCanInteract, T targetOrderType, out RestaurantInteractionComponent outInteractable) where T : Enum
|
public static TaskStatus FindAvailableOrderInteractable(RestaurantOrderType targetOrderType, out IInteractable outInteractable)
|
||||||
{
|
{
|
||||||
outInteractable = null;
|
outInteractable = null;
|
||||||
|
|
||||||
@ -45,25 +45,17 @@ public static TaskStatus FindAvailableOrderInteractable<T>(bool checkCanInteract
|
|||||||
}
|
}
|
||||||
|
|
||||||
var interactables = environmentState.GetInteractablesByType(InteractionType.RestaurantOrder);
|
var interactables = environmentState.GetInteractablesByType(InteractionType.RestaurantOrder);
|
||||||
|
|
||||||
foreach (var interactable in interactables)
|
foreach (var interactable in interactables)
|
||||||
{
|
{
|
||||||
// 서브시스템에서 RestaurantOrderType을 가져와 비교
|
// 서브시스템에서 RestaurantOrderType을 가져와 비교
|
||||||
outInteractable = interactable as RestaurantInteractionComponent;
|
if (interactable is not IInteractionSubsystemOwner subsystemOwner) continue;
|
||||||
if (outInteractable == null) continue;
|
if (!subsystemOwner.TryGetSubsystemObject<RestaurantOrderType>(out var subsystem)) continue;
|
||||||
if (!outInteractable.TryGetSubsystemObject<T>(out var subsystem)) continue;
|
if (subsystem.GetInteractionSubsystemType() == targetOrderType)
|
||||||
|
|
||||||
if (EqualityComparer<T>.Default.Equals(subsystem.GetInteractionSubsystemType(), targetOrderType))
|
|
||||||
{
|
{
|
||||||
// CheckCanInteract이 false면 타입만 맞으면 성공
|
|
||||||
if (!checkCanInteract)
|
|
||||||
{
|
|
||||||
return TaskStatus.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckCanInteract이 true면 실제 인터랙션 가능 여부까지 확인
|
// CheckCanInteract이 true면 실제 인터랙션 가능 여부까지 확인
|
||||||
if (interactable.CanInteract())
|
if (interactable.CanInteract())
|
||||||
{
|
{
|
||||||
|
outInteractable = interactable;
|
||||||
return TaskStatus.Success;
|
return TaskStatus.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,14 +39,17 @@ private Task Initialize()
|
|||||||
|
|
||||||
public override void InitializeSolvers()
|
public override void InitializeSolvers()
|
||||||
{
|
{
|
||||||
var typesToSolver = RestaurantInteractionEventSolvers.TypeToSolver;
|
|
||||||
var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver;
|
var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver;
|
||||||
foreach(var pair in playerSolver)
|
Dictionary<InteractionType, Type> 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(typesToSolver);
|
||||||
InitializeInteractionSolvers(playerSolver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
protected override void OnDestroy()
|
||||||
|
@ -6,5 +6,6 @@ namespace DDD
|
|||||||
public interface IInteractionSubsystemOwner
|
public interface IInteractionSubsystemOwner
|
||||||
{
|
{
|
||||||
public bool TryGetSubsystemObject<T>(out IInteractionSubsystemObject<T> subsystemObject) where T : Enum;
|
public bool TryGetSubsystemObject<T>(out IInteractionSubsystemObject<T> subsystemObject) where T : Enum;
|
||||||
|
public bool TryGetSubsystemEnumType<T>(out T subsystemType) where T : Enum;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,13 +21,7 @@ public interface IRestaurantOrderObject
|
|||||||
|
|
||||||
public class InteractionSubsystem_Order : MonoBehaviour, IInteractionSubsystemObject<RestaurantOrderType>, IRestaurantOrderObject
|
public class InteractionSubsystem_Order : MonoBehaviour, IInteractionSubsystemObject<RestaurantOrderType>, IRestaurantOrderObject
|
||||||
{
|
{
|
||||||
[FormerlySerializedAs("orderType")] [SerializeField] protected RestaurantOrderType _orderType = RestaurantOrderType.Wait;
|
[SerializeField] private RestaurantOrderType _currentRestaurantOrderType = RestaurantOrderType.Wait;
|
||||||
private RestaurantOrderType _currentRestaurantOrderType;
|
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
_currentRestaurantOrderType = _orderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanInteract()
|
public bool CanInteract()
|
||||||
{
|
{
|
||||||
@ -58,7 +52,6 @@ public ScriptableObject GetPayload()
|
|||||||
|
|
||||||
public void InitializeSubsystem()
|
public void InitializeSubsystem()
|
||||||
{
|
{
|
||||||
_currentRestaurantOrderType = _orderType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestaurantOrderType GetInteractionSubsystemType()
|
public RestaurantOrderType GetInteractionSubsystemType()
|
||||||
|
@ -185,5 +185,20 @@ public bool TryGetSubsystemObject<T>(out IInteractionSubsystemObject<T> subsyste
|
|||||||
subsystemObject = null;
|
subsystemObject = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetSubsystemEnumType<T>(out T enumValue) where T : Enum
|
||||||
|
{
|
||||||
|
foreach (var interactionSubsystemObject in _subsystems.Values)
|
||||||
|
{
|
||||||
|
if (interactionSubsystemObject is IInteractionSubsystemObject<T> subsystem)
|
||||||
|
{
|
||||||
|
enumValue = subsystem.GetInteractionSubsystemType();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enumValue = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,8 +7,8 @@ public class RestaurantOrderSolver_Wait : MonoBehaviour, IInteractionSubsystemSo
|
|||||||
{
|
{
|
||||||
public bool ExecuteInteractionSubsystem(IInteractor interactor, IInteractable interactable, ScriptableObject payload = null)
|
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)
|
if (interactable is not IInteractionSubsystemOwner subsystemOwner)
|
||||||
return false;
|
return false;
|
||||||
if (!subsystemOwner.TryGetSubsystemObject<RestaurantOrderType>(out var subsystem))
|
if (!subsystemOwner.TryGetSubsystemObject<RestaurantOrderType>(out var subsystem))
|
||||||
|
Loading…
Reference in New Issue
Block a user