유니티 빌드본(PC) 강제 종료 막기(Application.wantsToQuit)

    목차
728x90

PC를 목표로 빌드한 게임은 ALT+F4와 같은 시스템으로 인한 종료는 Application.Quit과 같이 즉시 종료된다. 


하지만 개인 프로젝트를 진행 중에 강제 종료키로 인한 강제 종료를 한번 막아보고 싶어졌다. 

물론 예상치 못한 상황(무한 로딩, 종료 버튼 작동 안됨 등의 문제로 인한 끄지 못하는 상황을 대비해서는 있어야 하는건 맞으나.. 짜피 작업관리자에서 강제 종료는 막지못함으로 한번 해보기로 했다.)

 
강제 종료키(ALT+F4)를 입력하면 모달창이 뜨면서 종료, 취소를 통해서 통제를 할수 있도록 만들어 보았다. 

모달창은 기존에 만들어둔것을 바탕으로 구현해보았다.

취소를 누르면 종료가 되지 않고 확인을 누르니까 즉시 종료가 되어버린다.(녹화본에서는 즉시 종료가 되니까 녹화도 종료되어버렸다.) 

여기 밑에서는 작업한 코드인데 직접 해보고 Application.wantsToQuit에 대해서 더 자세히 알게 된 것같다.
보고 wantsToQuit를 사용해 보는것도 나쁘지 않을거 같다.

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Cysharp.Threading.Tasks;

public class GameManager : MonoBehaviour
{
    [Header ("Singleton")] private static GameManager _inst;
    [Header ("Start Scene")]
    [SerializeField]private Button startButton;
    [SerializeField]private Button quitButton;
    [SerializeField]private Button menuButton;
    [SerializeField]private Button loadButton;
    private bool isModalActive = false;
    private bool? _wantsToQuit;
    private void Update()
    {
        if (Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.F4))
        {
            QuitConfirmation().Forget();
        }

        if (_wantsToQuit == true)
            Application.Quit();
    }
    
    #region 강제종료 관련 코드          
    [RuntimeInitializeOnLoadMethod]
    static void RunOnStart()
    {
        Application.wantsToQuit += WantsToQuit;
    }
    static bool WantsToQuit()
    {
        if (_inst._wantsToQuit == null)
        {
            _inst.QuitConfirmation().Forget();
            return false;
        }
        else
        {
            return _inst._wantsToQuit.Value;
        }
    }
    private async UniTaskVoid QuitConfirmation()
    {
        if (isModalActive)
        {
            return;
        }
        isModalActive = true;
        bool? result = null;

        SimpleModalWindow.Create(false)
            .SetHeader("종료")
            .SetBody("정말로 종료하시겠습니까?")
            .AddButton("종료", () => { result = true; }, ModalButtonType.Success)
            .AddButton("취소", () => { result = false; }, ModalButtonType.Danger)
            .Show();

        await UniTask.WaitUntil(() => result != null);

        _wantsToQuit = result;
        isModalActive = false;
    }
    #endregion

    #region 종료 버튼을 통한 종료 관련 코드
    private async void RequestQuitConfirmation()
    {
        if (isModalActive)
        {
            return;
        }
        isModalActive = true;
        bool? result = null;

        SimpleModalWindow.Create(false)
            .SetHeader("종료")
            .SetBody("정말로 종료하시겠습니까?")
            .AddButton("종료", () => { result = true; }, ModalButtonType.Success)
            .AddButton("취소", () => { result = false; }, ModalButtonType.Danger)
            .Show();
        await UniTask.WaitUntil(() => result != null);

        _wantsToQuit = result;
        isModalActive = false;
    } 
    

    #endregion

    private void Awake()
    {
        if (_inst == null)
        {
            _inst = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
    private void GameStart()
    {
        LoadingSceneManager.LoadScene("Game Scene");
        Debug.Log("작동 확인용");
    }
    private void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }
    private void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    private void LoadGame()
    {
        Debug.Log("작동 확인용");
        ToastModalWindow.Create(ignorable: true)
            .SetHeader("세이브 데이터가 없습니다!")
            .SetBody("게임시작을 눌러서 새게임을 시작해주세요")
            .SetDelay(3f) // Set it to 0 to make popup persistent
            //.SetIcon(sprite) // Also you can set icon
            .Show();
    } 
    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        switch (scene.name)
        {
            case "Start Scene":
            {
                startButton.onClick.AddListener(GameStart);
                quitButton.onClick.AddListener(RequestQuitConfirmation);
                loadButton.onClick.AddListener(LoadGame);
                break;
            }
            case "Game Scene":
                
                break;
        }
    }    
}

 

728x90