내배캠 1주차 미니프로젝트(3)

오도독·2024년 4월 17일

내배캠

목록 보기
3/26
post-thumbnail

내일배움캠프 3일차

오늘은 어제 얘기했던대로 카드매칭에 성공 했을 시 카드에 관한 주제가 나오도록 하는 기능과 경고기능에서 시간이 얼마 남지 않았을 때 BGM이 변경 되도록 하는 기능을 추가해줬어요.

카드 매칭 성공

카드를 배열에 넣을때 인덱스 번호랑 카드이름을 맞춰서 넣어줬는데 인덱스 번호와 카드의 주제를 통일 시켜줬어요.

private void CorrectCard(int idx)
{
    
    switch (idx)
    {
        case 0:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "취미!";
            Invoke("DeleteText",1);
            break;
        case 1:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "좋아하는 음식!";
            Invoke("DeleteText", 1);
            break;
        case 2:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "MBTI!";
            Invoke("DeleteText", 1);
            break;
        case 3:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "좋아하는 가수!";
            Invoke("DeleteText", 1);
            break;
        case 4:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "좋아하는 게임!";
            Invoke("DeleteText", 1);
            break;
        case 5:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "인상깊게 봤던 영화!";
            Invoke("DeleteText", 1);
            break;
        case 6:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "본인 사진!";
            Invoke("DeleteText", 1);
            break;
        case 7:
            correctTxt.gameObject.SetActive(true);
            correctTxt.text = "우리의 꿈!";
            Invoke("DeleteText", 1);
            break;

    }
}

private void DeleteText()
{
    correctTxt.gameObject.SetActive(false);
}

카드를 비교하는 함수인 Matched 함수에서 카드의 배열 인덱스를 비교해서 같을 경우 성공으로 구현이 되어 있어서 그 인덱스 값을 받아서 switch문을 이용해 조건을 걸어줬습니다.
카드 맞추기에 성공했을 시 텍스트 오브젝트를 활성화 시켜주고 잠시 뒤에 다시 텍스트가 사라지도록 하는데 SetActive(false)를 써줬더니 텍스트가 안보이더라구요.
그래서 텍스트를 없애 주는 함수를 만들어서 Invoke를 이용해 1초뒤에 텍스트가 사라지도록 해줬습니다.

그런 다음 만든 CorrectCard 함수를 Matched 함수의 카드가 성공했을 시의 조건문 안에 넣어주면

같은 그림을 맞췄을때 사진의 주제가 텍스트로 나왔다가 사라져요.

경고음악 변경기능

시간이 얼마 남지 않았을때 경고를 하기 위해 타이머의 글자 색이 빨개지고 커졌다 작아졌다 하는 애니메이션을 만들어 줬었는데요. 음악도 변경하는 기능을 추가해 봤습니다.


처음에는 기존의 BGM을 종료시키고 새로운 BGM을 재생시켜주는 방식으로 하려 했는데 이렇게 하면 뭔가 부자연스러운 느낌이 들어서 기존의 BGM의 볼륨을 점점 줄이면서 꺼주고 새로운 BGM의 볼륨을 점차 키우면서 켜주는 방식으로 구현하기로 했답니다.

public enum BGM_Type
{
    BGM_Normal = 0,
    BGN_NoTime,

}

///////////////////////////////////////////////////////////////////////////////

   [SerializeField]
   private List<AudioClip> bgmList;

   public void ChangeBGM(BGM_Type newBGM)
   {
       StartCoroutine(ChangeBGMClip(bgmList[(int)newBGM]));
   }

   float current;
   float percent;
   public readonly float changeDuration = 1f;

   IEnumerator ChangeBGMClip(AudioClip newClip)
   {
       current = 0f;
       percent = 0f;

       while (percent < 1)  // 기존의 BGM의 볼륨을 줄여나간다
       {
           current += Time.deltaTime;
           percent = current /  changeDuration;
           audioSource.volume = Mathf.Lerp(1f, 0f, percent);
           yield return null;
       }

       audioSource.clip = newClip;
       audioSource.Play();
       current = 0f;
       percent = 0f;

       while (percent < 1)  // 새로운 BGM의 볼륨을 키워나간다
       {
           current += Time.deltaTime;
           percent = current / changeDuration;
           audioSource.volume = Mathf.Lerp(0f, 1f, percent);
           yield return null;
       }
   }

