게임 매니저에서 점수를 관리하도록 변수를 추가한 후 동글 스크립트에 점수가 상승하는 로직을 작성한다. 점수 증가는 HideRoutine 내에 작성한다.
public int score;
manager.score += (int)Mathf.Pow(2, level); // 점수 증가
시작하기에 앞서 OnTriggerStay2D를 사용하기 위해 라인에 태그를 지정해 경계선에 충돌된 것인지를 확인한다. 유니티에서 기본 제공하는 Finish 태그를 지정한다.
void OnTriggerStay2D(Collider2D collision) //동글이 라인과 접촉
{
if(collision.tag == "Finish") //경계선에 접촉해있으면
{
deadTime += Time.deltaTime; //deadTime을 증가시킴
if (deadTime > 2f)
{
// 2초 이상 머무를 시 색을 변경
spriteRenderer.color = new Color(0.9f, 0.2f, 0.2f);
}
if (deadTime > 5f)
{
// 5초 이상 머무를 시 게임 오버
manager.GameOver();
}
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "Finish") //경계선 나가면
{
deadTime = 0; //deadTime 초기화
spriteRenderer.color = Color.white; //색 초기화
}
}
public void GameOver()
{
if (isOver) //이미 게임 오버된 상태면 return
return;
Debug.Log("gg"); //테스트용 출력
isOver = true;
}
Sleeping Mode : 물리연산을 멈추고 쉬는 상태 모드 설정
- 지속적으로 인지를 하기 위해서 Never Sleep으로 설정
이제 게임오버 로직을 구현해보자.
게임오버에서는 아래와 같은 두 가지 과정이 진행된다.
2번 과정이 필요한 이유는 3번에서 아래에 있는 동글이 지워지면 위에 있는 동글이 떨어지면서 새로운 동글로 합쳐질 수도 있기 때문이다.
public void GameOver()
{
if (isOver) //이미 게임 오버된 상태면 return
return;
isOver = true;
StartCoroutine(GameOverRoutine());
}
IEnumerator GameOverRoutine()
{
//1. 장면 안에 활성화 되어있는 모든 동글 가져오기
Dongle[] dongles = GameObject.FindObjectsOfType<Dongle>();
//2. 지우기 전에 모든 동글의 물리효과 비활성화
for (int i = 0; i < dongles.Length; i++)
{
dongles[i].rigid.simulated = false; //물리효과 비화성화
}
//3. 1번 목록을 하나씩 접근해서 지우기
for (int i = 0; i < dongles.Length; i++)
{
dongles[i].Hide(Vector3.up * 100); //게임 플레이 중에는 나올 수 없는 큰값을 전달하여 숨기기
yield return new WaitForSeconds(0.1f); //시간차를 두고 동글이 사라지도록 대기
}
}
FindObjectsOfType : 장면에 올라온 오브젝트들 중 해당하는 컴포넌트를 가진 오브젝트들을 반환
추가적으로 게임 오버가 되면 동글 생성이 더 이상 진행되지 않도록 NextDongle도 수정한다.
void NextDongle()
{
if(isOver)
return;
//생성된 동글을 가져와 new Dongle로 지정
Dongle newDongle = GetDongle();
lastDongle = newDongle;
lastDongle.manager = this; //게임매니저를 넘겨준다.
lastDongle.level = Random.Range(0, maxLevel); //레벨 0 ~ maxLevel-1에서 랜덤하게 생성되도록 구현
lastDongle.gameObject.SetActive(true); //레벨 설정 후 활성화
StartCoroutine(WaitNext()); //대기후 NextDongle을 실행하는 코루틴 시작
}
public void Hide(Vector3 targetPos)
{
isMerge = true; //잠금장치 걸어두기
//흡수 이동을 위해 물리효과 모두 비활성화
rigid.simulated = false; //리지드바디 2D 물리효과 중지
circle.enabled = false; //서클 콜라이더 2D 비활성화
if(targetPos == Vector3.up * 100)
{
EffectPlay();
}
StartCoroutine(HideRoutine(targetPos));
}
IEnumerator HideRoutine(Vector3 targetPos)
{
int frameCount = 0;
while(frameCount < 20)
{
frameCount++;//20프레임 실행되도록
if(targetPos != Vector3.up * 100)
{
transform.position = Vector3.Lerp(transform.position, targetPos, 0.5f);
yield return null; //프레임 단위로 대기
}
else if(targetPos == Vector3.up * 100) //게임매니저가 Hide 시켜준 경우
{
transform.localScale = Vector3.Lerp(transform.localScale, Vector3.zero, 0.2f);
}
}
게임 매니저에서는 targetPos로 vector3.up * 100을 넘겨주기 때문에 Dongle의 Hide와 HideRoutine에서도 이를 확인해서 만약 게임 매니저에서 Hide를 호출한 경우, 즉 게임 오버 시에 실행되는 Hide일 때는 이펙트가 실행되면서 다른 로직으로 Hide가 진행되도록 구현한다.