From 015cadde31248671d829b3b437d932f1050c8f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=82=B0?= Date: Fri, 29 Aug 2025 13:35:46 +0900 Subject: [PATCH] =?UTF-8?q?=EC=86=90=EB=8B=98=20=ED=83=80=EC=9E=84=20?= =?UTF-8?q?=EB=A6=AC=EB=AF=B8=ED=84=B0=20=EC=A0=9C=EC=9E=91,=20=EB=B8=94?= =?UTF-8?q?=EB=9E=99=EB=B3=B4=EB=93=9C=20=EA=B8=B0=EB=A1=9D=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80,=20string=20=ED=82=A4=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20IAIBlackboard=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EC=A0=9C=EB=84=A4=EB=A6=AD=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_Scripts/AI/Common/IAISharedBlackboard.cs | 6 ++- .../Common/Actions/LookAtInteractionTarget.cs | 2 +- .../Common/Actions/MoveToInteractionTarget.cs | 2 +- .../AI/Common/Decorator/TimeLimiter.cs | 43 +++++++++++-------- .../Customer/Actions/StartRestaurantOrder.cs | 6 +-- .../Actions/WaitForPlayerInteraction.cs | 2 +- .../Customer/CustomerBlackboardComponent.cs | 26 +++++------ .../Character/AI/Customer/Decorator.meta | 3 ++ .../Customer/Decorator/CustomerTimeLimiter.cs | 30 +++++++++++++ .../Decorator/CustomerTimeLimiter.cs.meta | 3 ++ ProjectSettings/EditorBuildSettings.asset | 2 +- 11 files changed, 84 insertions(+), 41 deletions(-) create mode 100644 Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator.meta create mode 100644 Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs create mode 100644 Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs.meta diff --git a/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs b/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs index 8136be741..b21a58bd7 100644 --- a/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs +++ b/Assets/_DDD/_Scripts/AI/Common/IAISharedBlackboard.cs @@ -9,7 +9,9 @@ namespace DDD /// public interface IAISharedBlackboard { - void SetBlackboardGameObject(string key, GameObject inGameObject); - GameObject GetBlackboardGameObject(string key); + + void SetBlackboardValue(string key, T inValue); + + T GetBlackboardValue(string key); } } 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 68058dfd2..4805bfbbe 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/LookAtInteractionTarget.cs @@ -37,7 +37,7 @@ public override void OnStart() _isLooking = false; var blackboard = gameObject.GetComponent(); - _cachedTarget = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + _cachedTarget = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); } public override TaskStatus OnUpdate() 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 1c37ad0f0..90f804fed 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs @@ -41,7 +41,7 @@ public override void OnStart() _isMoving = false; var blackboard = gameObject.GetComponent(); - _target = blackboard.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + _target = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); } public override TaskStatus OnUpdate() 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 4adb569c6..679cb98ec 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Decorator/TimeLimiter.cs @@ -241,30 +241,35 @@ public void Execute(ref DynamicBuffer branchComponents, public class SharedTimeLimiter : DecoratorNode { [Tooltip("최대 실행 시간(초)")] - [SerializeField] private SharedVariable m_TimeLimit = 30f; + [SerializeField] protected SharedVariable _timeLimit = 30f; [Tooltip("시간 초과 시 반환할 상태")] - [SerializeField] private TaskStatus m_TimeoutStatus = TaskStatus.Failure; + [SerializeField] protected TaskStatus _timeoutStatus = TaskStatus.Failure; + + [Tooltip("하단 블랙보드 키에 현재 시간을 저장할 지")] + [SerializeField] protected bool _isBlackboardWriteEnabled = false; + [SerializeField] protected string _blackboardKey = "CurrentTime"; public SharedVariable TimeLimit { - get => m_TimeLimit; - set => m_TimeLimit = value; + get => _timeLimit; + set => _timeLimit = value; } public TaskStatus TimeoutStatus { - get => m_TimeoutStatus; - set => m_TimeoutStatus = value; + get => _timeoutStatus; + set => _timeoutStatus = value; } - private float m_StartTime; - private float m_PauseTime = -1f; + protected float _startTime; + private float _pauseTime = -1f; public override void OnStart() { base.OnStart(); - m_StartTime = Time.time; + _startTime = Time.time; + } public override TaskStatus OnUpdate() @@ -272,15 +277,15 @@ public override TaskStatus OnUpdate() var taskComponents = m_BehaviorTree.World.EntityManager.GetBuffer(m_BehaviorTree.Entity); ref var child = ref taskComponents.ElementAt(Index + 1); - if (Time.time - m_StartTime >= m_TimeLimit.Value) + if (Time.time - _startTime >= _timeLimit.Value) { if (child.Status == TaskStatus.Running || child.Status == TaskStatus.Queued) { - child.Status = m_TimeoutStatus; + child.Status = _timeoutStatus; taskComponents[Index + 1] = child; } - return m_TimeoutStatus; + return _timeoutStatus; } if (child.Status == TaskStatus.Success || child.Status == TaskStatus.Failure) @@ -294,16 +299,16 @@ public override TaskStatus OnUpdate() public override void OnBehaviorTreeStopped(bool paused) { base.OnBehaviorTreeStopped(paused); - if (paused) m_PauseTime = Time.time; + if (paused) _pauseTime = Time.time; } public override void OnBehaviorTreeStarted() { base.OnBehaviorTreeStarted(); - if (m_PauseTime >= 0f) + if (_pauseTime >= 0f) { - m_StartTime += (Time.time - m_PauseTime); - m_PauseTime = -1f; + _startTime += (Time.time - _pauseTime); + _pauseTime = -1f; } } @@ -312,14 +317,14 @@ public override void OnBehaviorTreeStarted() public override object Save(World world, Entity entity) { // [제한 시간, 경과 시간] 저장 - return new object[] { m_TimeLimit.Value, Time.time - m_StartTime }; + return new object[] { _timeLimit.Value, Time.time - _startTime }; } public override void Load(object saveData, World world, Entity entity) { var data = (object[])saveData; - m_TimeLimit.Value = (float)data[0]; - m_StartTime = Time.time - (float)data[1]; + _timeLimit.Value = (float)data[0]; + _startTime = Time.time - (float)data[1]; } } } \ No newline at end of file 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 f294c5c79..ba29130bd 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/StartRestaurantOrder.cs @@ -23,7 +23,7 @@ public override void OnStart() public override TaskStatus OnUpdate() { var blackboard = gameObject.GetComponent(); - var target = blackboard?.GetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + var target = blackboard?.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); IInteractable currentInteractable = target?.GetComponent(); if (_targetOrderType == RestaurantOrderType.Wait) { @@ -34,7 +34,7 @@ public override TaskStatus OnUpdate() return TaskStatus.Failure; } var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), currentInteractable.GetInteractableGameObject()); + customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), currentInteractable.GetInteractableGameObject()); } // Check order type of the current interactable @@ -71,7 +71,7 @@ public override TaskStatus OnUpdate() if (_targetOrderType == RestaurantOrderType.Busy) { var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetBlackboardGameObject(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null); + customerBlackboard?.SetBlackboardValue(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 c661a508d..934bb7159 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs @@ -18,7 +18,7 @@ public override void OnStart() GameObject interactionTarget = null; if (!gameObject.TryGetComponent(out var sharedBlackboard)) return; interactionTarget = - sharedBlackboard.GetBlackboardGameObject( + sharedBlackboard.GetBlackboardValue( nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); if (interactionTarget == null) diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs index af5437e41..ed6398a68 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/CustomerBlackboardComponent.cs @@ -11,26 +11,26 @@ public class CustomerBlackboardComponent : MonoBehaviour, ICustomerBlackboard, I public void InitializeWithBehaviorTree(BehaviorTree inBehaviorTree) { _behaviorTree = inBehaviorTree; - if (!_behaviorTree) return; - _behaviorTree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.SelfGameObject), gameObject); + SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.SelfGameObject), gameObject); } public void SetCustomerData(string inCustomerDataId) { - if (!_behaviorTree) return; - _behaviorTree.SetVariableValue(nameof(RestaurantCustomerBlackboardKey.CustomerDataId), inCustomerDataId); - } - - public void SetBlackboardGameObject(string key, GameObject inGameObject) - { - if (!_behaviorTree) return; - _behaviorTree.SetVariableValue(key, inGameObject); + SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CustomerDataId), inCustomerDataId); } - public GameObject GetBlackboardGameObject(string key) + public void SetBlackboardValue(string key, T inValue) { - if (!_behaviorTree) return null; - return _behaviorTree.GetVariable(key)?.Value; + if (!_behaviorTree) return; + _behaviorTree.SetVariableValue(key, inValue); + } + + public T GetBlackboardValue(string key) + { + if (!_behaviorTree) return default; + SharedVariable blackboardValue = _behaviorTree.GetVariable(key); + + return blackboardValue != null ? blackboardValue.Value : default; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator.meta new file mode 100644 index 000000000..31757848f --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dd35b9ad54934727805aa8a9e232cffd +timeCreated: 1756440681 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs new file mode 100644 index 000000000..067f23c2c --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs @@ -0,0 +1,30 @@ +using DDD; +using Opsive.BehaviorDesigner.Runtime.Tasks; +using UnityEngine; + +namespace _DDD.Restaurant +{ + public class CustomerTimeLimiter : SharedTimeLimiter + { + private IAISharedBlackboard _blackboard; + public override void OnStart() + { + base.OnStart(); + if (!_isBlackboardWriteEnabled) return; + if (!gameObject.TryGetComponent(out _blackboard)) + { + Debug.LogError($"[{GetType().Name}] 블랙보드를 찾을 수 없습니다. 게임오브젝트 해시코드: {gameObject.GetHashCode()}"); + } + } + + public override TaskStatus OnUpdate() + { + if (_isBlackboardWriteEnabled && _blackboard != null) + { + _blackboard.SetBlackboardValue(_blackboardKey, Time.time - _startTime); + } + + return base.OnUpdate(); + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs.meta new file mode 100644 index 000000000..9f8884e00 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Decorator/CustomerTimeLimiter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 546f038ee64e401fb67a4ba7d8717b7f +timeCreated: 1756440694 \ No newline at end of file diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index ed8485fa0..b1d747c7b 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f86abe14bf9fc4c7c93dfa96efd110ef0f56c3fb96a952c57e06a723fc87c352 +oid sha256:5d69f9ac4352f59df16943fd905dd7351328f295b2a8e4f74e8346f7bd4dc1bc size 1075