[Unity][2D-Game] Suika-Game (5)

suhan0304·2023년 11월 18일
0

유니티 - Suika Game

목록 보기
5/8
post-thumbnail

Review

  • Particle 시스템 오브젝트로 이펙트 시스템을 구현하였다.
  • 동글을 생성할 때 파티클 오브젝트도 자식 오브젝트로 같이 생성해주었다.
  • 동글이 합쳐질 때 합쳐지는 동글이 가지고 있는 파티클 오브젝트가 플레이되도록 구현했다.

강의영상 (5) - 게임오버 구현하기


개발

점수 추가

게임 매니저에서 점수를 관리하도록 변수를 추가한 후 동글 스크립트에 점수가 상승하는 로직을 작성한다. 점수 증가는 HideRoutine 내에 작성한다.

GameManager.cs

public int score;

Dongle.cs

manager.score += (int)Mathf.Pow(2, level); // 점수 증가

경계선 이벤트

시작하기에 앞서 OnTriggerStay2D를 사용하기 위해 라인에 태그를 지정해 경계선에 충돌된 것인지를 확인한다. 유니티에서 기본 제공하는 Finish 태그를 지정한다.

Dongle.cs

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; //색 초기화
    }
}

Manager.cs

public void GameOver()
{
    if (isOver) //이미 게임 오버된 상태면 return
        return;
    Debug.Log("gg"); //테스트용 출력
    isOver = true;
}

Sleeping Mode : 물리연산을 멈추고 쉬는 상태 모드 설정

  • 지속적으로 인지를 하기 위해서 Never Sleep으로 설정

게임 오버

이제 게임오버 로직을 구현해보자.
게임오버에서는 아래와 같은 두 가지 과정이 진행된다.

  1. 장면 안에 활성화 되어있는 모든 동글 가져오기
  2. 모든 동글들의 물리효과 비활성화
  3. 1번 목록을 하나씩 접근해서 지우기

2번 과정이 필요한 이유는 3번에서 아래에 있는 동글이 지워지면 위에 있는 동글이 떨어지면서 새로운 동글로 합쳐질 수도 있기 때문이다.

GameManager.cs

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을 실행하는 코루틴 시작
}

Dongle.cs

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가 진행되도록 구현한다.


결과물

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글