추가 사항: RestaurantEnvironmentPointQueryEvent 삭제, CheckCumulateOrderCount 조건 액션 추가, CustomerBlackboardSo 클래스 추가, ExitSubtree 에셋 추가
This commit is contained in:
parent
b7f9fbb5ab
commit
3f237cd1c1
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/ExitSubtree.asset
(Stored with Git LFS)
Normal file
BIN
Assets/_DDD/_Addressables/AI/Customer/Subtree/ExitSubtree.asset
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71fd4c1fc79e83a4b9af326332323c28
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
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.
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD
|
||||
@ -7,11 +8,11 @@ namespace DDD
|
||||
/// - 다양한 캐릭터 AI에서 공통으로 참조하는 현재 인터랙션 타겟만 정의합니다.
|
||||
/// - 필요 시 키-값 확장을 고려하되, 현재는 최소 요구만 충족합니다.
|
||||
/// </summary>
|
||||
public interface IAISharedBlackboard
|
||||
public interface IAISharedBlackboard<T> where T : Enum
|
||||
{
|
||||
|
||||
void SetBlackboardValue<T>(string key, T inValue);
|
||||
void SetBlackboardValue<T1>(T key, T1 inValue);
|
||||
|
||||
T GetBlackboardValue<T>(string key);
|
||||
T1 GetBlackboardValue<T1>(T key);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using Action = Opsive.BehaviorDesigner.Runtime.Tasks.Actions.Action;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
@ -11,7 +12,7 @@ public enum EmotionType
|
||||
Satisfied,
|
||||
}
|
||||
|
||||
public class ExpressEmotion : Action
|
||||
public class ExpressEmotion<T> : Action where T : Enum
|
||||
{
|
||||
public interface IEmotionVisual
|
||||
{
|
||||
@ -21,13 +22,14 @@ public interface IEmotionVisual
|
||||
}
|
||||
|
||||
//이를 파생해서 기본값을 주거나, 바로 사용하면 될 듯
|
||||
[SerializeField] protected string _emotionBlackboardKey;
|
||||
[SerializeField] protected T _emotionBlackboardKey;
|
||||
|
||||
private IEmotionVisual _emotionVisual;
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
var currentEmotion = (EmotionType)m_BehaviorTree.GetVariable<int>(_emotionBlackboardKey).Value;
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<T>>();
|
||||
var currentEmotion = blackboard.GetBlackboardValue<EmotionType>(_emotionBlackboardKey);
|
||||
|
||||
_emotionVisual = gameObject.GetComponentInChildren<IEmotionVisual>();
|
||||
if (_emotionVisual == null)
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using UnityEngine;
|
||||
using Action = Opsive.BehaviorDesigner.Runtime.Tasks.Actions.Action;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
@ -8,7 +9,7 @@ namespace DDD.Restaurant
|
||||
/// 인터랙션 타겟을 바라보도록 시각(Spine/애니메이션) 컴포넌트에 위임하는 액션의 껍데기/골격.
|
||||
/// 실제 회전/스파인 제어 로직은 별도의 Visual 컴포넌트(예: Spine/Animation Controller)에서 구현하십시오.
|
||||
/// </summary>
|
||||
public class LookAtInteractionTarget : Action
|
||||
public abstract class LookAtInteractionTarget<T> : Action where T : Enum
|
||||
{
|
||||
[Header("Target Settings")]
|
||||
[Tooltip("InteractionPoints를 사용해 가장 적절한 지점을 바라봄")]
|
||||
@ -27,19 +28,21 @@ public interface ILookAtVisual
|
||||
}
|
||||
|
||||
private ILookAtVisual _visual;
|
||||
private GameObject _cachedTarget;
|
||||
protected GameObject _cachedTarget;
|
||||
private bool _isLooking;
|
||||
private Vector3 _currentLookPosition;
|
||||
|
||||
public override void OnStart()
|
||||
public sealed override void OnStart()
|
||||
{
|
||||
_visual = gameObject.GetComponentInParent<ILookAtVisual>();
|
||||
_isLooking = false;
|
||||
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<T>>();
|
||||
InitializeBlackboard(blackboard);
|
||||
|
||||
_cachedTarget = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
|
||||
}
|
||||
|
||||
protected abstract void InitializeBlackboard(IAISharedBlackboard<T> blackboard);
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
|
@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using Action = Opsive.BehaviorDesigner.Runtime.Tasks.Actions.Action;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
/// <summary>
|
||||
/// IAiMovement를 이용해 인터랙션 타겟으로 이동하는 액션
|
||||
/// </summary>
|
||||
public class MoveToTargetPoint : Action
|
||||
public abstract class MoveToTargetPoint<T> : Action where T : Enum
|
||||
{
|
||||
[Header("Target Settings")]
|
||||
[Tooltip("InteractionPoints를 사용해 가장 가까운 지점으로 이동")]
|
||||
@ -32,17 +33,19 @@ public class MoveToTargetPoint : Action
|
||||
private float _repathTimer;
|
||||
private Vector3 _currentDestination;
|
||||
private bool _isMoving;
|
||||
private GameObject _target;
|
||||
protected GameObject _target;
|
||||
|
||||
public override void OnStart()
|
||||
public sealed override void OnStart()
|
||||
{
|
||||
_movement = gameObject.GetComponent<IAiMovement>();
|
||||
_repathTimer = 0f;
|
||||
_isMoving = false;
|
||||
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
_target = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<T>>();
|
||||
InitializeBlackboard(blackboard);
|
||||
}
|
||||
|
||||
protected abstract void InitializeBlackboard(IAISharedBlackboard<T> blackboard);
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
|
@ -0,0 +1,7 @@
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class RestaurantExpressEmotion : ExpressEmotion<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12b0bf82aef64d9d82a77a82943d7878
|
||||
timeCreated: 1756692031
|
@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class RestaurantLookAtInteractionTarget : LookAtInteractionTarget<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
protected override void InitializeBlackboard(IAISharedBlackboard<RestaurantCustomerBlackboardKey> blackboard)
|
||||
{
|
||||
_cachedTarget = blackboard.GetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d73d4725548490da952ac2079f98497
|
||||
timeCreated: 1756692248
|
@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class RestaurantMoveToTargetPoint : MoveToTargetPoint<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
protected override void InitializeBlackboard(IAISharedBlackboard<RestaurantCustomerBlackboardKey> blackboard)
|
||||
{
|
||||
_target = blackboard.GetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e02da400458a473d9131601fc09192c0
|
||||
timeCreated: 1756692564
|
@ -0,0 +1,7 @@
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class RestaurantSearchAndRegisterMarker : SearchAndRegisterMarker<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e62500af8d764eac9b14024f155a168f
|
||||
timeCreated: 1756693121
|
@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using UnityEngine;
|
||||
using Action = Opsive.BehaviorDesigner.Runtime.Tasks.Actions.Action;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class SearchAndRegisterMarker : Action
|
||||
public class SearchAndRegisterMarker<T> : Action where T : Enum
|
||||
{
|
||||
[SerializeField] private PointType _pointType;
|
||||
[SerializeField] private RestaurantCustomerBlackboardKey _markerBlackboardKey;
|
||||
[SerializeField] private T _markerBlackboardKey;
|
||||
private bool _isRegistered;
|
||||
|
||||
public override void OnStart()
|
||||
@ -15,13 +16,12 @@ public override void OnStart()
|
||||
var environmentState = RestaurantState.Instance?.EnvironmentState;
|
||||
if (environmentState == null) return;
|
||||
var pointProviders = environmentState.GetPointProviderByType(_pointType);
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<T>>();
|
||||
if (blackboard == null) return;
|
||||
|
||||
foreach (var pointProvider in pointProviders)
|
||||
{
|
||||
if (!pointProvider.IsSupportsType(_pointType)) continue;
|
||||
blackboard.SetBlackboardValue(nameof(_markerBlackboardKey), pointProvider.GetGameObject());
|
||||
blackboard.SetBlackboardValue(_markerBlackboardKey, pointProvider.GetGameObject());
|
||||
_isRegistered = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Opsive.GraphDesigner.Runtime.Variables;
|
||||
using Sirenix.OdinInspector;
|
||||
using Sirenix.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class BlackboardSo<T> : ScriptableObject where T : Enum
|
||||
{
|
||||
[OdinSerialize, ShowInInspector]
|
||||
private Dictionary<T, SharedVariable> _variables = new();
|
||||
|
||||
public SharedVariable<T1> GetVariable<T1>(T key)
|
||||
@ -25,6 +28,7 @@ public void SetVariable<T1>(T key, T1 value)
|
||||
if (outVariable != null)
|
||||
{
|
||||
outVariable.Value = value;
|
||||
_variables[key] = outVariable;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -238,7 +238,7 @@ public void Execute(ref DynamicBuffer<BranchComponent> branchComponents,
|
||||
}
|
||||
|
||||
[NodeDescription("자식 태스크의 실행 시간을 제한합니다 (GameObject 워크플로우)")]
|
||||
public class SharedTimeLimiter : DecoratorNode
|
||||
public class SharedTimeLimiter<T> : DecoratorNode
|
||||
{
|
||||
[Tooltip("최대 실행 시간(초)")]
|
||||
[SerializeField] protected SharedVariable<float> _timeLimit = 30f;
|
||||
@ -248,7 +248,7 @@ public class SharedTimeLimiter : DecoratorNode
|
||||
|
||||
[Tooltip("하단 블랙보드 키에 현재 시간을 저장할 지")]
|
||||
[SerializeField] protected bool _isBlackboardWriteEnabled = false;
|
||||
[SerializeField] protected string _blackboardKey = "CurrentTime";
|
||||
[SerializeField] protected T _blackboardKey;
|
||||
|
||||
public SharedVariable<float> TimeLimit
|
||||
{
|
||||
|
@ -0,0 +1,20 @@
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class IncrementOrderCount : Action
|
||||
{
|
||||
public override void OnStart()
|
||||
{
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
if (blackboard == null)
|
||||
{
|
||||
Debug.LogWarning($"블랙보드가 존재하지 않음 해시코드: {gameObject.GetHashCode()}");
|
||||
return;
|
||||
}
|
||||
var cumulativeOrderCount = blackboard.GetBlackboardValue<int>(RestaurantCustomerBlackboardKey.CumulativeOrderCount);
|
||||
blackboard.SetBlackboardValue(RestaurantCustomerBlackboardKey.CumulativeOrderCount, ++cumulativeOrderCount);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3f7e66da71042a5b5a679261d1bbf0b
|
||||
timeCreated: 1756700443
|
@ -0,0 +1,15 @@
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class LeaveRestaurant : Action
|
||||
{
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
Object.Destroy(gameObject);
|
||||
return TaskStatus.Running;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e39046ffc9bb46d39d2a5c4a9899cd68
|
||||
timeCreated: 1756702274
|
@ -0,0 +1,33 @@
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class PublishRestaurantInterruptEvent : Action
|
||||
{
|
||||
[SerializeField] private RestaurantOrderType _targetInterruptType;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
if (blackboard == null) return TaskStatus.Failure;
|
||||
|
||||
var currentTarget = blackboard.GetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
|
||||
if (currentTarget == null) return TaskStatus.Failure;
|
||||
|
||||
var orderObject = currentTarget.GetComponent<IRestaurantOrderObject>();
|
||||
if (orderObject == null) return TaskStatus.Failure;
|
||||
|
||||
RestaurantOrderInterrupt evt = new()
|
||||
{
|
||||
Table = currentTarget,
|
||||
OrderObject = orderObject.GetOrderObjectState(),
|
||||
TransitionType = _targetInterruptType
|
||||
};
|
||||
|
||||
EventBus.Broadcast(evt);
|
||||
|
||||
return TaskStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aaaf550a60264509a1ebd35506000e2b
|
||||
timeCreated: 1756706679
|
@ -14,13 +14,13 @@ public enum EvaluationStep
|
||||
[NodeDescription("만족도 평가 테스크")]
|
||||
public class SatisfactionEvaluator : Action
|
||||
{
|
||||
[SerializeField] private string _satisfactionBlackboardKey;
|
||||
[SerializeField] private RestaurantCustomerBlackboardKey _satisfactionBlackboardKey;
|
||||
[SerializeField] private EvaluationStep _evaluationStep;
|
||||
public override void OnStart()
|
||||
{
|
||||
var currentSatisfaction = CalculateSatisfaction();
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
blackboard.SetBlackboardValue(_satisfactionBlackboardKey, (int)currentSatisfaction);
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
blackboard.SetBlackboardValue(_satisfactionBlackboardKey, currentSatisfaction);
|
||||
}
|
||||
|
||||
//TODO 만족도 계산?
|
||||
|
@ -22,8 +22,8 @@ public override void OnStart()
|
||||
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
var target = blackboard?.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
var target = blackboard?.GetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
|
||||
IInteractable currentInteractable = target?.GetComponent<IInteractable>();
|
||||
if (_targetOrderType == RestaurantOrderType.Wait)
|
||||
{
|
||||
@ -33,8 +33,8 @@ public override TaskStatus OnUpdate()
|
||||
{
|
||||
return TaskStatus.Failure;
|
||||
}
|
||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject), currentInteractable.GetInteractableGameObject());
|
||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
customerBlackboard?.SetBlackboardValue(RestaurantCustomerBlackboardKey.CurrentTargetGameObject, currentInteractable.GetInteractableGameObject());
|
||||
}
|
||||
|
||||
// Check order type of the current interactable
|
||||
@ -70,8 +70,8 @@ public override TaskStatus OnUpdate()
|
||||
|
||||
if (_targetOrderType == RestaurantOrderType.Busy)
|
||||
{
|
||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
|
||||
customerBlackboard?.SetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject), null);
|
||||
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
customerBlackboard?.SetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject, null);
|
||||
}
|
||||
|
||||
return TaskStatus.Success;
|
||||
|
@ -16,10 +16,10 @@ public class WaitForPlayerInteraction : Action
|
||||
public override void OnStart()
|
||||
{
|
||||
GameObject interactionTarget = null;
|
||||
if (!gameObject.TryGetComponent<IAISharedBlackboard>(out var sharedBlackboard)) return;
|
||||
if (!gameObject.TryGetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>(out var sharedBlackboard)) return;
|
||||
interactionTarget =
|
||||
sharedBlackboard.GetBlackboardValue<GameObject>(
|
||||
nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
|
||||
RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
|
||||
|
||||
if (interactionTarget == null)
|
||||
{
|
||||
|
@ -0,0 +1,54 @@
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||||
using Opsive.BehaviorDesigner.Runtime.Tasks.Conditionals;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class CheckCumulateOrderCount : Conditional
|
||||
{
|
||||
public enum ComparisonType
|
||||
{
|
||||
Less,
|
||||
LessOrEqual,
|
||||
Equal,
|
||||
NotEqual,
|
||||
Greater,
|
||||
GreaterOrEqual
|
||||
}
|
||||
|
||||
[SerializeField] private int _compareOrderCount;
|
||||
[SerializeField] private ComparisonType _comparisonType;
|
||||
public override TaskStatus OnUpdate()
|
||||
{
|
||||
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
|
||||
if (blackboard == null)
|
||||
{
|
||||
Debug.LogWarning($"블랙보드가 존재하지 않음 해시코드: {gameObject.GetHashCode()}");
|
||||
return TaskStatus.Failure;
|
||||
}
|
||||
var cumulativeOrderCount = blackboard.GetBlackboardValue<int>(RestaurantCustomerBlackboardKey.CumulativeOrderCount);
|
||||
return Evaluate(cumulativeOrderCount) ? TaskStatus.Success : TaskStatus.Failure;
|
||||
}
|
||||
|
||||
private bool Evaluate(int compareValue)
|
||||
{
|
||||
switch (_comparisonType)
|
||||
{
|
||||
case ComparisonType.Less:
|
||||
return compareValue < _compareOrderCount;
|
||||
case ComparisonType.LessOrEqual:
|
||||
return compareValue <= _compareOrderCount;
|
||||
case ComparisonType.Equal:
|
||||
return compareValue == _compareOrderCount;
|
||||
case ComparisonType.NotEqual:
|
||||
return compareValue != _compareOrderCount;
|
||||
case ComparisonType.Greater:
|
||||
return compareValue > _compareOrderCount;
|
||||
case ComparisonType.GreaterOrEqual:
|
||||
return compareValue >= _compareOrderCount;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b3c5ee2ca89419394819e57dbab0bcd
|
||||
timeCreated: 1756701161
|
@ -1,36 +1,68 @@
|
||||
using DDD.Restaurant;
|
||||
using Opsive.BehaviorDesigner.Runtime;
|
||||
using Opsive.GraphDesigner.Runtime.Variables;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD
|
||||
{
|
||||
public class CustomerBlackboardComponent : MonoBehaviour, ICustomerBlackboard, IAISharedBlackboard
|
||||
public class CustomerBlackboardComponent : MonoBehaviour, ICustomerBlackboard, IAISharedBlackboard<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
private BehaviorTree _behaviorTree;
|
||||
[SerializeField, InlineEditor]
|
||||
private CustomerBlackboardSo _blackboardSo;
|
||||
|
||||
public void InitializeWithBehaviorTree(BehaviorTree inBehaviorTree)
|
||||
{
|
||||
_behaviorTree = inBehaviorTree;
|
||||
SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.SelfGameObject), gameObject);
|
||||
|
||||
_blackboardSo = ScriptableObject.CreateInstance<CustomerBlackboardSo>();
|
||||
_blackboardSo.SetVariable(RestaurantCustomerBlackboardKey.SelfGameObject, gameObject);
|
||||
|
||||
if (!_behaviorTree) return;
|
||||
_behaviorTree.SetVariableValue(nameof(BlackboardKey.RestaurantBlackboard), _blackboardSo);
|
||||
}
|
||||
|
||||
public void SetCustomerData(string inCustomerDataId)
|
||||
{
|
||||
SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CustomerDataId), inCustomerDataId);
|
||||
_blackboardSo.SetVariable(RestaurantCustomerBlackboardKey.CustomerDataId, inCustomerDataId);
|
||||
}
|
||||
|
||||
public void SetBlackboardValue<T>(string key, T inValue)
|
||||
public void SetBlackboardValue<T>(RestaurantCustomerBlackboardKey key, T inValue)
|
||||
{
|
||||
if (!_behaviorTree) return;
|
||||
_behaviorTree.SetVariableValue(key, inValue);
|
||||
|
||||
var blackboardSo =
|
||||
_behaviorTree.GetVariable<CustomerBlackboardSo>(nameof(BlackboardKey.RestaurantBlackboard));
|
||||
if (blackboardSo == null || blackboardSo.Value == null)
|
||||
{
|
||||
Debug.LogWarning($"behaviorTree에 blackboardSo가 존재하지 않음 오브젝트 해시코드: {gameObject.GetHashCode()}");
|
||||
return;
|
||||
}
|
||||
blackboardSo.Value.SetVariable(key, inValue);
|
||||
}
|
||||
|
||||
public T GetBlackboardValue<T>(string key)
|
||||
public T GetBlackboardValue<T>(RestaurantCustomerBlackboardKey key)
|
||||
{
|
||||
if (!_behaviorTree) return default;
|
||||
SharedVariable<T> blackboardValue = _behaviorTree.GetVariable<T>(key);
|
||||
var blackboardSo =
|
||||
_behaviorTree.GetVariable<CustomerBlackboardSo>(nameof(BlackboardKey.RestaurantBlackboard));
|
||||
|
||||
return blackboardValue != null ? blackboardValue.Value : default;
|
||||
if (blackboardSo == null || blackboardSo.Value == null)
|
||||
{
|
||||
Debug.LogWarning($"behaviorTree에 blackboardSo가 존재하지 않음 오브젝트 해시코드: {gameObject.GetHashCode()}");
|
||||
return default;
|
||||
}
|
||||
var value = blackboardSo.Value.GetVariable<T>(key);
|
||||
return value != null ? value.Value : default;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_blackboardSo)
|
||||
{
|
||||
Destroy(_blackboardSo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
[Serializable]
|
||||
public class CustomerBlackboardSo : BlackboardSo<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5d5fca67b054314aef1ee6f3fda2b76
|
||||
timeCreated: 1756689633
|
@ -3,9 +3,9 @@
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public class CustomerTimeLimiter : SharedTimeLimiter
|
||||
public class CustomerTimeLimiter : SharedTimeLimiter<RestaurantCustomerBlackboardKey>
|
||||
{
|
||||
private IAISharedBlackboard _blackboard;
|
||||
private IAISharedBlackboard<RestaurantCustomerBlackboardKey> _blackboard;
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
|
@ -2,13 +2,18 @@
|
||||
|
||||
namespace DDD
|
||||
{
|
||||
public enum BlackboardKey
|
||||
{
|
||||
RestaurantBlackboard,
|
||||
}
|
||||
public enum RestaurantCustomerBlackboardKey
|
||||
{
|
||||
SelfGameObject,
|
||||
CustomerDataId,
|
||||
CurrentTargetGameObject,
|
||||
SatisfactionLevel,
|
||||
OrderCount,
|
||||
CumulativeOrderCount,
|
||||
Remaining
|
||||
}
|
||||
|
||||
public interface ICustomerBlackboard
|
||||
|
@ -60,6 +60,7 @@ public bool TryMoveToPosition(Vector3 position)
|
||||
|
||||
_iAstarAi.destination = position;
|
||||
PlayMove();
|
||||
_iAstarAi.SearchPath();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace DDD
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
public enum RestaurantOrderType : uint
|
||||
{
|
||||
@ -21,6 +21,16 @@ public class RestaurantOrderObjectState
|
||||
|
||||
public string FoodId;
|
||||
}
|
||||
|
||||
public class RestaurantOrderInterrupt : IEvent
|
||||
{
|
||||
public GameObject Table;
|
||||
public RestaurantOrderObjectState OrderObject;
|
||||
public RestaurantOrderType TransitionType;
|
||||
}
|
||||
|
||||
// RestaurantOrderInterrupt 이벤트 ? OrderObject, Worker는 여기에 등록해두기. Customer가 이벤트 호출
|
||||
// InterruptResult - Clean, Dirty?
|
||||
|
||||
public interface IRestaurantOrderObject
|
||||
{
|
||||
@ -31,7 +41,7 @@ public interface IRestaurantOrderObject
|
||||
|
||||
// TODO : 도중에 이탈할 경우, 순차적으로 다음 페이즈로 넘어가는 게 아니라 바로 Wait, Dirty로 전이시킬 필요가 있음
|
||||
|
||||
public class InteractionSubsystem_Order : MonoBehaviour, IInteractionSubsystemObject<RestaurantOrderType>, IRestaurantOrderObject
|
||||
public class InteractionSubsystem_Order : MonoBehaviour, IInteractionSubsystemObject<RestaurantOrderType>, IRestaurantOrderObject, IEventHandler<RestaurantOrderInterrupt>
|
||||
{
|
||||
[SerializeField] private RestaurantOrderType _currentRestaurantOrderType = RestaurantOrderType.Wait;
|
||||
[SerializeField] private RestaurantOrderObjectState _orderObjectState = new();
|
||||
@ -80,6 +90,7 @@ public ScriptableObject GetPayload()
|
||||
|
||||
public void InitializeSubsystem()
|
||||
{
|
||||
EventBus.Register(this);
|
||||
}
|
||||
|
||||
public RestaurantOrderType GetInteractionSubsystemType()
|
||||
@ -110,5 +121,17 @@ public bool CanTransitionToNextPhase()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void HandleEvent(RestaurantOrderInterrupt evt)
|
||||
{
|
||||
if (evt.Table != gameObject) return;
|
||||
Debug.Log($"Order Interrupt : {evt.TransitionType}, Current State : {GetInteractionSubsystemType()}");
|
||||
SetInteractionSubsystemType(evt.TransitionType);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
EventBus.Unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DDD.Restaurant
|
||||
{
|
||||
//public class RestaurantEnvironmentPointQueryEvent : RestaurantEventBase<PointType>
|
||||
//{
|
||||
// protected override bool EventSolve(GameObject causer, GameObject target, PointType eventType, ScriptableObject payload)
|
||||
// {
|
||||
// if (!target.TryGetComponent(out IEnvironmentPointProvider provider)) return false;
|
||||
// if (!provider.IsSupportsType(eventType)) return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17b28cfc7a5a4d43a050d247e22004dc
|
||||
timeCreated: 1756453073
|
@ -24,30 +24,20 @@ public class RestaurantInteractionEvent : RestaurantEventBase<InteractionType>
|
||||
protected override bool EventSolve(GameObject causer, GameObject target, InteractionType interactionType,
|
||||
ScriptableObject payload)
|
||||
{
|
||||
IInteractor interactor = causer.GetComponent<IInteractor>();
|
||||
if (interactor != null && interactor.CanSolveInteractionType(interactionType))
|
||||
var interactor = causer.GetComponent<IInteractor>();
|
||||
if (interactor == null || !interactor.CanSolveInteractionType(interactionType)) return false;
|
||||
if (!interactor.FetchSolverTypeForInteraction(interactionType, out var solverType)) return false;
|
||||
// Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로.
|
||||
if (solverType == null) return false;
|
||||
var solver = causer.GetComponent(solverType) as IInteractionSolver;
|
||||
var interactable = target.GetComponent<IInteractable>();
|
||||
if (solver is not null)
|
||||
{
|
||||
if (interactor.FetchSolverTypeForInteraction(interactionType, out var solverType))
|
||||
{
|
||||
// Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로.
|
||||
if (solverType != null)
|
||||
{
|
||||
IInteractionSolver solver = causer.GetComponent(solverType) as IInteractionSolver;
|
||||
IInteractable interactable = target.GetComponent<IInteractable>();
|
||||
if (solver is not null)
|
||||
{
|
||||
bool canExecute = solver.CanExecuteInteraction(interactor, interactable, payload);
|
||||
return canExecute && solver.ExecuteInteraction(interactor, interactable, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should not reach here!
|
||||
Debug.Assert(false, "Solver Component or Interactor is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
bool canExecute = solver.CanExecuteInteraction(interactor, interactable, payload);
|
||||
return canExecute && solver.ExecuteInteraction(interactor, interactable, payload);
|
||||
}
|
||||
|
||||
Debug.Assert(false, "Solver Component or Interactor is null");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user