1. 오늘 학습 키워드
제네릭 싱글톤, 액션 활용?
2. 오늘 학습 한 내용을 나만의 언어로 정리하기
숙련 프로젝트가 끝이 났고, 심화 프로젝트가 시작됐다.
이번 프로젝트에서는 내가 과정을 이해하는 바로는 부족했던 부분을 약간 되돌아보고, 스스로 갈고닦는 시간으로 느껴졌다.
Unity 배치고사를 세상 망쳤기에, 기초를 되돌아보는 기회를 가질 수 있게 됐다.
우선 ATM을 제작하는 과제를 받았는데, 지난번에 아이템을 사용할 때, 썼던 SO와 제네릭 싱글톤, 그리고 액션 및 델리게이트의 추가적인 사용을 좀 우선적으로 생각했다.
구현이 목적이 아니라 구조를 짜는 것이 목적이였기에, 작업 과정은 좀 더뎠다.
우선 버튼을 많이 사용하는 기능이기에, ButtonManager를 제작해서 버튼을 관리했다.
리스트를 사용하여 버튼을 관리하고,
SetButtonAction()를 통해 버튼과 액션을 매치했고, OnButtonClick을 통해 버튼을 구현했다.
public class ButtonManager : Singleton<ButtonManager>
{
[SerializeField] private List<Button> buttons;
private Action[] actions;
private Action<int>[] intActions;
private void Start()
{
actions = new Action[buttons.Count];
intActions = new Action<int>[buttons.Count];
for (int i = 0; i < buttons.Count; i++)
{
int index = i;
buttons[i].onClick.AddListener(() => OnButtonClick(index));
}
}
private void OnButtonClick(int index)
{
if (index < intActions.Length && intActions[index] != null)
{
intActions[index]?.Invoke(index);
}
else if (index < actions.Length)
{
actions[index]?.Invoke();
}
}
public void SetButtonAction(int index, Action action)
{
if (index >= 0 && index < actions.Length)
{
actions[index] = action;
}
}
public void SetButtonAction(int index, Action<int> action)
{
if (index >= 0 && index < intActions.Length)
{
intActions[index] = action;
}
}
}
그리고 제네릭 싱글톤을 제작했다.
지난번에 특강때 제네릭 강의를 들었을 때, 그나마 내가 시도할 만한게 이 부분이였다.
그래서 제네릭 싱글톤을 작성하며 느낀건, 원래 클래스 같은 것을 T를 사용해서 대체했다.
여기서도 GameManager를 제작했을때와 비교하면 T자리에, GameManager가 들어갔다.
이 기본적인 제네릭 싱글톤은 한 줄을 쓰는 것으로, 작업 시간이 확 줄었다..
제네릭에 대해서 심화 기간때 강의를 추가로 다시 들으며 더 배워야겠다.
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T Instance;
public static T instance
{
get
{
if (Instance == null)
{
Instance = FindObjectOfType<T>();
if (Instance == null)
{
Instance = new GameObject(typeof(T).Name).AddComponent<T>();
}
}
return Instance;
}
set { Instance = value; }
}
protected virtual void Awake()
{
if (Instance != null)
Destroy(gameObject);
else
DontDestroyOnLoad(gameObject);
}
}
그리고 SO를 통해 유저 데이터를 관리하려고 했는데, 이 부분은 Class로 관리해도 괜찮다고 하셔서 수정했다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class UserBase
{
public string userName;
public string userId;
public int cash;
public int balance;
}
[CreateAssetMenu(fileName = "NewUser", menuName = "UserData")]
public class UserData : ScriptableObject
{
[SerializeField] private List<UserBase> userInfo;
public List<UserBase> UserInfo => userInfo;
}
그리고 마지막 UIManager이다
이 부분은 Start()를 보면 인스턴스를 BM과 GM으로 요약해줬고,
버튼과 버튼을 통한 UI 부분을 UIManager로 제작했다.
액션을 통해 버튼의 메서드를 관리했다.
지난 프로젝트에서는 버튼을 델리게이트를 통해 버튼 값을 바꿔줬는데, 이번에는 버튼을 한 스크립트로 관리하는 그런 구조를 짜보고싶었다
그리고 매개 변수가 없는 액션을 0~2에서 사용하다가, 매개 변수가 필요한 액션을 사용하기 위해
ButtonManager에서 Action<int> intActions를 제작했고, 다형성을 사용하며, 변수명을 동일하게 설정해줬다.
public class UIManager : Singleton<UIManager>
{
[SerializeField] private GameObject selectPanel;
[SerializeField] private GameObject atmPanel;
[SerializeField] private TextMeshProUGUI header;
[SerializeField] private TMP_InputField inputField;
[SerializeField] private UserData userData;
private ButtonManager BM;
private bool isDeposit = false;
protected int currentuserIndex = 0;
private GameManager GM;
private void Start()
{
BM = ButtonManager.instance;
GM = GameManager.instance;
atmPanel.SetActive(false);
BM.SetButtonAction(0, OnDepositButtonClickAction);
BM.SetButtonAction(1, OnWithdrawButtonClickAction);
BM.SetButtonAction(2, OnGobackAction);
BM.SetButtonAction(3, () => OnMoneyButtonClickAction(10000));
BM.SetButtonAction(4, () => OnMoneyButtonClickAction(30000));
BM.SetButtonAction(5, () => OnMoneyButtonClickAction(50000));
BM.SetButtonAction(6, OnConfirmButtonClickAction);
//ButtonManager.instance.SetButtonAction(3, () => OnMoneyButtonClickAction(10000, "USER01", TransactionType.Deposit));
}
public void OnConfirmButtonClickAction()
{
if (int.TryParse(inputField.text, out int amount))
{
OnMoneyButtonClickAction(amount);
inputField.text = String.Empty;
}
}
public void OnDepositButtonClickAction()
{
selectPanel.SetActive(false);
atmPanel.SetActive(true);
header.text = "입금";
isDeposit = true;
}
public void OnWithdrawButtonClickAction()
{
selectPanel.SetActive(false);
atmPanel.SetActive(true);
header.text = "출금";
isDeposit = false;
}
public void OnGobackAction()
{
atmPanel.SetActive(false);
selectPanel.SetActive(true);
}
public void SetCurrentUserIndex(int index)
{
currentuserIndex = index;
}
public void OnMoneyButtonClickAction(int money)
{
if (currentuserIndex >= 0 && currentuserIndex < userData.UserInfo.Count)
{
var user = userData.UserInfo[GameManager.instance.index];
if (isDeposit)
{
if (GM.usersData.money >= money)
{
GM.usersData.money -= money;
GM.usersData.balance += money;
}
}
else
{
if (GM.usersData.balance >= money)
{
GM.usersData.money += money;
GM.usersData.balance -= money;
}
}
}
}
}
ButtonManager를 통해, 버튼 제작시에 그냥 간단히 한 줄만 적고 해당 버튼을 할당 시켜주면 버튼을 사용할 수 있게 됐다.
시작은 버튼이지만, 앞으론 더더욱 간단히 구조를 볼 수 있지 않을까 싶다..
3. 학습하며 겪었던 문제점 & 에러
제네릭 싱글톤을 제작할 때, Where T : MonoBehaviour를 빼먹어서 오류가 났다. 강의에서도 Where T를 강조해주셨는데
제작을 해보며 오류 사항을 좀 더 깎을 수 있는 기회였다.
그리고 Button을 관리하면서 매개 변수가 있는 액션을 사용할 때, 람다를 사용하면 된다. 도 알 수 있었다.
하위 코드 처럼 오류를 수정했다.
BM.SetButtonAction(3, OnMoneyButtonClickAction(money));
BM.SetButtonAction(3, (money) => OnMoneyButtonClickAction());
BM.SetButtonAction(3, () => OnMoneyButtonClickAction(10000));
그리고 제작을 하면서 머리가 좀 지끈 했던 부분은
SO로 관리하는 사용자의 UserData를 사용했을 때, UserData에 String UserID를 저장하여
해당 값을 인덱스 키로 쓰고싶었다.
그래서 ConvertUserIDToNum 메서드를 제작해서 변환 후 해당 인덱스 값을 사용하려고 했으나,
UserData.UserInfo[Index]에서 Index는 그냥 정보가 들어가있는 순서였어서
ID를 숫자로 변환하는 그런 아래의 코드는 의미가 없었다.
그리고 아직 미비하지만 구조를 짜보려고 한 것과, 버튼을 하나의 스크립트로 관리하는 방법을 생각하는데 좀 머리가 과부화가 됐다.
4. 내일 학습 할 것은 무엇인지
내일은 json에 대해서 학습을 해보려고 한다.
물론 과제 내용 중 Playerprefs를 사용해 데이터를 저장하는 방법도 있지만
Playerprefs는 접근이 키 값만 있으면 변동이 쉽기에 중요한 데이터를 저장할 때에는 사용이 되지 않는다고 경고해주셨다.
그래서 Playerprefs를 사용하지는 않을 것이고, json을 가지고 저장을 해본적이 없기에, 이 부분을 해보려고한다.
그리고 저장을 성공하면, 로그인 UI를 제작해서 해당 유저 정보를 관리 해보려고한다.
이때 유저 정보를 어떻게 관리해야하는지 머릿속에 SO 밖에 안떠올라서, 서핑을 좀 더 해봐야할 것 같다.
'TIL' 카테고리의 다른 글
25.03.24 TIL (0) | 2025.03.24 |
---|---|
25.03.21 TIL (0) | 2025.03.24 |
25.03.13 TIL (0) | 2025.03.13 |
25.03.11 TIL (0) | 2025.03.11 |
25.03.10 TIL (0) | 2025.03.10 |