계산대 로직 중간저장

This commit is contained in:
2026-04-23 15:44:45 +09:00
parent e1124c927b
commit c8c39ddbc8
10 changed files with 163 additions and 9 deletions

Binary file not shown.

View File

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

View File

@@ -0,0 +1,28 @@
using UnityEngine;
namespace VRShopping.Player
{
public class PlayerWallet : MonoBehaviour
{
//예산
[Min(0)] public int Budget;
public bool PayMoney(int cost)
{
bool successFlag;
//예산이 비용보다 많을시
if(Budget >= cost)
{
Budget -= cost;
successFlag = true;
}
else //예산 부족
{
successFlag = false;
}
return successFlag;
}
}
}

View File

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

View File

@@ -1,4 +1,9 @@
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using VRShopping.Interact;
using VRShopping.Items;
using VRShopping.Player;
using VRShopping.Shopping;
using VRShopping.UI; using VRShopping.UI;
public class PlayerController : MonoBehaviour,ITransScenePossible public class PlayerController : MonoBehaviour,ITransScenePossible
@@ -9,6 +14,7 @@ public class PlayerController : MonoBehaviour,ITransScenePossible
private bool _controlPositive = true; private bool _controlPositive = true;
[SerializeField] private ShoppingOrderView _shoppingOrderView; [SerializeField] private ShoppingOrderView _shoppingOrderView;
[SerializeField] private PlayerWallet playerWallet;
private void Awake() private void Awake()
{ {
@@ -35,4 +41,58 @@ public async void ToggleShoppingOrderList()
await _shoppingOrderView.ToggleShoppingOrderList(); await _shoppingOrderView.ToggleShoppingOrderList();
_controlPositive = true; _controlPositive = true;
} }
public void Checkout(CheckoutMachine checkoutMachine)
{
List<CheckoutProductionRow> checkoutList = checkoutMachine.GetCheckoutList();
if(playerWallet.PayMoney(checkoutMachine.CheckoutSum))
{
Debug.Log("결제완료");
if (ShoppingOrderMissionClearCheck(checkoutList, out var missing))
{
Debug.Log("게임 클리어");
}
else
{
var parts = new List<string>(missing.Count);
foreach (var (group, shortage) in missing) parts.Add($"{group} x{shortage}");
Debug.Log($"장보기 목록 미충족 — 부족: {string.Join(", ", parts)}");
}
}
else
{
Debug.Log("예산 부족으로 결제 불가");
}
}
//계산한 품목이 장보기 목록을 모두 충족하는지 검사 (더 많은 건 허용)
//missing: 부족한 ProductGroup과 부족 수량 목록
private bool ShoppingOrderMissionClearCheck(List<CheckoutProductionRow> checkoutList, out List<(ProductGroup group, int shortage)> missing)
{
missing = new List<(ProductGroup, int)>();
ShoppingOrderList orderList = _shoppingOrderView != null ? _shoppingOrderView.OrderList : null;
if (orderList == null) return true;
//구매한 품목을 ProductGroup 기준으로 집계
var boughtByGroup = new Dictionary<ProductGroup, int>();
foreach (var row in checkoutList)
{
if (row.Item == null) continue;
boughtByGroup.TryGetValue(row.Item.ProductGroup, out int count);
boughtByGroup[row.Item.ProductGroup] = count + row.Quantity;
}
//목록의 각 항목을 전부 확인해서 부족분 수집
foreach (var entry in orderList.Entries)
{
boughtByGroup.TryGetValue(entry.ProductGroup, out int count);
int shortage = entry.RequiredQuantity - count;
if (shortage > 0) missing.Add((entry.ProductGroup, shortage));
}
return missing.Count == 0;
}
} }

View File

