인터랙션 및 인터랙션 솔버 구조 작성

This commit is contained in:
Jeonghyeon Ha 2025-07-22 20:15:20 +09:00
parent a54c3cec66
commit 6c11c9e801
9 changed files with 183 additions and 20 deletions

View File

@ -12,15 +12,10 @@ public static class GameEvents
public static OpenPopupUiEvent OpenPopupUiEvent = new();
public static ClosePopupUiEvent ClosePopupUiEvent = new();
public static ShowGlobalMessageEvent RequestShowGlobalMessageEvent = new();
public static InteractionEvent Interaction = new();
public static InventoryChangedEvent InventoryChangedEvent = new();
}
// public static class RestaurantEvents
// {
// // Some events...
// }
// public static class VoyageEvents
// {
// // Some events...
@ -65,11 +60,5 @@ public class ClosePopupUiEvent : IEvent
public Type UiType;
}
public class InteractionEvent : IEvent
{
public GameObject Causer;
public GameObject Target;
}
public class InventoryChangedEvent : IEvent { }
}

View File

@ -7,14 +7,23 @@ public enum InteractionType
{
None,
RestaurantManagement,
Count
}
public interface IInteractable
{
bool CanInteract();
void OnInteracted(IInteractor interactor);
bool OnInteracted(IInteractor interactor, ScriptableObject interactionPayloadSo = null);
InteractionType GetInteractionType();
GameObject GetInteractableGameObject();
void InitializeInteraction(InteractionType interactionType);
}
public interface IInteractor
{
void TryInteract(InteractionType interactionType);
GameObject GetInteractorGameObject();
}
public interface IInteractionSolver
{
bool ExecuteInteraction(IInteractor interactor, ScriptableObject interactionPayloadSo = null);
}
}

View File

@ -1,9 +1,29 @@
using DDD.RestaurantEvent;
using NUnit.Framework;
using UnityEngine;
namespace DDD
{
public class RestaurantCharacter : MonoBehaviour, IGameCharacter
public class RestaurantCharacter : MonoBehaviour, IGameCharacter, IInteractor
{
private void Start()
{
TODO_IMPLEMENT_ME();
// TODO : Add event solvers dynamically
for (int i = (int)InteractionType.Count; i < (int)InteractionType.Count; i++)
{
InteractionType interactionType = (InteractionType)i;
// TODO : if this character should handle the interaction?
if(RestaurantEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType))
{
gameObject.AddComponent(solverType);
}
}
}
public GameObject GetInteractorGameObject()
{
return TODO_IMPLEMENT_ME;
}
}
}

View File

@ -0,0 +1,23 @@
using DDD.RestaurantEvent;
using UnityEngine;
namespace DDD
{
public class RestaurantCharacterInteraction : MonoBehaviour, IInteractor, IEventHandler<RestaurantInteractionEvent>
{
private void Start()
{
EventBus.Register(this);
}
public void Invoke(RestaurantInteractionEvent evt)
{
// TODO : 이벤트결과를 보고 할 일이 있다면 여기서 뭔가 처리. 기본적으로 이벤트에서 이미 인터페이스로 인터랙션 처리됨
}
public GameObject GetInteractorGameObject()
{
return TODO_IMPLEMENT_ME;
}
}
}

View File

@ -42,11 +42,6 @@ private void GenerateDummyEnvironmentProps()
// Make dummy placement data
foreach (EnvironmentData prop in DataManager.Instance.EnvironmentDataSo.GetDataList())
{
if (prop.EnvironmentType != EnvironmentType.Prop)
{
continue;
}
for (int i = 0; i < 10; i++)
{
// Make random position

View File

@ -1,3 +1,4 @@
using DDD.RestaurantEvent;
using Spine.Unity;
using Unity.VisualScripting;
using UnityEngine;
@ -50,6 +51,13 @@ public async void Initialize(RestaurantEnvironmentData data)
transform.position = new Vector3(data.Position.x, 0f, data.Position.y);
transform.localScale = Vector3.one * environmentData.Size;
// Interaction initialize
if (environmentData.InteractionType != InteractionType.None)
{
var interactionComponent = transform.AddComponent<RestaurantInteractionComponent>();
interactionComponent.InitializeInteraction(environmentData.InteractionType);
}
}
}
}

View File

@ -0,0 +1,12 @@
using UnityEngine;
namespace DDD.RestaurantEvent
{
public class RestaurantManagementEventSolver : MonoBehaviour, IInteractionSolver
{
public bool ExecuteInteraction(IInteractor interactor, ScriptableObject interactionPayloadSo = null)
{
return TODO_IMPLEMENT_ME;
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace DDD.RestaurantEvent
{
public static class RestaurantEvents
{
public static RestaurantInteractionEvent RestaurantInteraction = new();
}
public static class RestaurantEventSolvers
{
public static Dictionary<InteractionType, Type> TypeToSolver = new()
{
{InteractionType.RestaurantManagement, typeof(RestaurantManagementEventSolver)}
};
}
public class RestaurantInteractionEvent : IEvent
{
public GameObject Causer;
public GameObject Target;
public InteractionType InteractionType;
public ScriptableObject InteractionPayloadSo;
public bool eventResult = false;
public RestaurantInteractionEvent MakeInteractionEvent(GameObject causer, GameObject target, InteractionType interactionType,
ScriptableObject interactionPayloadSo)
{
Causer = causer;
Target = target;
return this;
}
public bool RequestInteraction(GameObject causer, GameObject target, InteractionType interactionType, ScriptableObject interactionPayloadSo = null, bool shouldBroadcastAfterSolve = true)
{
if (interactionType == InteractionType.None)
{
return false;
}
var evt = MakeInteractionEvent(causer, target, interactionType, interactionPayloadSo);
evt.eventResult = false;
// Solve event directly. 이벤트 처리는 여기서 하고, 이벤트 호출로는 이런 이벤트가 호출되었고 결과가 어떻다는 거 전파하는 식으로.
if (RestaurantEventSolvers.TypeToSolver.TryGetValue(interactionType, out var solverType))
{
Component solverComponent = target.GetComponent(solverType);
IInteractionSolver solver = solverComponent as IInteractionSolver;
IInteractor interactor = causer.GetComponent<IInteractor>();
// Cast solverComponent to IInteractable
if (solver is not null && interactor is not null)
{
evt.eventResult = solver.ExecuteInteraction(interactor, interactionPayloadSo);
}
else
{
// Should not reach here!
Debug.Assert(false, "Solver Component or Interactor is null");
}
}
EventBus.Broadcast(evt);// 이벤트 결과를 이거 받아서 처리하면 될듯.
return evt.eventResult;
}
}
}

View File

@ -0,0 +1,39 @@
using UnityEngine;
namespace DDD.RestaurantEvent
{
public class RestaurantInteractionComponent : MonoBehaviour, IInteractable
{
public bool CanInteract()
{
return true;
}
public bool OnInteracted(IInteractor interactor, ScriptableObject interactionPayloadSo = null)
{
if (CanInteract() == false)
{
return false;
}
bool interactionResult = RestaurantEvents.RestaurantInteraction.RequestInteraction(interactor.GetInteractorGameObject(),
GetInteractableGameObject(), GetInteractionType(), interactionPayloadSo, true);
return interactionResult;
}
public InteractionType GetInteractionType()
{
return TODO_IMPLEMENT_ME;
}
public GameObject GetInteractableGameObject()
{
return TODO_IMPLEMENT_ME;
}
public void InitializeInteraction(InteractionType interactionType)
{
TODO_IMPLEMENT_ME();
}
}
}