레스토랑 settlement 추가

This commit is contained in:
NTG 2025-09-02 18:44:20 +09:00
parent fa6746b93e
commit 0322bebc8d
34 changed files with 2362 additions and 189 deletions

Binary file not shown.

Binary file not shown.

View File

@ -520,7 +520,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7995964240802183498, guid: c40aab0ea6318ea49a4aecbc0218e971, type: 3}
propertyPath: m_SizeDelta.y
value: 49
value: 45
objectReference: {fileID: 0}
- target: {fileID: 7995964240802183498, guid: c40aab0ea6318ea49a4aecbc0218e971, type: 3}
propertyPath: m_LocalPosition.x
@ -556,7 +556,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7995964240802183498, guid: c40aab0ea6318ea49a4aecbc0218e971, type: 3}
propertyPath: m_AnchoredPosition.y
value: -24.5
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7995964240802183498, guid: c40aab0ea6318ea49a4aecbc0218e971, type: 3}
propertyPath: m_LocalEulerAnglesHint.x

View File

@ -0,0 +1,107 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &6620044048037479843
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 1818210974266083558, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_Spacing
value: 10
objectReference: {fileID: 0}
- target: {fileID: 1818210974266083558, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_ChildAlignment
value: 4
objectReference: {fileID: 0}
- target: {fileID: 3692320566506517576, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_Name
value: TextVerticalLayout
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchorMax.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchorMin.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_SizeDelta.x
value: 100
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6081224996391838562, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2584c5c02497cf84abcd5f63bcc3b903, type: 3}

View File

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

View File

@ -9176,11 +9176,11 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 2603685703181773184, guid: 3042958ab9668ed4aa25e965fc39b7f9, type: 3}
propertyPath: m_AnchorMax.x
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2603685703181773184, guid: 3042958ab9668ed4aa25e965fc39b7f9, type: 3}
propertyPath: m_AnchorMax.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2603685703181773184, guid: 3042958ab9668ed4aa25e965fc39b7f9, type: 3}
propertyPath: m_AnchorMin.y
@ -9284,7 +9284,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 3674250138247648768, guid: 3042958ab9668ed4aa25e965fc39b7f9, type: 3}
propertyPath: m_IsActive
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4055127153857618644, guid: 3042958ab9668ed4aa25e965fc39b7f9, type: 3}
propertyPath: m_Sprite

