[Unity] T-rex Run (크롬 공룡 게임) 만들기 (4) - 게임 시작, 게임 오버

Kim Yuhyeon·2023년 4월 21일
0

게임개발

목록 보기
93/135
post-thumbnail
post-custom-banner

게임 시작, 게임 오버


UI

  • 시작 안내 문구

  • 게임 오버 & 다시하기 버튼

DinoGameManager.cs

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

public class DinoGameManager : MonoBehaviour
{
    
    #region instance
    public static DinoGameManager instance;
    private void Awake()
    {
        if (instance != null)
        {
            Destroy(gameObject);
            return;
        }

        instance = this;
    }
    #endregion

    public float gameSpeed = 1;
    public bool isPlay = false;
    public delegate void OnPlay(bool isPlay);
    public OnPlay onPlay;

    [@SerializeField] private GameObject startText;
    [@SerializeField] private GameObject retryUI;
    [@SerializeField] private GameObject scoreUI;
    
    private void Update()
    {
        if (!isPlay && Input.GetKeyDown(KeyCode.Space)) // spacebar 누르면 
        {
            Play();
        }
    }
    public void Play()
    {
        
        // 게임 시작 안내 문구 비활성화
        if (startText.activeSelf) 
            startText.SetActive(false);
        
        // 다시하기 UI 비활성화
        if (retryUI.activeSelf)
            retryUI.SetActive(false);
        
        // 점수 UI 활성화
        if (!scoreUI.activeSelf)
            scoreUI.SetActive(true);
        
        isPlay = true;
        onPlay.Invoke(isPlay);
    }

    public void GameOver()
    {
        retryUI.SetActive(true);
        isPlay = false;
        onPlay.Invoke(isPlay);
    }

}
  • 싱글톤 패턴을 사용하여, 한 게임 내에서 하나의 인스턴스만 존재하도록 보장합니다.
  • 변수

    • gameSpeed : 게임의 속도를 제어하는데 사용
    • isPlay : 게임이 현재 실행 중인지 여부
    • onPlay : 게임 실행/정지 이벤트를 처리하기 위해 사용되는 델리게이트
  • 흐름

    • Awake()

      • 이미 인스턴스가 존재하면 게임 오브젝트를 파괴하고, 그렇지 않으면 인스턴스를 할당합니다.
    • Update()

      • 게임이 실행 중이 아니면 spacebar 키를 눌렀을 때 Play() 메서드를 호출하여 게임을 시작합니다.
    • Play()

      • 게임 시작 안내 문구를 숨기고,
      • 다시하기 UI를 숨기고,
      • 점수 UI를 활성화한 후,
      • isPlay를 true로 설정하고 onPlay 이벤트를 호출합니다.
    • GameOver()

      • 게임 오버 시 다시하기 UI를 표시하고,
      • isPlay를 false로 설정하고 onPlay 이벤트를 호출합니다.

애니메이션 컨트롤러

  • Idle : 눈 깜빡이는 애니메이션
  • Run : 달리는 애니메이션
  • Jump : 죽는 애니메이션
  • Die : 죽는 애니메이션

< Transitions >

  • Idle -> Run : run = true
  • Idle -> Jump : jump = true
  • Run -> Jump : jump = true
  • Run -> Die : die = true
  • Jump -> Run : jump = false
  • Jump -> Die : die = true
  • Die -> Idle : die = false

DinoPlayerController.cs

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

public class DinoPlayerController : MonoBehaviour
{
    private Animator animator;
    private bool isJump = false;
    private bool isTop = false;
    public float jumpHeight = 0;
    public float jumpSpeed = 0;

    private Vector2 startPosition;
    void Start()
    {
        
        startPosition = transform.position;
        animator = GetComponent<Animator>();
    }
    void Update()
    {
        if (DinoGameManager.instance.isPlay)
        {
            animator.SetBool("die", false);
            // 달리는 애니메이션으로 설정하기
            animator.SetBool("run", true);
        }
        else
        {
            animator.SetBool("run", false);
        }

        // 점프 애니메이션으로 설정하기
        if (Input.GetKeyDown(KeyCode.Space) && DinoGameManager.instance.isPlay)
        {
            animator.SetBool("run", false);
            animator.SetBool("jump", true);
            isJump = true;
        }
        else if (transform.position.y <= startPosition.y && isJump)
        {
            isJump = false;
            isTop = false;
            transform.position = startPosition;

            // 땅에 착지했을 경우
            if (transform.position.y == startPosition.y)
            {
                animator.SetBool("jump", false);
                animator.SetBool("run", true);
            }
        }

        if (isJump)
        {
            if (transform.position.y <= jumpHeight - 0.1f && !isTop)
            {
                transform.position = Vector2.Lerp(transform.position,
                    new Vector2(transform.position.x, jumpHeight), jumpSpeed * Time.deltaTime);
            }
            else
            {
                isTop = true;
            }

            if (transform.position.y > startPosition.y && isTop)
            {
                transform.position = Vector2.MoveTowards(transform.position,
                    startPosition, jumpSpeed * Time.deltaTime);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D col)
    {
        if (col.CompareTag("Mob"))
        {
            DinoGameManager.instance.GameOver();
            animator.SetBool("die", true);
        }
    }
}
  • 변경된 부분
    • Update()
      • DinoGameManager 스크립트의 isPlay 변수를 이용하여 게임이 실행 중인지 확인합니다.
      • isPlay 변수가 true 일 때는 달리기 애니메이션을 재생하고, false 일 때는 달리기 애니메이션을 멈춥니다.
      • 스페이스바를 누르면 점프 애니메이션을 실행합니다.
    • OnTriggerEnter2D()
      • 트리거 충돌이 발생하면 GameOver() 함수를 호출하여 게임 오버 처리를 합니다.
      • 장애물(Mob)과 닿으면 게임 오버되고 죽는 애니메이션을 재생합니다.

CactusRespawnManager.cs

    private void Start()
    {
        DinoGameManager.instance.onPlay += PlayGame;

    }

    void PlayGame(bool isPlay)
    {
        if (isPlay)
        {
            // 시작 전 장애물 비화성화
            for (int i = 0; i < cactusPool.Count; i++)
            {
                if (cactusPool[i].activeSelf)
                        cactusPool[i].SetActive(false);
            }
            
            StartCoroutine(CreateCactus());
        }
        else
            StopAllCoroutines();
    }
  • 변경된 부분

    • Start()

      • DinoGameManager 클래스의 onPlay 이벤트에 PlayGame 함수를 등록합니다.
    • PlayGame()

      • 시작 전 cactusPool에 존재하는 모든 선인장 오브젝트를 비활성화하고 CreateCactus 코루틴을 실행합니다.

그 외

  • DinoGroundScroller, CactusBase 클래스에도 DinoGameManager 인스턴스의 isPlay가 참일 경우 조건문을 추가하였다.

결과

post-custom-banner

2개의 댓글

comment-user-thumbnail
2023년 4월 21일

공룡이 귀여워요

1개의 답글