Merge branch 'feature/Entry-ExitPoint' into develop

# Conflicts:
#	Assets/_DDD/_Scripts/Restaurant/Event/RestaurantInteractionEvents.cs
This commit is contained in:
김산 2025-08-29 19:35:08 +09:00
commit 759384d626
35 changed files with 701 additions and 75 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f7569e20bdc77e429d3e140c38b7185
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 186d28777ccbc484780568f74c110ff7
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -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}

View File

@ -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<int>(_emotionBlackboardKey).Value;
_emotionVisual = gameObject.GetComponentInChildren<IEmotionVisual>();
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();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c30f2fbe7c3d4b05bf0cd92810314db5
timeCreated: 1756447956

View File

@ -37,7 +37,8 @@ public override void OnStart()
_isLooking = false;
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
_cachedTarget = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
_cachedTarget = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
}
public override TaskStatus OnUpdate()

View File

@ -8,7 +8,7 @@ namespace DDD.Restaurant
/// <summary>
/// IAiMovement를 이용해 인터랙션 타겟으로 이동하는 액션
/// </summary>
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<IAISharedBlackboard>();
_target = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
_target = blackboard.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
}
public override TaskStatus OnUpdate()

View File

@ -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<IAISharedBlackboard>();
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;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cdd22f2712964a81b4a55f95c605ae13
timeCreated: 1756454016

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using Opsive.GraphDesigner.Runtime.Variables;
using UnityEngine;
namespace DDD.Restaurant
{
public class BlackboardSo<T> : ScriptableObject where T : Enum
{
private Dictionary<T, SharedVariable> _variables = new();
public SharedVariable<T1> GetVariable<T1>(T key)
{
if (_variables.TryGetValue(key, out var variable))
{
return variable as SharedVariable<T1>;
}
return null;
}
public void SetVariable<T1>(T key, T1 value)
{
var outVariable = GetVariable<T1>(key);
if (outVariable != null)
{
outVariable.Value = value;
}
else
{
SharedVariable<T1> sharedVariable = new SharedVariable<T1>() { Value = value };
_variables.Add(key, sharedVariable);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 24029c24eac8499bbb9ca02126da8148
timeCreated: 1756462002

View File

@ -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<IAISharedBlackboard>();
blackboard.SetBlackboardValue(_satisfactionBlackboardKey, (int)currentSatisfaction);
}
//TODO 만족도 계산?
private EmotionType CalculateSatisfaction()
{
return EmotionType.Satisfied;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ada80a75a61473394d6ab301a4daeaf
timeCreated: 1756449593

View File

@ -23,7 +23,7 @@ public override void OnStart()
public override TaskStatus OnUpdate()
{
var blackboard = gameObject.GetComponent<IAISharedBlackboard>();
var target = blackboard?.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
var target = blackboard?.GetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
IInteractable currentInteractable = target?.GetComponent<IInteractable>();
if (_targetOrderType == RestaurantOrderType.Wait)
{
@ -34,7 +34,7 @@ public override TaskStatus OnUpdate()
return TaskStatus.Failure;
}
var customerBlackboard = gameObject.GetComponent<IAISharedBlackboard>();
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<IAISharedBlackboard>();
customerBlackboard?.SetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget), null);
customerBlackboard?.SetBlackboardValue<GameObject>(nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject), null);
}
return TaskStatus.Success;

View File

@ -19,7 +19,7 @@ public override void OnStart()
if (!gameObject.TryGetComponent<IAISharedBlackboard>(out var sharedBlackboard)) return;
interactionTarget =
sharedBlackboard.GetBlackboardValue<GameObject>(
nameof(RestaurantCustomerBlackboardKey.CurrentInteractionTarget));
nameof(RestaurantCustomerBlackboardKey.CurrentTargetGameObject));
if (interactionTarget == null)
{

View File

@ -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)

View File

@ -6,7 +6,9 @@ public enum RestaurantCustomerBlackboardKey
{
SelfGameObject,
CustomerDataId,
CurrentInteractionTarget,
CurrentTargetGameObject,
SatisfactionLevel,
OrderCount,
}
public interface ICustomerBlackboard

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f01a9fb897547f4bd10c39acade7489
timeCreated: 1756445406

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 82eedd995f09472a9e3c6b93eeecf79f
timeCreated: 1756445877

View File

@ -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;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 01f8d593287c4672a63146e6b4905db5
timeCreated: 1756446387

View File

@ -0,0 +1,15 @@
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;
// }
//}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 17b28cfc7a5a4d43a050d247e22004dc
timeCreated: 1756453073

View File

@ -0,0 +1,39 @@
using System;
using UnityEngine;
namespace DDD.Restaurant
{
public abstract class RestaurantEventBase<T> : IEvent where T : Enum
{
protected GameObject Causer;
protected GameObject Target;
protected T EventType;
protected ScriptableObject Payload;
protected bool EventResult = false;
protected RestaurantEventBase<T> 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);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa6f80fbb0ca4c2ba33616a9f070bced
timeCreated: 1756452619

View File

@ -18,62 +18,37 @@ public static class RestaurantInteractionEventSolvers
{InteractionType.RestaurantOrder, typeof(RestaurantOrderPlayerSolver)},
};
}
public class RestaurantInteractionEvent : IEvent
public class RestaurantInteractionEvent : RestaurantEventBase<InteractionType>
{
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<IInteractor>();
if (interactor != null && interactor.CanSolveInteractionType(interactionType))
IInteractable interactable = target.GetComponent<IInteractable>();
// 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<IInteractable>();
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;
}
}
}

View File

@ -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<IInteractable> _registeredInteractables = new List<IInteractable>();
private readonly List<IEnvironmentPointProvider> _registeredPointProviders = new List<IEnvironmentPointProvider>();
/// <summary>
/// 인터랙션 가능한 객체를 등록합니다
@ -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);
}
/// <summary>
/// 인터랙션 가능한 객체를 해제합니다
/// </summary>
@ -44,6 +52,12 @@ public void UnregisterInteractable(IInteractable interactable)
_registeredInteractables.Remove(interactable);
}
public void UnRegisterPointProvider(IEnvironmentPointProvider provider)
{
if (provider == null) return;
_registeredPointProviders.Remove(provider);
}
/// <summary>
/// 특정 InteractionType에 해당하는 인터랙션 객체들을 반환합니다
/// </summary>
@ -61,6 +75,19 @@ public List<IInteractable> GetInteractablesByType(InteractionType interactionTyp
}
return result;
}
public List<IEnvironmentPointProvider> GetPointProviderByType(PointType pointType)
{
var result = new List<IEnvironmentPointProvider>();
// 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;
}
/// <summary>
/// 모든 등록된 인터랙션 객체들을 반환합니다
@ -70,5 +97,11 @@ public List<IInteractable> GetAllInteractables()
_registeredInteractables.RemoveAll(item => item == null || (item as UnityEngine.Object) == null);
return new List<IInteractable>(_registeredInteractables);
}
public List<IEnvironmentPointProvider> GetAllPointProviders()
{
_registeredPointProviders.RemoveAll(item => item == null || (item as UnityEngine.Object) == null);
return new List<IEnvironmentPointProvider>(_registeredPointProviders);
}
}
}