레스토랑 상호작용 시스템 개선:
- 고객 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")]
|
||||
[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<IAISharedBlackboard>();
|
||||
var target = blackboard?.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
|
||||
IInteractable currentInteractable = target?.GetComponent<IInteractable>();
|
||||
|
||||
if (_targetOrderType == RestaurantOrderType.Wait)
|
||||
{
|
||||
// 레스토랑 주문 인터랙션 후보를 가져옴
|
||||
TaskStatus targetSearchSuccess = RestaurantOrderAvailable.FindAvailableOrderInteractable(_targetOrderType, out currentInteractable);
|
||||
if (targetSearchSuccess == 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로 사용
|
||||
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<IAISharedBlackboard>();
|
||||
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), outInteractable.gameObject);
|
||||
}
|
||||
|
||||
if (_UnregisterOnBlackboard)
|
||||
if (_targetOrderType == RestaurantOrderType.Busy)
|
||||
{
|
||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null);
|
||||
|
@ -9,8 +9,9 @@ namespace DDD.Restaurant
|
||||
public class WaitForPlayerInteraction : Action
|
||||
{
|
||||
[SerializeField] private RestaurantOrderType _targetOrderType;
|
||||
[SerializeField] private RestaurantOrderType _nextOrderType;
|
||||
private IInteractionSubsystemObject<RestaurantOrderType> _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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<T>(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<T>(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<T>(out var subsystem)) continue;
|
||||
|
||||
if (EqualityComparer<T>.Default.Equals(subsystem.GetInteractionSubsystemType(), targetOrderType))
|
||||
if (interactable is not IInteractionSubsystemOwner subsystemOwner) continue;
|
||||
if (!subsystemOwner.TryGetSubsystemObject<RestaurantOrderType>(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;
|
||||
}
|
||||
}
|
||||
|
@ -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<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(playerSolver);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
|
@ -6,5 +6,6 @@ namespace DDD
|
||||
public interface IInteractionSubsystemOwner
|
||||
{
|
||||
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
|
||||
{
|
||||
[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()
|
||||
|
@ -185,5 +185,20 @@ public bool TryGetSubsystemObject<T>(out IInteractionSubsystemObject<T> subsyste
|
||||
subsystemObject = null;
|
||||
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)
|
||||
{
|
||||
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<RestaurantOrderType>(out var subsystem))
|
||||
|
Loading…
Reference in New Issue
Block a user