Unity 강의 정리 4-6장: 소코반 게임 만들기 - 게임 매니저, 승리 UI, 최종 빌드🎮

나무·2023년 8월 16일
1

Unity

목록 보기
9/21
post-thumbnail

인프런에 있는 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리하는 글입니다!


1. 게임 매니저와 승리 조건 🎮

게임 매니저는 게임 로직을 관리하고 승리 조건을 판별하는 중앙 제어 시스템이다. 여기에서는 C# 스크립트로 GameManager 클래스를 만든다.

ItemBox 클래스

먼저, 게임의 승리 조건을 판별하기 위해 사용되는 ItemBox 클래스에 isOveraped 변수를 추가한다.

public class ItemBox : MonoBehaviour
{
    public bool isOveraped = false; // 충돌 여부
    private Renderer myRenderer;
    public Color touchColor; 
    private Color originalColor;
    
    // 나머지 코드...
]

GameManager 클래스

다음은 GameManager 클래스다. 이 클래스는 ItemBox 오브젝트의 isOveraped 값을 모니터링하여 모든 상자가 목표 지점에 도달했는지 판단한다.

public class GameManager : MonoBehaviour
{
    public ItemBox[] itemBoxes;
    public bool isGameOver;

    void Start()
    {
        isGameOver = false;
    }

    void Update()
    {
        if(isGameOver == true)
        {
            return;
        }

        int count = 0;
        for(int i = 0; i < 3; i++)
        {
            if(itemBoxes[i].isOveraped == true)
            {
                count++;
            }
        }

        if(count >= 3)
        {
            Debug.Log("게임 승리!");
            isGameOver = true;
        }
    }
}

2. 승리 UI 만들기 🏆

승리 조건을 만족하면 플레이어에게 승리 메시지를 표시해야 한다. 아래의 단계에서는 승리 UI를 만드는 방법을 설명한다.

UI 추가하기

  1. Unity의 Hierarchy 창에서 마우스 오른쪽 버튼을 클릭하여 "Create Empty"를 선택하고 "Canvas"라는 이름으로 바꾼다.
  2. "Canvas" 오브젝트를 선택하고, Inspector 창에서 "UI -> Text"를 선택하여 텍스트 UI 요소를 추가한다.

텍스트 UI 편집

  1. 텍스트 UI 요소를 선택하고 Inspector 창에서 "Rect Transform"을 사용하여 크기와 위치를 조정한다.
  2. "Text" 컴포넌트로 텍스트 내용, 글꼴, 크기, 색상 등을 설정한다.

UI가 게임 승리시에만 나타나도록 구현

GameManager 클래스의 Update 메서드를 수정하여 승리 조건이 충족되면 승리 UI를 활성화하도록 한다.

public class GameManager : MonoBehaviour
{
    public GameObject winUI; // 승리 UI 참조

    // 나머지 코드...

    void Update()
    {
        // 기존 코드...

        if(count >= 3)
        {
            Debug.Log("게임 승리!");
            isGameOver = true;
            winUI.SetActive(true); // 승리 UI 활성화
        }
    }
}

위의 코드와 함께, Unity Editor에서 "Win UI" 오브젝트를 GameManager의 "Win UI" 필드에 드래그 앤 드롭해야 한다.

이렇게 하면, 게임 매니저와 승리 조건의 구현이 완료되고, 승리 UI가 게임 승리 시 활성화된다.


3. 스페이스바 누르면 게임을 재시작 🔄

사용자가 스페이스바를 눌렀을 때 게임을 재시작할 수 있게 구현하기

SceneManagement 네임스페이스 추가하기 📚

우선, UnityEngine.SceneManagement 네임스페이스를 추가해야 한다. 이 네임스페이스 안에는 장면(Scene) 관리와 관련된 여러 클래스와 메서드가 포함되어 있다. 여기서는 장면을 로드하는 SceneManager.LoadScene 메서드를 사용한다.

