게임 개발 로그

미니게임: 미로 숨바꼭질 본문

게임 개발/미니게임

미니게임: 미로 숨바꼭질

03:00am 2024. 12. 9. 17:12

 

 

 

0. 구현

Managers 

  • GameManager
  • EventBusManager
  • LoadingSceneManager
  • SoundManager

 

 

GameManager

게임 진행 중인지 판단 및 점수/시간 기록, 게임 오버 판단 등을 담당함.

public class GameManager : SingleTon<GameManager>
{
    public bool bGameOver = false;
    public int score = 0;
    public int enemyScore = 0;
    public float time = 60;
    public bool isPlaying = true;

    private void Update()
    {
        if (isPlaying)
        {
            time -= Time.deltaTime;
            if (time < 0)
            {
                bGameOver = true;
                time = 0;
                isPlaying = false;
                EventBusManager.Publish(EventBusType.Timeout);
            }
        }
    }
    public void GameOver()
    {
        Debug.Log("GameOver");
        isPlaying = false;
        bGameOver = true;
        EventBusManager.Publish(EventBusType.Gameover);
    }

    public void GameReset()
    {
        score = 0;
        enemyScore = 0;
        bGameOver = false;
        isPlaying = true;
        time = 90;
        EventBusManager.Clear();
    }
}

 

 

 

EventBusManager

이벤트 발생 시 구독자에게 이벤트 발생 여부를 전달해 주는 역할이다. 플레이어가 데미지를 받았을 때 HUD와 UI에 사용하기 위해 PlayerDamaged 이벤트를, GameOver와 Timeout 등의 이벤트를 처리하기 위해 세 가지 타입을 사용하고 있다. 

public enum EventBusType
{
	PlayerDamaged,
	Gameover,
	Timeout,
	Max
}

public class EventBusManager : MonoBehaviour
{
	private static readonly IDictionary<EventBusType, UnityEvent>
			Events = new Dictionary<EventBusType, UnityEvent>();

	public static void Subscribe(EventBusType eventType, UnityAction listener)
	{
		UnityEvent thisEvent;

		if (Events.TryGetValue(eventType, out thisEvent))
		{
			thisEvent.AddListener(listener);
		}
		else
		{
			thisEvent = new UnityEvent();
			thisEvent.AddListener(listener);
			Events.Add(eventType, thisEvent);
		}
	}

	public static void UnSubscribe(EventBusType eventType, UnityAction listener)
	{
		UnityEvent thisEvent;

		if (Events.TryGetValue(eventType, out thisEvent))
		{
			thisEvent.RemoveListener(listener);
		}
	}

	public static void Publish(EventBusType eventType)
	{
		UnityEvent thisEvent;
		if (Events.TryGetValue(eventType, out thisEvent))
		{
			thisEvent.Invoke();
		}
	}

	public static void Clear()
	{
		Events.Clear();
	}
}

 

 

 

LoadingSceneManager

씬을 넘어가는 Manager인데 Loading하는 씬을 포함하고 싶어서 변형을 줬다. 오브젝트가 많지 않은 씬이라 넘어갈 때 너무 순식간에 넘어가서 fakeTime을 추가하여 천천히 로딩 프로그레스바가 올라가도록 했다. LoadingSceneManager.Instance.LoadSceneWithFadeEffect("SceneName")으로 로딩씬&씬전환을 사용할 수 있는데, 씬 전환 전에 먼저 FadeOut, In 효과를 준다. Fade 이펙트가 완전히 까맣게 되면 로딩씬으로 넘어가고, 로딩 씬에서 Next Scene을 로드하면서 로딩된 정도에 따라 프로그레스바를 변경시킨다. 로드가 완료되면 다음 씬으로 넘어가면서 또다시  FadeIn/Out 효과를 준다.

public class LoadingSceneManager : SingleTon<LoadingSceneManager>
{
	private const float fakeTime = 5.0f;
	public string nextScene;
	public float fadeTime = 1.0f;
	public GameObject uiPrefab;
	public GameObject uiObj;
	private LoadingUI loadingUi;
	private Image image;

	protected override void Awake()
	{
		base.Awake();
		if (image == null)
		{
			Canvas canvas = gameObject.AddComponent<Canvas>();
			canvas.renderMode = RenderMode.ScreenSpaceOverlay;
			gameObject.AddComponent<CanvasScaler>();
			gameObject.AddComponent<GraphicRaycaster>();

			image = gameObject.AddComponent<Image>();
			image.color = Color.black;
			Color temp = image.color;
			temp.a = 0;
			image.color = temp;

			uiPrefab = Resources.Load("Prefabs\\MazeGame\\LoadingUI") as GameObject;
		}
	}

	public void LoadSceneWithFadeEffect(string nextScene)
	{
		this.nextScene = nextScene;
		StartCoroutine(LoadingSceneWithFadeEffect());
	}

	IEnumerator LoadingSceneWithFadeEffect()
	{
		Color temp = image.color;
		while (temp.a <= 0.99)
		{
			temp.a += Time.deltaTime;
			image.color = temp;
			yield return null;
		}
		temp.a = 1;
		image.color = temp;
		SceneManager.LoadScene("LoadingScene");
		while (temp.a >= 0.01)
		{
			temp.a -= Time.deltaTime;
			image.color = temp;
			yield return null;
		}
		temp.a = 0;
		LoadScene(nextScene);
		uiObj = Instantiate(uiPrefab);
		loadingUi = uiObj.GetComponent<LoadingUI>();
	}

	public void LoadScene(string sceneName)
	{
		nextScene = sceneName;
		StartCoroutine(LoadScene());
	}

	IEnumerator LoadScene()
	{
		AsyncOperation op = SceneManager.LoadSceneAsync(nextScene);
		op.allowSceneActivation = false;
		float timer = 0.0f;
		while (!op.isDone)
		{
			yield return null;
			timer += Time.deltaTime;
			if (op.progress + timer < 0.9f * fakeTime)
			{
				loadingUi.SetProgress(Mathf.Lerp(loadingUi.GetProgress(), (op.progress + timer) / fakeTime, timer / fakeTime));
			}
			else
			{
				loadingUi.SetProgress(Mathf.Lerp(loadingUi.GetProgress(), 1f, timer));
				if (loadingUi.GetProgress() == 1.0f)
				{
					if (nextScene == "GameScene")
						GameManager.Instance.isPlaying = true;
					StartCoroutine(ActiveSceneWithFadeEffect(op));
					yield break;
				}
			}
		}
	}

	IEnumerator ActiveSceneWithFadeEffect(AsyncOperation op)
	{
		Color temp = image.color;
		while (temp.a <= 0.99)
		{
			temp.a += Time.deltaTime;
			image.color = temp;
			yield return null;
		}
		temp.a = 1;
		image.color = temp;
		op.allowSceneActivation = true;
		loadingUi = null;
		while (temp.a >= 0.01)
		{
			temp.a -= Time.deltaTime;
			image.color = temp;
			yield return null;
		}
		temp.a = 0;
	}
}

'게임 개발 > 미니게임' 카테고리의 다른 글

미니게임: Carrot Flight  (0) 2024.11.21
Flappy Brid  (1) 2024.11.12