먼저 enum으로 BGM의 타입을 만들어줬어요
enum 이란 C#에서 사용하는 열거형(“enumeration”의 줄임말) 형식을 가리켜요.
열거형이란 이름이 지정된 상수 집합을 나타내는 값 형식이에요.
enum을 사용하면 일반 상수를 사용하는 것보다 읽기 쉽고, 유지 관리가 쉽고, 안전하다고 해요.

그리고 BGM을 저장하는 리스트를 만들어서 기본상태의 BGM과 경고 상태의 BGM을 넣어줬어요.
코루틴과 lerp 함수를 이용해서 볼륨을 줄여주고 키워주는 기능을 구현했어요.


● 코루틴이란?

유니티 매뉴얼을 보면

사실 잘 모르겠어요.

게임이 실행 됐을 때 프레임마다 Update문이 계속해서 반복실행이 되는데 코루틴을 사용하면 자신이 필요한 순간에만 반복을 할 수 있는 것이라고 이해를 했어요.
유니티는 싱글코어인데 코루틴을 쓰면 싱글쓰레드를 멀티쓰레드 처럼 활용할 수 있게 해줘서 최적화에 도움이 많이 된다는 말도 있네요.

코루틴 사용방법은 다음과 같아요.

IEnumerator (코루틴 함수 이름)() : 코루틴 함수 생성시 타입
StartCoroutine() : 코루틴 실행하기
StopCoroutine() : 코루틴 멈추기
yield : 함수를 지연 실행 시키기
yield return new WaitForSeconds() : 괄호안 해당하는 시간만큼 실제시간 대기
yield return null : 한 프레임 대기


● lerp 함수란?

lerp함수는 숫자 간의 선형보간 함수입니다.
선형 보간법은 시작점과 끝점이 주어졌을때 그 사이에 위치한 값을 구하기 위해 직선거리에 따라 선형적으로 계산하는 방법이라고 해요.

Math.lerp(float a, float b, float c)

위와 같이 사용하는데


a - 시작점
b - 끝점
c - 구하고자 하는 위치


이렇게 값이 들어가요.


볼륨 값이 계속 변해야 하니 deltaTime값을 넣어주고 1초안에 작업을 실행하도록 1로 나누어 주었어요.
그럼 코루틴이 루프를 돌면서 기존의 BGM의 볼륨을 1에서 0까지 1초안에 줄여주고 반대로 새로운 BGM은 키워줘요.
이 코루틴을 GameManger 스크립트의 시간이 얼마남지 않았을 때의 조건문 안에 실행해주면 완성!

마무리

오늘은 음악변경 기능을 구현하면서 Update문 안의 경고 조건문 안에 코루틴을 집어넣었더니 코루틴을 계속 반복실행 시키면서 BGM의 첫 부분만 반복재생이 되어 다다다닥 하는 소리만 들리는 현상이 발생해 처음에는 사운드 문제인가 싶어 꽤 오랬동안 어떻게 해결해야 할지 고민을 했어요.

그러다 코루틴이 계속 반복 실행 된다는 것을 깨닫고 이거를 어떻게 한번만 실행 시킬수 있을까 했는데
음악이 바뀐적이 있는지를 나타내는 bool값을 받아 조건을 거는 걸로 간단하게 해결할 수 있었어요.
이걸 왜 빨리 깨닫지 못했을까요.

역시 Simple is best 구나 하는 하루였습니다.

0개의 댓글