@@ -1,7 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using VRShopping.Items; using VRShopping.Items;
using VRShopping.Player;
using VRShopping.Shopping;
using VRShopping.UI; using VRShopping.UI;
namespace VRShopping.Interact namespace VRShopping.Interact
@@ -12,20 +15,24 @@ public class CheckoutMachine : MonoBehaviour
[SerializeField] private Transform _rowContainer; [SerializeField] private Transform _rowContainer;
[SerializeField] private CheckoutProductionRow _rowPrefab; [SerializeField] private CheckoutProductionRow _rowPrefab;
private readonly Dictionary<string, CheckoutProductionRow> _rowByItemId = new(); private readonly Dictionary<string, CheckoutProductionRow> _rowByItemId = new();
private int _nextOrderNum = 1;
[SerializeField] private TMP_Text _checkoutSumField; [SerializeField] private TMP_Text _checkoutSumField;
private void Start()
{
UpdateSumUI();
}
public void UpdateSumUI() public void UpdateSumUI()
{ {
_checkoutSumField.text = CheckoutSum.ToString("N0"); if (_checkoutSumField != null)
_checkoutSumField.text = CheckoutSum.ToString("N0");
} }
public void AddCheckoutProduction(ItemData itemData) public void AddCheckoutProduction(ItemData itemData)
{ {
Debug.Log("추가버튼 누름");
if (itemData == null) return; if (itemData == null) return;
if (_rowByItemId.TryGetValue(itemData.ItemId, out CheckoutProductionRow row)) if (_rowByItemId.TryGetValue(itemData.ItemId, out CheckoutProductionRow row))
@@ -35,19 +42,27 @@ public void AddCheckoutProduction(ItemData itemData)
else else
{ {
row = Instantiate(_rowPrefab, _rowContainer); row = Instantiate(_rowPrefab, _rowContainer);
row.gameObject.SetActive(false); // OnEnable 지연
row.Bind(itemData, 1);
row.SetOrderNum(_nextOrderNum++);
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(_rowContainer as RectTransform);
row.gameObject.SetActive(true); // 바운드 확정 후 OnEnable
row.OnAddClicked += AddCheckoutProduction; row.OnAddClicked += AddCheckoutProduction;
row.OnRemoveClicked += RemoveCheckoutProduction; row.OnRemoveClicked += RemoveCheckoutProduction;
row.Bind(itemData, 1);
_rowByItemId[itemData.ItemId] = row; _rowByItemId[itemData.ItemId] = row;
} }
CheckoutSum += itemData.FinalPrice; CheckoutSum += itemData.FinalPrice;
UpdateSumUI();
} }
public void RemoveCheckoutProduction(ItemData itemData) public void RemoveCheckoutProduction(ItemData itemData)
{ {
Debug.Log("감소버튼 누름");
if (itemData == null) return; if (itemData == null) return;
if (!_rowByItemId.TryGetValue(itemData.ItemId, out CheckoutProductionRow row)) return; if (!_rowByItemId.TryGetValue(itemData.ItemId, out CheckoutProductionRow row)) return;
@@ -62,6 +77,15 @@ public void RemoveCheckoutProduction(ItemData itemData)
{ {
row.Bind(itemData, row.Quantity - 1); row.Bind(itemData, row.Quantity - 1);
} }
UpdateSumUI();
}
public List<CheckoutProductionRow> GetCheckoutList()
{
var list = new List<CheckoutProductionRow>(_rowByItemId.Values);
list.Sort((a, b) => a.OrderNum.CompareTo(b.OrderNum));
return list;
} }
} }
} }

View File

@@ -16,10 +16,13 @@ public class CheckoutProductionRow : MonoBehaviour
public ItemData Item { get; private set; } public ItemData Item { get; private set; }
public int Quantity { get; private set; } public int Quantity { get; private set; }
public int OrderNum { get; private set; } = 1;
public event Action<ItemData> OnAddClicked; public event Action<ItemData> OnAddClicked;
public event Action<ItemData> OnRemoveClicked; public event Action<ItemData> OnRemoveClicked;
public void SetOrderNum(int orderNum) => OrderNum = orderNum;
private void Awake() private void Awake()
{ {
if (_addButton != null) _addButton.onClick.AddListener(() => OnAddClicked?.Invoke(Item)); if (_addButton != null) _addButton.onClick.AddListener(() => OnAddClicked?.Invoke(Item));

View File

@@ -0,0 +1,25 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.XR.Interaction.Toolkit.UI;
using VRShopping.Interact;
public class CheckoutVRButton : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
GameObject whatWasClicked = eventData.pointerPress;
if (eventData is not TrackedDeviceEventData trackedData) return;
var interactorMB = trackedData.interactor as MonoBehaviour;
if (interactorMB == null) return;
GameObject whoClicked = interactorMB.gameObject;
PlayerController clickPlayer = whoClicked.GetComponentInParent<PlayerController>();
CheckoutMachine checkoutMachine = whatWasClicked.GetComponentInParent<CheckoutMachine>();
if (clickPlayer == null || checkoutMachine == null) return;
clickPlayer.Checkout(checkoutMachine);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4b57c28251a9ae24ea3f54a09201a948

View File

@@ -11,6 +11,8 @@ public class ShoppingOrderView : MonoBehaviour
[SerializeField] private Animator _anim; [SerializeField] private Animator _anim;
[SerializeField] private GameObject _paper; [SerializeField] private GameObject _paper;
public ShoppingOrderList OrderList => _orderList;
private bool _visibleShoppingOrderList = false; private bool _visibleShoppingOrderList = false;
private void Start() private void Start()