diff --git a/Assets/_DDD/Restaurant/Environments/PointMarker.meta b/Assets/_DDD/Restaurant/Environments/PointMarker.meta new file mode 100644 index 000000000..ee47e304f --- /dev/null +++ b/Assets/_DDD/Restaurant/Environments/PointMarker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f7569e20bdc77e429d3e140c38b7185 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab b/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab new file mode 100644 index 000000000..d59e7e33b --- /dev/null +++ b/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab @@ -0,0 +1,103 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4103096974375017811 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3697702677815423220} + - component: {fileID: 3761059052922690693} + - component: {fileID: 7433508832753786351} + m_Layer: 7 + m_Name: PointMarker + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3697702677815423220 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &3761059052922690693 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: 22cbc31c0f91548f096d10d462447973, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 0.41, y: 3.41} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!114 &7433508832753786351 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103096974375017811} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 01f8d593287c4672a63146e6b4905db5, type: 3} + m_Name: + m_EditorClassIdentifier: + _pointType: 0 diff --git a/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab.meta b/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab.meta new file mode 100644 index 000000000..28c315929 --- /dev/null +++ b/Assets/_DDD/Restaurant/Environments/PointMarker/PointMarker.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 186d28777ccbc484780568f74c110ff7 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset b/Assets/_DDD/_Addressables/AI/Customer/Subtree/CustomerDefault.asset index 60c7d1530..7529b61c5 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:61af29ad3709aee08733b30c715f6f318e7f99be67a7a7486eb4cfd72556e972 -size 66395 +oid sha256:8089b1a0f359704e721ce008d9816bc58743c7a00abdf7cc504619f18500877f +size 67585 diff --git a/Assets/_DDD/_Addressables/Scenes/Restaurant.unity b/Assets/_DDD/_Addressables/Scenes/Restaurant.unity index 332c922c8..4444d43a5 100644 --- a/Assets/_DDD/_Addressables/Scenes/Restaurant.unity +++ b/Assets/_DDD/_Addressables/Scenes/Restaurant.unity @@ -1169,6 +1169,84 @@ Transform: m_CorrespondingSourceObject: {fileID: 1061695247072719575, guid: 70f56d7d65d2e7842b5bd517ae7fe7fe, type: 3} m_PrefabInstance: {fileID: 254422935} m_PrefabAsset: {fileID: 0} +--- !u!1001 &258167323 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1274705225} + m_Modifications: + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.x + value: 3.6498075 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.y + value: 0.53 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.z + value: 3.17 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.w + value: 0.9396927 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.x + value: 0.3420201 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 40 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3761059052922690693, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_Color.b + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3761059052922690693, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_Color.g + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3761059052922690693, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_Color.r + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4103096974375017811, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_Name + value: ExitPointMarker + objectReference: {fileID: 0} + - target: {fileID: 7433508832753786351, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: _pointType + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 186d28777ccbc484780568f74c110ff7, type: 3} +--- !u!4 &258167324 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + m_PrefabInstance: {fileID: 258167323} + m_PrefabAsset: {fileID: 0} --- !u!1001 &258222979 PrefabInstance: m_ObjectHideFlags: 0 @@ -5833,6 +5911,68 @@ Transform: m_CorrespondingSourceObject: {fileID: 6689525833630355058, guid: 3d5223f30fdbde645a80188adc0cb577, type: 3} m_PrefabInstance: {fileID: 1284467807} m_PrefabAsset: {fileID: 0} +--- !u!1001 &929645616 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1274705225} + m_Modifications: + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.x + value: 6.541485 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.y + value: 0.53 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalPosition.z + value: 24.356 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.w + value: 0.9396927 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.x + value: 0.3420201 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 40 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4103096974375017811, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + propertyPath: m_Name + value: EntryPointMarker + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 186d28777ccbc484780568f74c110ff7, type: 3} +--- !u!4 &929645617 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 3697702677815423220, guid: 186d28777ccbc484780568f74c110ff7, type: 3} + m_PrefabInstance: {fileID: 929645616} + m_PrefabAsset: {fileID: 0} --- !u!1001 &931717435 PrefabInstance: m_ObjectHideFlags: 0 @@ -8558,6 +8698,8 @@ Transform: - {fileID: 27095953} - {fileID: 2029954630} - {fileID: 1390875353} + - {fileID: 929645617} + - {fileID: 258167324} m_Father: {fileID: 1428769370} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1284467807 @@ -8711,6 +8853,52 @@ Transform: m_CorrespondingSourceObject: {fileID: 1061695247072719575, guid: 70f56d7d65d2e7842b5bd517ae7fe7fe, type: 3} m_PrefabInstance: {fileID: 1629500546} m_PrefabAsset: {fileID: 0} +--- !u!1 &1367038805 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1367038807} + - component: {fileID: 1367038806} + m_Layer: 0 + m_Name: (Singleton)DDD.AssetManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1367038806 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1367038805} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 38667042b7dae844b813b6d15d63ec65, type: 3} + m_Name: + m_EditorClassIdentifier: + _persistent: 0 + _enableDebugLog: 0 +--- !u!4 &1367038807 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1367038805} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1368937918 GameObject: m_ObjectHideFlags: 0 @@ -15527,3 +15715,4 @@ SceneRoots: - {fileID: 761682093} - {fileID: 549344125} - {fileID: 1775054121} + - {fileID: 1367038807} diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs new file mode 100644 index 000000000..e668ae601 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs @@ -0,0 +1,53 @@ +using Opsive.BehaviorDesigner.Runtime.Tasks; +using Opsive.BehaviorDesigner.Runtime.Tasks.Actions; +using Unity.VisualScripting; +using UnityEngine; + +namespace DDD.Restaurant +{ + public enum EmotionType + { + Angry, + Satisfied, + } + + public class ExpressEmotion : Action + { + public interface IEmotionVisual + { + bool HasEmotionAvailable(EmotionType emotionType); + void ShowEmotion(EmotionType emotionType); + void EndEmotion(); + } + + //이를 파생해서 기본값을 주거나, 바로 사용하면 될 듯 + [SerializeField] protected string _emotionBlackboardKey; + + private IEmotionVisual _emotionVisual; + + public override void OnStart() + { + var currentEmotion = (EmotionType)m_BehaviorTree.GetVariable(_emotionBlackboardKey).Value; + + _emotionVisual = gameObject.GetComponentInChildren(); + if (_emotionVisual == null) + { + Debug.LogWarning($"[{GetType().Name}] Emotion Interface가 없습니다. 게임오브젝트 해시코드: {gameObject.GetHashCode()}"); + return; + } + + if (!_emotionVisual.HasEmotionAvailable(currentEmotion)) + { + Debug.LogWarning($"[{GetType().Name}] {nameof(currentEmotion)}이 없습니다. 게임오브젝트 해시코드: {gameObject.GetHashCode()}"); + return; + } + + _emotionVisual.ShowEmotion(currentEmotion); + } + + public override void OnEnd() + { + _emotionVisual?.EndEmotion(); + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs.meta new file mode 100644 index 000000000..c5ab560c0 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/ExpressEmotion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c30f2fbe7c3d4b05bf0cd92810314db5 +timeCreated: 1756447956 \ No newline at end of file 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 4805bfbbe..8a8aff755 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,8 @@ public override void OnStart() _isLooking = false; var blackboard = gameObject.GetComponent(); - _cachedTarget = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + + _cachedTarget = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject)); } 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/MoveToTargetPoint.cs similarity index 98% rename from Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs rename to Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToTargetPoint.cs index 90f804fed..26b4271b8 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToTargetPoint.cs @@ -8,7 +8,7 @@ namespace DDD.Restaurant /// /// IAiMovement를 이용해 인터랙션 타겟으로 이동하는 액션 /// - public class MoveToInteractionTarget : Action + public class MoveToTargetPoint : Action { [Header("Target Settings")] [Tooltip("InteractionPoints를 사용해 가장 가까운 지점으로 이동")] @@ -41,7 +41,7 @@ public override void OnStart() _isMoving = false; var blackboard = gameObject.GetComponent(); - _target = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + _target = blackboard.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject)); } public override TaskStatus OnUpdate() diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToTargetPoint.cs.meta similarity index 100% rename from Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToInteractionTarget.cs.meta rename to Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/MoveToTargetPoint.cs.meta diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs new file mode 100644 index 000000000..7e4190980 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs @@ -0,0 +1,35 @@ +using Opsive.BehaviorDesigner.Runtime.Tasks; +using Opsive.BehaviorDesigner.Runtime.Tasks.Actions; +using UnityEngine; + +namespace DDD.Restaurant +{ + public class SearchAndRegisterMarker : Action + { + [SerializeField] private PointType _pointType; + [SerializeField] private RestaurantCustomerBlackboardKey _markerBlackboardKey; + private bool _isRegistered; + + public override void OnStart() + { + var environmentState = RestaurantState.Instance?.EnvironmentState; + if (environmentState == null) return; + var pointProviders = environmentState.GetPointProviderByType(_pointType); + var blackboard = gameObject.GetComponent(); + if (blackboard == null) return; + + foreach (var pointProvider in pointProviders) + { + if (!pointProvider.IsSupportsType(_pointType)) continue; + blackboard.SetBlackboardValue(nameof(_markerBlackboardKey), pointProvider.GetGameObject()); + _isRegistered = true; + break; + } + } + + public override TaskStatus OnUpdate() + { + return _isRegistered ? TaskStatus.Success : TaskStatus.Failure; + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs.meta new file mode 100644 index 000000000..f4d475d9d --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/Actions/SearchAndRegisterMarker.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cdd22f2712964a81b4a55f95c605ae13 +timeCreated: 1756454016 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs new file mode 100644 index 000000000..45405d752 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using Opsive.GraphDesigner.Runtime.Variables; +using UnityEngine; + +namespace DDD.Restaurant +{ + public class BlackboardSo : ScriptableObject where T : Enum + { + private Dictionary _variables = new(); + + public SharedVariable GetVariable(T key) + { + if (_variables.TryGetValue(key, out var variable)) + { + return variable as SharedVariable; + } + + return null; + } + + public void SetVariable(T key, T1 value) + { + var outVariable = GetVariable(key); + if (outVariable != null) + { + outVariable.Value = value; + } + else + { + SharedVariable sharedVariable = new SharedVariable() { Value = value }; + _variables.Add(key, sharedVariable); + } + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs.meta new file mode 100644 index 000000000..f2af04ccc --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Common/BlackboardSO.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 24029c24eac8499bbb9ca02126da8148 +timeCreated: 1756462002 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs new file mode 100644 index 000000000..483191762 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs @@ -0,0 +1,32 @@ +using Opsive.BehaviorDesigner.Runtime.Tasks; +using Opsive.BehaviorDesigner.Runtime.Tasks.Actions; +using Opsive.GraphDesigner.Runtime; +using UnityEngine; + +namespace DDD.Restaurant +{ + public enum EvaluationStep + { + FoodSatisfactionCheck, + FavoriteTasteCheck, + } + + [NodeDescription("만족도 평가 테스크")] + public class SatisfactionEvaluator : Action + { + [SerializeField] private string _satisfactionBlackboardKey; + [SerializeField] private EvaluationStep _evaluationStep; + public override void OnStart() + { + var currentSatisfaction = CalculateSatisfaction(); + var blackboard = gameObject.GetComponent(); + blackboard.SetBlackboardValue(_satisfactionBlackboardKey, (int)currentSatisfaction); + } + + //TODO 만족도 계산? + private EmotionType CalculateSatisfaction() + { + return EmotionType.Satisfied; + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs.meta new file mode 100644 index 000000000..3392daacc --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/SatisfactionEvaluator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9ada80a75a61473394d6ab301a4daeaf +timeCreated: 1756449593 \ 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 045256e15..805caab1b 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?.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + var target = blackboard?.GetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject)); IInteractable currentInteractable = target?.GetComponent(); if (_targetOrderType == RestaurantOrderType.Wait) { @@ -34,7 +34,7 @@ public override TaskStatus OnUpdate() return TaskStatus.Failure; } var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), currentInteractable.GetInteractableGameObject()); + customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject), currentInteractable.GetInteractableGameObject()); } // Check order type of the current interactable @@ -66,12 +66,12 @@ public override TaskStatus OnUpdate() return TaskStatus.Failure; } - RestaurantEvents.InteractionEvent.RequestInteraction(_interactor.GetInteractorGameObject(), currentInteractable.GetInteractableGameObject(), currentInteractable.GetInteractionType()); + RestaurantEvents.InteractionEvent.RequestEvent(_interactor.GetInteractorGameObject(), currentInteractable.GetInteractableGameObject(), currentInteractable.GetInteractionType()); if (_targetOrderType == RestaurantOrderType.Busy) { var customerBlackboard = gameObject.GetComponent(); - customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null); + customerBlackboard?.SetBlackboardValue(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject), 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 934bb7159..fd8338fbf 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/AI/Customer/Actions/WaitForPlayerInteraction.cs @@ -19,7 +19,7 @@ public override void OnStart() if (!gameObject.TryGetComponent(out var sharedBlackboard)) return; interactionTarget = sharedBlackboard.GetBlackboardValue( - nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget)); + nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject)); if (interactionTarget == null) { diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs index 7dcb8ab7a..480813a3f 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Core/CharacterInteraction.cs @@ -42,7 +42,7 @@ protected void TryInteraction(IInteractable interactable, ScriptableObject paylo var causer = gameObject; var target = interactable.GetInteractableGameObject(); var interactionType = _nearestInteractable.GetInteractionType(); - RestaurantEvents.InteractionEvent.RequestInteraction(causer, target, interactionType, payload); + RestaurantEvents.InteractionEvent.RequestEvent(causer, target, interactionType, payload); } public IInteractionSolver GetInteractionSolver(InteractionType interactionType) diff --git a/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs b/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs index 8754ec832..04cfef17a 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Character/Interfaces/ICustomerBlackboard.cs @@ -6,7 +6,9 @@ public enum RestaurantCustomerBlackboardKey { SelfGameObject, CustomerDataId, - CurrentInteractionTarget, + CurrentTargetGameObject, + SatisfactionLevel, + OrderCount, } public interface ICustomerBlackboard diff --git a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/RestaurantSpawnPointProvider.cs b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/RestaurantSpawnPointProvider.cs new file mode 100644 index 000000000..9f777c16a --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/RestaurantSpawnPointProvider.cs @@ -0,0 +1,30 @@ +using DDD.Restaurant; +using UnityEngine; + +namespace DDD +{ + public interface ISpawnPointProvider + { + void Initialize(); + Vector3 GetSpawnPoint(); + } + + public class RestaurantSpawnPointProvider : ISpawnPointProvider + { + private Vector3 _spawnPoint = new(5f, 0f, 4f); + + public void Initialize() + { + var environmentState = RestaurantState.Instance?.EnvironmentState; + var pointProviders = environmentState.GetPointProviderByType(PointType.Entry); + foreach (var pointProvider in pointProviders) + { + if (!pointProvider.IsSupportsType(PointType.Entry)) continue; + _spawnPoint = pointProvider.GetPosition(); + break; + } + } + + public Vector3 GetSpawnPoint() => _spawnPoint; + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/SpawnPointProvider.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/RestaurantSpawnPointProvider.cs.meta similarity index 100% rename from Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/SpawnPointProvider.cs.meta rename to Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/RestaurantSpawnPointProvider.cs.meta diff --git a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/SpawnPointProvider.cs b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/SpawnPointProvider.cs deleted file mode 100644 index 1557012bb..000000000 --- a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/Run/Customer/SpawnPointProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UnityEngine; - -namespace DDD -{ - public interface ISpawnPointProvider - { - Vector3 GetSpawnPoint(); - } - - public class SpawnPointProvider : ISpawnPointProvider - { - private Vector3 _spawnPoint = new(5f, 0f, 4f); - - public Vector3 GetSpawnPoint() => _spawnPoint; - } -} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/RunController.cs b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/RunController.cs index cbd0e8e4c..149a92d3e 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/RunController.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Controller/Conrtollers/RunController.cs @@ -35,7 +35,8 @@ public override Task InitializeController() public override Task InitializeState() { - _spawnPointProvider ??= new SpawnPointProvider(); + _spawnPointProvider ??= new RestaurantSpawnPointProvider(); + _spawnPointProvider.Initialize(); _restaurantRunStateSo.InitializeSpawnPoint(_spawnPointProvider.GetSpawnPoint()); return Task.CompletedTask; } diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs b/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs new file mode 100644 index 000000000..f09354275 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs @@ -0,0 +1,20 @@ +using System; +using UnityEngine; +using UnityEngine.Splines; + +namespace DDD.Restaurant +{ + public enum PointType + { + Entry, + Exit, + } + + public interface IEnvironmentPointProvider + { + bool IsSupportsType(PointType pointType); + Vector3 GetPosition(); + + GameObject GetGameObject(); + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs.meta new file mode 100644 index 000000000..1f28a6279 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/IEnvironmentPointProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2f01a9fb897547f4bd10c39acade7489 +timeCreated: 1756445406 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider.meta b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider.meta new file mode 100644 index 000000000..17ce30822 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 82eedd995f09472a9e3c6b93eeecf79f +timeCreated: 1756445877 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs new file mode 100644 index 000000000..592ca3f0f --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace DDD.Restaurant +{ + public class EnvironmentPointMarker : MonoBehaviour, IEnvironmentPointProvider + { + [SerializeField] PointType _pointType; + + private void Start() + { + var environmentState = RestaurantState.Instance?.EnvironmentState; + environmentState?.RegisterPointProvider(this); + } + + private void OnDisable() + { + var environmentState = RestaurantState.Instance?.EnvironmentState; + environmentState?.UnRegisterPointProvider(this); + } + + public bool IsSupportsType(PointType pointType) + { + return _pointType == pointType; + } + + public Vector3 GetPosition() + { + return transform.position; + } + + public GameObject GetGameObject() + { + return gameObject; + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs.meta new file mode 100644 index 000000000..044bf26ff --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Environment/PositionProvider/EnvironmentPointMarker.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01f8d593287c4672a63146e6b4905db5 +timeCreated: 1756446387 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs new file mode 100644 index 000000000..7ef165c00 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +namespace DDD.Restaurant +{ + //public class RestaurantEnvironmentPointQueryEvent : RestaurantEventBase + //{ + // 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; + // } + //} +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs.meta new file mode 100644 index 000000000..55939787b --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEnvironmentPointQueryEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 17b28cfc7a5a4d43a050d247e22004dc +timeCreated: 1756453073 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs new file mode 100644 index 000000000..f2d7ab857 --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs @@ -0,0 +1,39 @@ +using System; +using UnityEngine; + +namespace DDD.Restaurant +{ + public abstract class RestaurantEventBase : IEvent where T : Enum + { + protected GameObject Causer; + protected GameObject Target; + protected T EventType; + protected ScriptableObject Payload; + protected bool EventResult = false; + + protected RestaurantEventBase MakeInteractionEvent(GameObject causer, GameObject target, + T eventType, + ScriptableObject payload = null) + { + Causer = causer; + Target = target; + EventType = eventType; + Payload = payload; + return this; + } + + public bool RequestEvent(GameObject causer, GameObject target, T eventType, + ScriptableObject payload = null) + { + var evt = MakeInteractionEvent(causer, target, eventType, payload); + // Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로. + evt.EventResult = EventSolve(causer, target, eventType, payload); + + EventBus.Broadcast(evt); // 이벤트 결과를 이거 받아서 처리하면 될듯. + return evt.EventResult; + } + + protected abstract bool EventSolve(GameObject causer, GameObject target, T eventType, + ScriptableObject payload); + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs.meta b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs.meta new file mode 100644 index 000000000..7803a8d5b --- /dev/null +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantEventBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa6f80fbb0ca4c2ba33616a9f070bced +timeCreated: 1756452619 \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs index 772d4e02e..cdcb66636 100644 --- a/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs +++ b/Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs @@ -18,62 +18,37 @@ public static class RestaurantInteractionEventSolvers {InteractionType.RestaurantOrder, typeof(RestaurantOrderPlayerSolver)}, }; } - - public class RestaurantInteractionEvent : IEvent + + public class RestaurantInteractionEvent : RestaurantEventBase { - public GameObject Causer; - public GameObject Target; - public InteractionType InteractionType; - public ScriptableObject Payload; - public bool EventResult = false; - - public RestaurantInteractionEvent MakeInteractionEvent(GameObject causer, GameObject target, InteractionType interactionType, - ScriptableObject payload = null) + protected override bool EventSolve(GameObject causer, GameObject target, InteractionType interactionType, + ScriptableObject payload) { - Causer = causer; - Target = target; - InteractionType = interactionType; - Payload = payload; - return this; - } - - public bool RequestInteraction(GameObject causer, GameObject target, InteractionType interactionType, - ScriptableObject payload = null, bool shouldBroadcastAfterSolve = true) - { - if (interactionType == InteractionType.None) + if (!RestaurantInteractionEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType)) { return false; } - - var evt = MakeInteractionEvent(causer, target, interactionType, payload); - evt.EventResult = false; - + + Component solverComponent = causer.GetComponent(solverType); + IInteractionSolver solver = solverComponent as IInteractionSolver; IInteractor interactor = causer.GetComponent(); - if (interactor != null && interactor.CanSolveInteractionType(interactionType)) + IInteractable interactable = target.GetComponent(); + + // Cast solverComponent to IInteractable + if (solver is not null && interactor is not null) { - if (interactor.FetchSolverTypeForInteraction(interactionType, out var solverType)) + bool canExecute = solver.CanExecuteInteraction(interactor, interactable, payload); + if (canExecute) { - // Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로. - if (solverType != null) - { - IInteractionSolver solver = causer.GetComponent(solverType) as IInteractionSolver; - IInteractable interactable = target.GetComponent(); - if (solver is not null) - { - bool canExecute = solver.CanExecuteInteraction(interactor, interactable, evt.Payload); - evt.EventResult = canExecute && solver.ExecuteInteraction(interactor, interactable, evt.Payload); - } - else - { - // Should not reach here! - Debug.Assert(false, "Solver Component or Interactor is null"); - } - } + return solver.ExecuteInteraction(interactor, interactable, payload); } + + return false; } - EventBus.Broadcast(evt);// 이벤트 결과를 이거 받아서 처리하면 될듯. - return evt.EventResult; + // Should not reach here! + Debug.Assert(false, "Solver Component or Interactor is null"); + return false; } } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/Restaurant/State/FlowStates/RestaurantEnvironmentState.cs b/Assets/_DDD/_Scripts/Restaurant/State/FlowStates/RestaurantEnvironmentState.cs index afb94720d..fe2408697 100644 --- a/Assets/_DDD/_Scripts/Restaurant/State/FlowStates/RestaurantEnvironmentState.cs +++ b/Assets/_DDD/_Scripts/Restaurant/State/FlowStates/RestaurantEnvironmentState.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using UnityEngine; -namespace DDD +namespace DDD.Restaurant { [Serializable] public class RestaurantPropLocation @@ -24,6 +24,7 @@ public class RestaurantEnvironmentState : ScriptableObject // 인터랙션 가능한 객체(IInteractable)를 관리하기 위한 리스트 (런타임 전용) private readonly List _registeredInteractables = new List(); + private readonly List _registeredPointProviders = new List(); /// /// 인터랙션 가능한 객체를 등록합니다 @@ -35,6 +36,13 @@ public void RegisterInteractable(IInteractable interactable) _registeredInteractables.Add(interactable); } + public void RegisterPointProvider(IEnvironmentPointProvider provider) + { + if (provider == null) return; + if (_registeredPointProviders.Contains(provider)) return; + _registeredPointProviders.Add(provider); + } + /// /// 인터랙션 가능한 객체를 해제합니다 /// @@ -44,6 +52,12 @@ public void UnregisterInteractable(IInteractable interactable) _registeredInteractables.Remove(interactable); } + public void UnRegisterPointProvider(IEnvironmentPointProvider provider) + { + if (provider == null) return; + _registeredPointProviders.Remove(provider); + } + /// /// 특정 InteractionType에 해당하는 인터랙션 객체들을 반환합니다 /// @@ -61,6 +75,19 @@ public List GetInteractablesByType(InteractionType interactionTyp } return result; } + + public List GetPointProviderByType(PointType pointType) + { + var result = new List(); + // null 또는 Destroyed 오브젝트 정리 + _registeredPointProviders.RemoveAll(item => item == null || (item as UnityEngine.Object) == null); + foreach (var provider in _registeredPointProviders) + { + if (!provider.IsSupportsType(pointType)) continue; + result.Add(provider); + } + return result; + } /// /// 모든 등록된 인터랙션 객체들을 반환합니다 @@ -70,5 +97,11 @@ public List GetAllInteractables() _registeredInteractables.RemoveAll(item => item == null || (item as UnityEngine.Object) == null); return new List(_registeredInteractables); } + + public List GetAllPointProviders() + { + _registeredPointProviders.RemoveAll(item => item == null || (item as UnityEngine.Object) == null); + return new List(_registeredPointProviders); + } } } \ No newline at end of file