using UnityEngine;
using UnityEngine.SceneManagement; // 이 부분은 Scene 관리를 위한 네임스페이스

public class GameManager : MonoBehaviour
{
    // ... 다른 변수 선언

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) // 스페이스바를 눌렀을 때의 이벤트 감지
        {
            SceneManager.LoadScene(0); // 현재 장면(인덱스 0)을 다시 로드
        }

        // ... 나머지 코드
    }
}

이렇게 하면 스페이스바를 눌렀을 때, 현재 장면이 다시 로드되어 게임이 재시작된다. 재시작 시 모든 오브젝트와 변수가 초기 상태로 리셋되므로 게임을 처음부터 다시 시작할 수 있다.


4. 배경 음악 설정 🎵

게임에 배경 음악을 추가하려면, 오디오 소스 컴포넌트를 사용하고 원하는 음악 파일을 설정해야 한다.

오디오 소스 추가하기

  1. Hierarchy 창에서 마우스 오른쪽 버튼을 클릭하고 "Create Empty"를 선택한다.
  2. 새 오브젝트를 "BGM"이라는 이름으로 바꾼다.
  3. "BGM" 오브젝트를 선택하고, Inspector 창에서 "Add Component -> Audio Source"를 선택한다.

음악 파일 설정 및 옵션 조정

  1. 오디오 소스 컴포넌트에서 "AudioClip" 필드를 클릭하고 원하는 음악 파일을 선택한다.
  2. "Play On Awake" 옵션을 체크하여 게임 시작시 음악이 자동으로 재생되도록 한다.
  3. "Loop" 옵션을 체크하여 음악이 반복 재생되도록 한다.

이렇게 하면 배경 음악이 게임 시작시 자동으로 재생되며, 무한 반복된다.


5. 게임이 끝나면 플레이어 오브젝트를 움직이지 못하도록 하기 🚫

이 섹션에서는 게임이 끝났을 때 플레이어의 움직임을 어떻게 제어하는지에 대해 설명한다.

Player.cs 코드 설명 📝

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

public class Player : MonoBehaviour
{
    public GameManager gameManager; // GameManager의 참조를 위해 변수를 선언. 게임 상태를 확인하기 위해 사용한다.

    // ... 다른 변수 선언

    void Update()
    {
        if (gameManager.isGameOver == true) // GameManager의 `isGameOver` 변수가 true일 경우, 플레이어의 움직임 코드 실행을 중단한다.
        {
            return; // 이후 코드 실행을 중단, 움직임 제어 안 함
        }

        // ... 플레이어 움직임 처리 코드
    }
}

이렇게 하면 게임이 끝나면 플레이어의 움직임을 제어하지 않아 움직이지 않게 된다.


6. 최종 빌드 (Build and Run) 🚀

게임 개발이 완료되면, 마지막 단계는 빌드(Build)와 실행(Run)이다. 이 과정은 Unity에서 쉽게 수행할 수 있다.

빌드와 실행 과정 🛠️

  1. File 메뉴로 이동하고, Build Settings를 선택한다.
  2. Platform을 선택하여 타겟 플랫폼(예: Windows, macOS, Android 등)을 정한다.
  3. Add Open Scenes를 클릭하여 현재 장면을 빌드 목록에 추가한다.
  4. Build And Run 버튼을 클릭한다.

이 과정을 통해 선택된 플랫폼에 맞는 실행 파일이 생성되며, 자동으로 게임이 실행된다. 빌드 설정에서 다양한 옵션을 변경하여 게임의 해상도, 아이콘 등을 설정할 수도 있다.


정리📝