View File

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

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a097d157f851d03479dfeb934e670edf
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b30903e1ac3d36240aa6bc3eef41cea8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
using Opsive.BehaviorDesigner.Runtime.Tasks;
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
using UnityEngine;
namespace DDD.Restaurant
{
public class CustomerSettlement : Action
{
public override TaskStatus OnUpdate()
{
var blackboard = gameObject.GetComponent<IAISharedBlackboard<RestaurantCustomerBlackboardKey>>();
if (blackboard == null)
{
Debug.LogWarning($"블랙보드가 존재하지 않음 해시코드: {gameObject.GetHashCode()}");
return TaskStatus.Failure;
}
var currentTarget = blackboard.GetBlackboardValue<GameObject>(RestaurantCustomerBlackboardKey.CurrentTargetGameObject);
if (currentTarget == null) return TaskStatus.Failure;
var customerId = blackboard.GetBlackboardValue<string>(RestaurantCustomerBlackboardKey.CustomerDataId);
CustomerType customerType = DataManager.Instance.GetDataAsset<CustomerDataAsset>().GetDataById(customerId).CustomerType;
if (customerType == CustomerType.None)
{
Debug.LogError("[CustomerSettlement] 손님 타입 오류");
return TaskStatus.Failure;
}
var orderObject = currentTarget.GetComponent<IRestaurantOrderObject>();
string servedFoodId = orderObject?.GetOrderObjectState().ServedFoodId;
// TODO : 전달받은 음식의 가격을 주고 있을 뿐 추후 계산 방식 변경
int price = 0;
bool isFood = DataManager.Instance.GetDataAsset<FoodDataAsset>().TryGetDataById(servedFoodId, out var foodDataEntry);
if (isFood)
{
price = foodDataEntry.Price;
}
else
{
bool isDrink = DataManager.Instance.GetDataAsset<DrinkDataAsset>().TryGetDataById(servedFoodId, out var drinkDataEntry);
if (isDrink)
{
price = drinkDataEntry.Price;
}
else
{
Debug.LogError("[CustomerSettlement] 요리 매칭 오류");
return TaskStatus.Failure;
}
}
RestaurantState.Instance.SettlementState.CustomerSettlement(customerType, price, servedFoodId);
return TaskStatus.Success;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c8ce8eada72c48eda7993b7a7add4242
timeCreated: 1756800221

View File

@ -0,0 +1,41 @@
using System.Threading.Tasks;
namespace DDD.Restaurant
{
public class SettlementController : FlowController
{
private RestaurantSettlementState _settlementState;
public override Task InitializeController()
{
return Task.CompletedTask;
}
public override Task InitializeState()
{
_settlementState = RestaurantState.Instance.SettlementState;
return Task.CompletedTask;
}
public override Task OnReadyNewFlow(GameFlowState newFlowState)
{
if (newFlowState == GameFlowState.ReadyForRestaurant)
{
_settlementState.InitializeState();
}
else if (newFlowState == GameFlowState.SettlementRestaurant)
{
// TODO : UI 띄우기
_settlementState.SaveSettlementResult();
}
return Task.CompletedTask;
}
public override Task OnExitCurrentFlow(GameFlowState exitingFlowState)
{
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0abea0e88c424b8798ceb6b974b67907
timeCreated: 1756796516

View File

@ -22,7 +22,8 @@ public class RestaurantController : Singleton<RestaurantController>, IManager, I
typeof(EnvironmentController),
typeof(ManagementController),
typeof(RunController),
typeof(GlobalMessageController)
typeof(GlobalMessageController),
typeof(SettlementController)
};
public void PreInit()

View File

@ -0,0 +1,10 @@
using UnityEngine;
namespace DDD.Restaurant
{
[CreateAssetMenu(fileName = "RestaurantSettlementData", menuName = "RestaurantData/RestaurantSettlementData")]
public class RestaurantSettlementData : ScriptableObject
{
public GameObject TextPrefab;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6e4f8a7758942d0979804d19942fd77
timeCreated: 1756804750

View File

@ -11,11 +11,13 @@ public class RestaurantData : ScriptSingleton<RestaurantData>
[SerializeField] private AssetReference _restaurantManagementData;
[SerializeField] private AssetReference _restaurantRunData;
[SerializeField] private AssetReference _restaurantCustomerData;
[SerializeField] private AssetReference _restaurantSettlementData;
public RestaurantPlayerData PlayerData { get; private set; }
public RestaurantManagementData ManagementData { get; private set; }
public RestaurantRunData RunData { get; private set; }
public RestaurantCustomerData CustomerData { get; private set; }
public RestaurantSettlementData SettlementData { get; private set; }
private bool _isLoaded;
@ -30,6 +32,7 @@ public async Task LoadData()
ManagementData = await AssetManager.Instance.LoadAssetAsync<RestaurantManagementData>(_restaurantManagementData);
RunData = await AssetManager.Instance.LoadAssetAsync<RestaurantRunData>(_restaurantRunData);
CustomerData = await AssetManager.Instance.LoadAssetAsync<RestaurantCustomerData>(_restaurantCustomerData);
SettlementData = await AssetManager.Instance.LoadAssetAsync<RestaurantSettlementData>(_restaurantSettlementData);
_isLoaded = true;
}
@ -45,11 +48,13 @@ private void OnDisable()
AssetManager.Instance.ReleaseAsset(_restaurantManagementData);
AssetManager.Instance.ReleaseAsset(_restaurantRunData);
AssetManager.Instance.ReleaseAsset(_restaurantCustomerData);
AssetManager.Instance.ReleaseAsset(_restaurantSettlementData);
PlayerData = null;
ManagementData = null;
RunData = null;
CustomerData = null;
SettlementData = null;
_isLoaded = false;
}

View File

@ -0,0 +1,42 @@
using System.Collections.Generic;
using UnityEngine;
namespace DDD.Restaurant
{
public class RestaurantSettlementState : ScriptableObject
{
public int TotalRevenue;
public int NormalCustomers;
public int SpecialCustomers;
public Dictionary<string, int> SoldCookingCounts;
public void InitializeState()
{
TotalRevenue = 0;
NormalCustomers = 0;
SpecialCustomers = 0;
SoldCookingCounts = new Dictionary<string, int>();
}
public void CustomerSettlement(CustomerType customerType, int price, string cookingId)
{
if (customerType == CustomerType.Normal)
{
NormalCustomers++;
}
else if (customerType == CustomerType.Special)
{
SpecialCustomers++;
}
TotalRevenue += price;
SoldCookingCounts.TryAdd(cookingId, 1);
}
public void SaveSettlementResult()
{
// TODO : 골드 경험치 등 필요 데이터 저장
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: efbbbf287af74ed8bb273b213a254649
timeCreated: 1756797585

View File

@ -7,6 +7,7 @@ public class RestaurantState : ScriptSingleton<RestaurantState>
public RestaurantEnvironmentState EnvironmentState { get; private set; }
public RestaurantPlayerState PlayerState { get; private set; }
public RestaurantCustomerState CustomerState { get; private set; }
public RestaurantSettlementState SettlementState { get; private set; }
private void OnEnable()
{
@ -15,6 +16,7 @@ private void OnEnable()
EnvironmentState = CreateInstance<RestaurantEnvironmentState>();
PlayerState = CreateInstance<RestaurantPlayerState>();
CustomerState = CreateInstance<RestaurantCustomerState>();
SettlementState = CreateInstance<RestaurantSettlementState>();
}
private void OnDisable()
@ -24,6 +26,7 @@ private void OnDisable()
if (EnvironmentState) DestroyImmediate(EnvironmentState);
if (PlayerState) DestroyImmediate(PlayerState);
if (CustomerState) DestroyImmediate(CustomerState);
if (SettlementState) DestroyImmediate(SettlementState);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 52bc5ededdaa41beab9352d9af69838e
timeCreated: 1756802739

View File

@ -0,0 +1,66 @@
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
namespace DDD.Restaurant
{
[RequireComponent(typeof(SettlementViewModel))]
public class SettlementUi : PopupUi<RestaurantUiActions, SettlementViewModel>
{
[SerializeField] private CommonButton _confirmButton;
[SerializeField] private TextMeshProUGUI _totalRevenueLabel;
[SerializeField] private TextMeshProUGUI _normalCustomersLabel;
[SerializeField] private TextMeshProUGUI _specialCustomersLabel;
[SerializeField] private Transform _soldCookingParent;
protected override GameObject GetInitialSelected()
{
return _confirmButton.gameObject;
}
protected override void OnCreatedInitializePopup()
{
BindingHelper.BindText(_bindingContext, _totalRevenueLabel, nameof(_viewModel.TotalRevenue));
BindingHelper.BindText(_bindingContext, _normalCustomersLabel, nameof(_viewModel.NormalCustomers));
BindingHelper.BindText(_bindingContext, _specialCustomersLabel, nameof(_viewModel.SpecialCustomers));
}
protected override void OnOpenedEventsPopup(OpenPopupUiEvent evt)
{
_viewModel.UpdateSettlement(_soldCookingParent);
}
protected override void OnClosedEventsPopup(ClosePopupUiEvent evt)
{
}
protected override void OnInputStartedPopup(RestaurantUiActions actionEnum, InputAction.CallbackContext context)
{
switch (actionEnum)
{
case RestaurantUiActions.Interact1:
HandleInteract1();
break;
}
}
protected override void OnInputPerformedPopup(RestaurantUiActions actionEnum, InputAction.CallbackContext context)
{
}
protected override void OnInputCanceledPopup(RestaurantUiActions actionEnum, InputAction.CallbackContext context)
{
}
private void HandleInteract1()
{
var selected = EventSystem.current.currentSelectedGameObject;
var interactable = selected?.GetComponent<IInteractableUi>();
interactable?.OnInteract();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: be3f1b851fc94f679128040f048afebb
timeCreated: 1756802760

View File

@ -0,0 +1,61 @@
using TMPro;
using UnityEngine;
namespace DDD.Restaurant
{
public class SettlementViewModel : SimpleViewModel
{
private RestaurantSettlementData _settlementData;
private RestaurantSettlementState _settlementState;
private string _totalRevenue;
public string TotalRevenue
{
get => _totalRevenue;
private set => SetField(ref _totalRevenue, value);
}
private string _normalCustomers;
public string NormalCustomers
{
get => _normalCustomers;
private set => SetField(ref _normalCustomers, value);
}
private string _specialCustomers;
public string SpecialCustomers
{
get => _specialCustomers;
private set => SetField(ref _specialCustomers, value);
}
public override void Initialize()
{
_settlementData = RestaurantData.Instance.SettlementData;
_settlementState = RestaurantState.Instance.SettlementState;
}
public override void Cleanup()
{
}
public void UpdateSettlement(Transform parent)
{
TotalRevenue = $"총 수익 : {_settlementState.TotalRevenue.ToGold()}";
NormalCustomers = $"일반 손님 수 : {_settlementState.NormalCustomers}";
SpecialCustomers = $"스폐셜 손님 수 : {_settlementState.SpecialCustomers}";
Utils.DestroyAllChildren(parent);
int count = 0;
foreach (var soldCookingCount in _settlementState.SoldCookingCounts)
{
count++;
var instance = Instantiate(_settlementData.TextPrefab, parent);
var textMeshProUGUI = instance.GetComponent<TextMeshProUGUI>();
var cookingName = LocalizationManager.Instance.GetName(soldCookingCount.Key);
textMeshProUGUI.text = $"판매된 메뉴{count} : {cookingName} {soldCookingCount.Value}";
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e035bfa3d4736014683ad6f6d8fbfec1