프로그래밍/유니티
[유니티] Delegate를 이용한 공통 팝업
갓똥
2021. 7. 6. 01:12
728x90
반응형
언제든 사용할 수 있는 공용 팝업을 만들자!
생김새는 위와같이 3종류의 팝업을 만들어 상황에 맞추어 쓸 예정이다.
하이라키는 위처럼 만들었다.
MessagePopUp은 MessagePopUpController를 갖고 있으며
BlockPanel은 뒤에 배경 블러처리용으로 사용했다.
메인은 PanelPosition 아래있는 Notice, Caution, Warning이다.
자식으로 있는 Text는 위 그림과 같이 상단의 알림, 주의, 경고가 입력되어있다.
Message는 내가 넣고 싶은 텍스트를 입력할 수 있는 곳이고
OKButton과 YesOrNo버튼은 하단에 "확인" 버튼 하나만 띄울 것인지 "예, 아니오" 버튼 두개를 뜨게할지 골라 출력하게 한다.
대략 요런 형태가 된다.
아래는 코드
// MessagePopUpController.cs
using System;
using UnintyEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MessagePopUpController : MonoBehaviour
{
public delegate void Callback();
private Callback callbackOK = null;
private Callback callbackYES = null;
private Callback callbackNO = null;
// Define
public enum DialogType { NOTICE = 0, WARNING = 1, CAUTION = 2 }
public enum DialogResponse { OK, YES, NO, ERROR }
public GameObject[] Dialogs;
public GameObject MessageBox;
public GameObject OneButton;
public GameObject YesOrNoButton;
private Button OKButton;
private Button YesButton;
private Button NoButton;
private DialogResponse thisResult;
private void Awake()
{
// 버튼 배정
OKButton = OneButton.GetComponent<Button>();
YesButton = YesOrNoButton.transform.Find("YesButton").gameObject.GetComponent<Button>();
NoButton = YesOrNoButton.transform.Find("NoButton").gameObject.GetComponent<Button>();
// 기본 리스너 추가
OKButton.onClick.AddListener(PopUpClose);
YesButton.onClick.AddListener(PopUpClose);
NoButton.onClick.AddListener(PopUpClose);
}
private void DialogInit() // 초기화
{
for (int i = 0; i < Dialogs.Length; i++)
Dialogs[i].SetActive(false);
}
public void PopUp(string message, DialogType type)
{
SetCallback(null, DialogResponse.OK);
DialogInit();
Dialogs[(int)type].SetActive(true);
MessageBox.GetComponent<Text>().text = message;
YesOrNoButton.SetActive(false);
OneButton.SetActive(true);
OKButton.interactable = true;
GetComponent<Animator>().SetTrigger("PopupOpen");
}
public void PopUp(string message, DialogType type, Callback Function)
{
SetCallback(Function, DialogResponse.OK);
DialogInit();
Dialogs[(int)type].SetActive(true);
MessageBox.GetComponent<Text>().text = message;
YesOrNoButton.SetActive(false);
OneButton.SetActive(true);
OKButton.interactable = true;
GetComponent<Animator>().SetTrigger("PopupOpen");
}
public void YesOrNoPopUp(string message, DialogType type, Callback yesButtonFuncion, Callback noButtonFuntion)
{
SetCallback(yesButtonFuncion, DialogResponse.YES);
SetCallback(noButtonFuntion, DialogResponse.NO);
DialogInit();
Dialogs[(int)type].SetActive(true);
MessageBox.GetComponent<Text>().text = message;
OneButton.SetActive(false);
YesOrNoButton.SetActive(true);
YesButton.interactable = true;
NoButton.interactable = true;
GetComponent<Animator>().SetTrigger("PopupOpen");
}
// 팝업이 닫힐 때, 지정해 둔 콜백 실행
public void PopUpClose()
{
switch (EventSystem.current.currentSelectedGameObject.name)
{
case "OKButton":
thisResult = DialogResponse.OK;
callbackOK?.Invoke();
callbackOK = null;
break;
case "YesButton":
thisResult = DialogResponse.YES;
callbackYES?.Invoke();
callbackYES = null;
break;
case "NoButton":
thisResult = DialogResponse.NO;
callbackNO?.Invoke();
callbackYES = null;
break;
default:
thisResult = DialogResponse.ERROR;
break;
}
OKButton.interactable = false;
YesButton.interactable = false;
NoButton.interactable = false;
GetComponent<Animator>().SetTrigger("PopupClose");
}
// Callback 관련
public void SetCallback(Callback call, DialogResponse buttontype)
{
switch (buttontype)
{
case DialogResponse.OK:
callbackOK = call;
break;
case DialogResponse.YES:
callbackYES = call;
break;
case DialogResponse.NO:
callbackNO = call;
break;
default:
callbackOK = call;
callbackYES = call;
callbackNO = call;
break;
}
}
internal void YesOrNoPopUp(string v1, DialogType nOTICE, object v2, object p)
{
throw new NotImplementedException();
}
}
다른 코드는 전부 보면 이해가고 핵심은 delegate를 이용해 메소드를 넘겨주어 처리한다는 것이다.
사용은 아래와 같이 하면 된다.
// 싱글톤
MessagePopupController.instance.Popup("Message", DialogType.Notice, MethodName);
MessagePopupController.instance.Popup("Message", DialogType.Notice, () => HelloWorld());
// public으로 등록해놓고 쓰기
messagePopupController.YesOrNoPopUp("Message", DialogType.Notice, YesMethod, null);
messagePopupController.YesOrNoPopUp("Message", DialogType.Notice, null, () => NoMethod(param));
Delegate를 간단하게 요약하자면 (이전에 쓴글 복붙)
인자를 전달하려면 람다식을 쓰면 된다.
최종결과물
MessagePopUpController.instance.YesOrNoPopUp("튜토리얼 화면을 종료하고 다음으로 진행하시겠습니까?",
DialogType.Notice,
() => CombatManager.instance.StartBattle(player, State.Start),
null);
아,
1. Delegate를 쓸 때 Invoke를 사용하자
2. ?를 통해 null검사가 가능하다. (Method?.Invoke();)
728x90
반응형