전체 코드
GameManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public GameObject winUI; // 게임 승리시 활성화할 UI 게임 오브젝트
    public ItemBox[] itemBoxes; // ItemBox 배열 선언
    public Boolean isGameover = false; // 게임 오버 상태 변수
    void Start()
    {
        isGameover = false; // 게임 오버 상태를 게임 중으로 변경
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //SceneManager.LoadScene(0); // 씬의 순번으로 로드
            SceneManager.LoadScene("Sokovan/Scenes/Main"); // 씬의 이름으로 로드
        }

        if (isGameover) return; // 게임 오버 상태라면 업데이트를 진행하지 않음
        
        int count = 0; // ItemBox 중에서 충돌한 ItemBox의 개수를 저장할 변수
        for(int i = 0; i < 3; i++) // 3개의 ItemBox를 모두 확인
        {
            if (itemBoxes[i].isOveraped) count++; // 만약 ItemBox가 충돌했다면 count를 1 증가
        }

        if(count >= 3) // 만약 충돌한 ItemBox의 개수가 3개 이상이라면
        {
            Debug.Log("게임 승리"); 
            winUI.SetActive(true); // 게임 승리 UI 활성화
            isGameover = true; // 게임 오버 상태를 게임 승리로 변경
        }
    }
}
ItemBox.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemBox : MonoBehaviour
{
    public bool isOveraped = false; // 아이템 박스와 충돌했는지 여부를 저장할 변수

    private Renderer myRenderer; // ItemBox의 Renderer 컴포넌트를 참조
    public Color touchColor;     // 충돌시 바뀔 색을 참조할 변수

    void Start()
    {
        myRenderer = GetComponent<Renderer>(); // Renderer 컴포넌트를 가져옴
    }

    void Update()
    {
    }

    // 트리거 콜라이더와 충돌했을 때 자동으로 실행
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "EndPoint")            // 태그가 "EndPoint"일 경우
        {
            isOveraped = true;                  // isOveraped를 true로 변경
            myRenderer.material.color = touchColor; // 색을 touchColor로 변경
        }
    }

    // 트리거 콜라이더와 충돌이 끝났을 때 자동으로 실행
    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "EndPoint")            // 태그가 "EndPoint"일 경우
        {
            isOveraped = false;                 // isOveraped를 false로 변경
            myRenderer.material.color = Color.white; // 색을 흰색으로 변경
        }
    }

    // 트리거 콜라이더와 충돌하고 있는 동안 계속 실행
    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "EndPoint")            // 태그가 "EndPoint"일 경우
        {
            isOveraped = true;                  // isOveraped를 true로 변경
            myRenderer.material.color = touchColor; // 색을 touchColor로 변경
        }
    }
}
Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public GameManager gameManager; // 게임 매니저

    // 플레이어의 이동 속도
    public float speed = 10f;

    // 플레이어의 리지드바디 컴포넌트
    Rigidbody playerRigidbody;

    // 게임이 시작될 때 한 번만 호출되는 함수 -> 초기화
    void Start()
    {
        // GetComponent<타입>() : 타입에 해당하는 컴포넌트를 찾아서 반환
        playerRigidbody = GetComponent<Rigidbody>();
    }

    // 매 프레임마다 호출되는 함수 -> 유저 입력을 받아서 처리
    void Update()
    {
        if (gameManager.isGameover) return; // 게임 오버 상태라면 업데이트를 진행하지 않음

        // GetAxis() : 키보드 입력을 받아서 -1 ~ 1 사이의 값을 반환
        float inpuitX = Input.GetAxis("Horizontal"); // 조이스틱 대응 가능
        float inputZ = Input.GetAxis("Vertical"); 
        float fallSpeed = playerRigidbody.velocity.y; // 중력에 의해 떨어지는 속도를 유지시키기 위해

        // 방향 * 속도 = 속도 벡터
        Vector3 velocity = new Vector3(inpuitX, 0f, inputZ);

        velocity = velocity * speed; // 방향 * 속도
        velocity.y = fallSpeed; // 중력에 의해 떨어지는 속도를 유지시키기 위해

        // 리지드바디의 속도를 velocity로 변경
        playerRigidbody.velocity = velocity;
    }
}

profile
개인 공부를 정리함니다

0개의 댓글