유니티 심화/복습

[복습] 동기/ 비동기

다모아 2023. 8. 31. 01:40

새프로젝트에서 안보고 복습 해봤는데 처음에 뭔가 App이 사라져서 DontDestroyOnLoad를 추가하지 않은걸 알게되었다.

DontDestroyonLoad를 추가해주지 않은 모습


DontDestroyOnLoad를 추가해준 모습

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class App : MonoBehaviour
{
    //동기 비동기
    //App에 TestMain과 GameMain을 얻어온다.
    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
    }

    private void Start()
    {
        this.ChangeScene();
    }

    private void ChangeScene()
    {
        //비동기 변수 설정
        AsyncOperation oper = SceneManager.LoadSceneAsync("Test");
        //변수로 할당 가져오기
        oper.completed += (obj) => {
            TestMain testMain = GameObject.FindObjectOfType<TestMain>();
            testMain.Init();
        };

    }

}

 

이렇게 쓰고보니 enum으로 eStateType으로 쓸 수 있었던 것도 기억나서 써보기로 했다.


해보던 중 Test씬에서 Button을 누르면 Game씬으로 이동하게 했는데 이상하게 Game이 엄청나게 나온다..

 

기다리면 Game 하나만 남긴 하지만 왜 그런지 이유를 모르겠다.

 

App

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class App : MonoBehaviour
{
    private enum eSceneType { 
        App, Test, Game
    }

    //동기 비동기
    //App에 TestMain과 GameMain을 얻어온다.
    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
    }

    private void Start()
    {
        this.ChangeScene(eSceneType.Test);
    }

    private void ChangeScene(eSceneType state)
    {
        //비동기 변수 설정
        AsyncOperation oper = SceneManager.LoadSceneAsync(state.ToString());

        switch (state)
        {
            case eSceneType.App:
                break;
            case eSceneType.Test:
                oper.completed += (obj) => {
                    TestMain testMain = GameObject.FindObjectOfType<TestMain>();
                    testMain.Init();
                    testMain.buttonClick = () => {
                        this.ChangeScene(eSceneType.Game);
                    };
                };
                break;
            case eSceneType.Game:
                oper.completed += (obj) => {
                    GameMain gameMain = GameObject.FindObjectOfType<GameMain>();
                    gameMain.Init();
                };
                break;
        }
    }
}

 

TestMain

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestMain : MonoBehaviour
{
    [SerializeField]
    private Button btn;

    public Action buttonClick;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        this.btn.onClick.AddListener(() => {
            this.buttonClick();
        });
    }

    public void Init()
    {
        Debug.Log("Init");
    }
}

 

GameMain

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameMain : MonoBehaviour
{
    public Action onComplete;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void Init()
    {
        Debug.Log("Load Complete");
    }
}

 


뭔가 Action<AsyncOperation> onComplete = null;로 안해줘서 그렇게 된걸까? 한번 고쳐보기로 했다.

그냥 해도 어차피 뭘 안해서 oper.completed += (obj) => { }; 로 해도 될 것 같았는데.. 뭔가 이유가 뭘까

 

뭔가 검색해봤는데도 잘 모르겠다..

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class App : MonoBehaviour
{
    private enum eSceneType { 
        App, Test, Game
    }

    //동기 비동기
    //App에 TestMain과 GameMain을 얻어온다.
    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
    }

    private void Start()
    {
        this.ChangeScene(eSceneType.Test);
    }

    private void ChangeScene(eSceneType state)
    {
        //비동기 변수 설정
        AsyncOperation oper = SceneManager.LoadSceneAsync(state.ToString());
        Action<AsyncOperation> onComplete = null;

        if(onComplete != null)
        {
            oper.completed -= onComplete;
            onComplete = null;
        }

        switch (state)
        {
            case eSceneType.App:
                break;
            case eSceneType.Test:
                onComplete = (oper) => { 
                    TestMain testMain = GameObject.FindObjectOfType<TestMain>();
                    testMain.Init();
                    testMain.buttonClick = () => {
                        this.ChangeScene(eSceneType.Game);
                    };
                };
                break;
            case eSceneType.Game:
                onComplete = (oper) => {
                    GameMain gameMain = GameObject.FindObjectOfType<GameMain>();
                    gameMain.Init();
                };
                break;
        }
        oper.completed += onComplete;
    }
}