게임 시작 버튼을 만들어서 해당 버튼을 누르면 isLive bool이 true로 바뀌도록 오브젝트와 스크립트를 작성한다.
GameStart라는 빈 오브젝트 생성 후 타이틀을 담당하는 이미지 오브젝트를 추가한다.
이제 시작 버튼을 만들기 위해 버튼 오브젝트를 추가해준다.
버튼을 누르면 게임 시작 되므로 게임 시작 버튼의 OnClick에 GameStart 오브젝트를 드래그 드랍하고 SetActive 함수를 넣어준다.
추가적으로 HUD라는 빈 오브젝트를 생성한후 Exp, Level, Kill, Timer, Health를 HUD안으로 넣어준 후 HUD를 비활성화 시켜준다. 이제 위와 동일하게 게임 시작 버튼을 누를 시 HUD가 다시 활성화 되도록 동일하게 OnClick > HUD 오브젝트 드래그 드랍 > SetActive 함수 호출
이제 isLive가 true로 바뀌도록 스크립트의 Start를 다음과 같이 수정한다.
private void GameStart()
{
health = maxHealth;
uiLevelUp.Select(0); //0번째 무기 버튼 Click이벤트 호출
isLive = true;
}
이제 위와 동일하게 게임 시작 버튼의 OnClick에서 GameManager의 GameStart 함수를 연결시켜준다.
이제 플레이어의 피격 판정을 만들어준다.
이 때 자료형 오류가 발생하는데 Player의 health와 maxHealth의 자료형을 float로 변경해주면 오류가 없어진다.
private void OnCollisionStay2D(Collision2D collision)
{
if (!GameManager.Instance.isLive) //살아있을때만 실행
return;
// 프레임마다 이벤트가 실행되기 때문에 DeltaTime을 곱해주어야 한다.
GameManager.Instance.health -= Time.deltaTime * 10;
if(GameManager.Instance.health < 0)
{
for(int i=2;i<transform.childCount;i++) //자식 오브젝트들을 비활성화
{
//Spawner부터 Hand 모두 비활성화
transform.GetChild(i).gameObject.SetActive(false);
//자식의 transform이 반환되므로 다시 gameobject로 올라가서 비활성화
}
//죽음 애니메이션 실행
anim.SetTrigger("Dead");
}
}
GetChild : 주어진 인덱스의 자식 오브젝트의 트랜스폼을 반환하는 함수
완성된 게임시작 오브젝트를 복사하여 게임결과로 활용한다.
이제 돌아가기 버튼 이벤트를 스크립트로 구현해보자.
using UnityEngine.SceneManagement;
public void GameOver()
{
StartCoroutine(GameOverRoutine());
}
IEnumerator GameOverRoutine()
{
isLive = false; //모든 작업 정지
yield return new WaitForSeconds(0.5f);
uiResult.SetActive(true);
Stop();
}
public void GameRetry()
{
SceneManager.LoadScene(0);//0번째 Scene을 불러온다.
}
SceneManager를 사용하기 위해 SceneManagement 네임스페이스를 추가해주어야 한다.
SecenManager.LoadSene : 이름 혹은 인덱스로 장면(Scene)을 새롭게 부르는 함수
- File > Build Settings 를 통해 이름과 인덱스를 확인할 수 있다.
이제 GameOver 함수를 플레이어 스크립트의 사망 로직에서 호출해준다.
if(GameManager.Instance.health < 0)
{
for(int i=2;i<transform.childCount;i++) //자식 오브젝트들을 비활성화
{
//Spawner부터 Hand 모두 비활성화
transform.GetChild(i).gameObject.SetActive(false);
//자식의 transform이 반환되므로 다시 gameobject로 올라가서 비활성화
}
//죽음 애니메이션 실행
anim.SetTrigger("Dead");
GameManager.Instance.GameOver();
}
마지막으로 돌아가기 버튼의 OnClick에 게임 매니저의 Retry 함수 호출을 연결 시켜준다.
시간이 모두 끝나면 몬스터들을 모두 제거해주기 위해 몬스터 정리 전용 빈 오브젝트 EnemyCleaner를 하나 생성한다.
기존 GameResult 오브젝트에서 Title Over을 복사해 Title Victory를 만들어준다.
이제 생존 여부에 따라 게임 결과가 바뀌어야 하므로, 게임 결과를 보여주는 스크립트 Result를 새롭게 작성해준 후 GameResult 오브젝트의 컴포넌트로 추가한다.
public class Result : MonoBehaviour
{
public GameObject[] titles;
public void Lose()
{
titles[0].SetActive(true);
}
public void Win()
{
titles[1].SetActive(true);
}
}
이후 게임 매너지에서 기존 uiResult의 변수 타입을 Result로 변경해준다. 그 이후 아래의 uiResult를 uiResult.GameObject로 수정해 추가로 발생되는 오류를 해결한다.
IEnumerator GameOverRoutine()
{
isLive = false; //모든 작업 정지
yield return new WaitForSeconds(0.5f);
uiResult.gameObject.SetActive(true);
uiResult.Lose();
Stop();
}
위와 같이 수정 후에 스크립트 수정으로 연결이 끊긴 것들을 인스펙터로 다시 연결해준다.
게임 매니저에 게임 승리 시 적을 정리하는 클리너 변수를 선언해주고 EnemyCleaner 오브젝트를 드래그드랍해서 초기화해준다.
이제 승리 시 로직을 GameManager 스크립트를 아래와 같이 작성해서 구현한다.
public void GameStart()
{
health = maxHealth;
uiLevelUp.Select(0); //0번째 무기 버튼 Click이벤트 호출
Resume();
}
public void GameVictory()
{
StartCoroutine(GameVictoryRoutine());
}
IEnumerator GameVictoryRoutine()
{
isLive = false; //모든 작업 정지
enemyCleaner.SetActive(true);
yield return new WaitForSeconds(0.5f);
uiResult.gameObject.SetActive(true);
uiResult.Win();
Stop();
}
void Update()
{
if (!isLive)
return;
//DeltaTime : 한 프레임에 걸린 시간
gameTime += Time.deltaTime;
//1초마다 Spawn 실행
if (gameTime > maxGameTime)
{
gameTime = maxGameTime;
GameVictory();
}
}
public void GetExp()
{
if (!isLive) // 끝났을때 경험치가 오르는 상황 방지
return;
exp++;
if(exp == nextExp[Mathf.Min(level, nextExp.Length-1)])
{
level++;
exp = 0;
uiLevelUp.Show();
}
}
이제 Title Over와 Title Victory를 비활성화 해준 상태로 GameReulst를 비활성화시킨 후 다시 GameStart를 활성화 시킨다.