본문 바로가기

유니티/확장 프로젝트[3D]

3D 미니 프로젝트 3 ] 스테이지 수정 및 효과음, UI 추가

지난 포스팅에서는 여러 가지 기믹 발판들을 만들어 주었다.

 

그 발판들을 배치하였으니, 이제는 스테이지를 보완하고, 배경음악, 효과음, 그리고 추가 했던 UI에 대한 추가 보강 작업을 진행 해 보도록 하겠다.


아이템 (동전) 추가

점프 맵에서 아이템이 없으면 뭔가 허전하다.

 

어려운 코스에 동전을 배치 해 놓아서, 모든 동전을 모아 클리어를 한 사람은 컨트롤적으로 돋보이게 만들어 줄 수도 있다.

 

동전은 Polygon Starter Pack에 있는 Asset을 사용하였다.

 

silver 코인
gold 코인

은화와 금화를 아이템으로 추가 해 주었다.

 

tag에도 silver, gold를 추가 해 주어, 점수를 추가 할 때 어려움이 없게 만들어 준다.

 

은화는 개당 1점, 금화는 개당 10점의 포인트를 추가 해 주게 된다.

 

모델을 가져 와서, 색을 입힌 뒤, Box Collider를 추가 해 준 다음 Trigger로 설정 해 준다.

 

금화는 좀 더 특별하기에 파티클을 추가 해 준다.

 

파티클 설정

적당히 파티클을 설정 해 준다. (Loop를 해 주어야 계속해서 파티클이 생성된다.)

 

이제, Player에서 아이템에 닿았을 때, Managing과 연계하여 점수를 올려주는 코드를 작성 해 보자.

 

Player.cs

private void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.tag == "SavePoint")
        {
            ReturnPos = other.gameObject.transform.position;
            other.gameObject.SetActive(false); // 세이브 포인트를 먹었으니 비활성화
        }

        if(other.gameObject.tag == "gold")
        {
            managing.addScore(1);
            other.gameObject.SetActive(false);
        }

        if (other.gameObject.tag == "silver")
        {
            managing.addScore(0);
            other.gameObject.SetActive(false);
        }

        if (other.gameObject.tag == "Notice")
        {
            if(other.gameObject.name == "1" && showNotice < 1)
            {
                managing.ShowNotices(1);
                showNotice++;
            }
            else if(other.gameObject.name == "2" && showNotice < 2)
            {
                managing.ShowNotices(2);
                showNotice++;
            }
            else if (other.gameObject.name == "3" && showNotice < 3)
            {
                managing.ShowNotices(3);
                showNotice++;
            }
            else if (other.gameObject.name == "4" && showNotice < 4)
            {
                managing.ShowNotices(4);
                showNotice++;
            }
            else if (other.gameObject.name == "5" && showNotice < 5)
            {
                managing.ShowNotices(5);
                showNotice++;
            }
            else if (other.gameObject.name == "6" && showNotice < 6)
            {
                managing.ShowNotices(6);
                showNotice++;
            }
            else if (other.gameObject.name == "7" && showNotice < 7)
            {
                managing.ShowNotices(7);
                showNotice++;
            }

        }

    }

SavePoint가 있는 이벤트에 추가 해 주면 된다.

 

tag로 물체를 구분 한 다음, Managing에서 점수를 추가 해 주는 함수를 실행한다.

 

 

 

Managing.cs

 public void addScore(int num)
    {
        switch (num)
        {
            case 0: // silver
                score = int.Parse(scoreText.text);
                score++;
                scoreText.text = score.ToString();
                break;
            case 1: // gold
                score = int.Parse(scoreText.text);
                score += 10;
                scoreText.text = score.ToString();
                break;
        }
    }

UI와 연계하여 점수를 추가 해 준다.

 

여기서는 Scene이 변할 때, 파일 같은 곳에 저장하거나 해서 전 스테이지의 점수를 유지하는 것이 필요할 것 같다.

 

아이템을 추가 했으니, 이제 UI를 개선 해 주도록 하자

 


UI 안내문 수정

 

몇 번 플레이를 해 본 결과, 안내문 출력이 너무 빠르게 갱신되어 미처 설명을 읽지 못하였음에도 불구하고 다음 안내문이 출력되는 상황이 발생하였다.

 

즉, 안내 트리거 사이의 간격이 너무 좁았던 것 같다는 생각이 들고, 플레이에 관련이 없는 내용을 출력하는 부분도 있어서 대사 코드를 아래와 같이 수정함과 동시에 트리거의 간격을 늘려 주었다.

 

public void ShowNotices(int num)
    {
        switch (num)
        {
            case 1:
                panel.SetActive(true); // 첫 번째는 내용 변화가 X
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }

                break;
            case 2:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "동전을 먹으면 점수가 올라갑니다!\n 동전을 최대한 많이 먹으면서 골인 지점까지 가면 돼요!";
                break;
            case 3:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "안 보이는 곳에도 동전이 있을 수 있어요!\n 만점을 받기 위해서는 눈썰미가 좋아야겠죠?";
                break;
            case 4:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "방금 먹은 노란색 꼬깔은 세이브 포인트에요!\n 바닥에 떨어지면 세이브 포인트로 복귀한답니다!";
                break;
            case 5:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "전방에 움직이는 파란 색 발판이 보이나요?\n 튕겨 나가지 않게 조심하세요!";
                break;
            case 6:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "앞에 보라색 발판이 보이나요?\n 통! 통! 튀기면서 저 멀리 하늘 위로 올라가 봐요!";
                break;
            case 7:
                panel.SetActive(true);
                if (!isOn) // UI가 사라진 상태에서 UI 생성 시
                {
                    isOn = true;
                }
                else
                {
                    onTime = 0f;
                }
                noticeText.text = "앞에 노란색 발판은 크기가 줄었다가 늘었다가 하네요!\n 크기가 커지기를 기다렸다가 가는 것을 추천해요!";
                break;

        }
    }

트리거 위치(파란색 - 기존, 빨간색 - 수정 후)

간격이 수정되지 않은 부분이 있기는 해도 이 것은 내용을 플레이에 관련이 있게 수정 해 주었다.

 

또한, 밑에 언급되겠지만 6번 트리거에서도 좁은 길에 위치 했던 트리거를 일반 발판을 추가 하여 내용을 조금 더 여유롭게 볼 수 있게 하였다.

 

그 외에도 세이브 포인트와 겹친 트리거는 세이브 포인트 트리거 크기에 맞게 수정 해 주어서, 세이브 포인트를 먹지 않았음에도 세이브 포인트를 먹었다는 문구가 나오는 현상을 수정하였다.


그리고 바닥에 떨어지면 처음 위치(or 세이브 포인트)로 돌아 간다는 부분은 직접 바닥에 떨어졌을 때, 2초 가량 나오게 하는 것으로 수정하였다.

 

떨어졌을 때 나오는 UI

이것 역시 2초 내에 다시 떨어지게 되면 남은 시간이 다시 리필되게 하였다.


배경음악, 효과음 추가

 

이제, 게임에서 빼 놓을 수 없는 배경음악과 효과음을 추가 해 보도록 하자.

 

배경음악은 여기에서, 효과음은 여기에서 무료 에셋을 받아 사용하였다.

 

배경음악은 메인 카메라에 Audiuo Source를 넣어 준 다음, Play on Awake를 통하여 장면이 시작되면 바로 실행되게 하였다.

 

BGM 설정

또한 배경음악은 계속 해서 반복 되어야 하기에 Loop를 체크 해 주었다.


이제는 코인을 먹거나 세이브 포인트를 먹었을 때, 효과음이 출력 되게끔 해 보자.

 

플레이어에게 코드를 하나 더 추가 해 주어, 오디오 클립들을 할당 해 준 다음, 부딪힌 물체의 태그에 맞게 Audio Source의 Clip에 할당 해 주어서 재생을 해 준다.

 

새롭게 작성한 코드는 아래와 같다.

 

PlayerSFX.cs

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

public class PlayerSFX : MonoBehaviour
{
    AudioSource audioS;
    public AudioClip silverSFX;
    public AudioClip goldSFX;
    public AudioClip savePointSFX;
    public AudioClip fallToUnder;


    // Start is called before the first frame update
    void Start()
    {
        audioS = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.tag == "silver")
        {
            audioS.clip = silverSFX;
            audioS.Play();
        }
        else if(other.gameObject.tag == "gold")
        {
            audioS.clip = goldSFX;
            audioS.Play();
        }
        else if (other.gameObject.tag == "SavePoint")
        {
            audioS.clip = savePointSFX;
            audioS.Play();
        }

    }

    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.tag == "under")
        {
            audioS.clip = fallToUnder;
            audioS.Play();
        }
    }
}

또한, 아래로 떨어졌을 때도 효과음이 출력되게끔 하였다.

 


스테이지 밸런싱

 

앞서 코인을 만들었다. 그 코인을 어떻게 배치하느냐에 따라서 난이도가 달라질 수 있다.

 

코인 배치 (기본 경로)

기본적으로 코인은 진행 방향에 맞게 발판 위, 점프 경로에 배치하였다.

 

그렇지만 더 많은 점수를 주는 골드 코인은 사각지대 또는 진행방향에서 자연스럽게 먹지 못하는 경로에 배치해 두어 난이도를 소폭 상승시켰다.

진행 경로에서 이탈된 곳에 골드를 배치하였다.
사각지대에 골드를 배치하였다.

 


앞서 설명을 출력하게 만드는 트리거의 위치를 조정하였다고 하였다.

 

여기서 이전 포스팅에서와 달리 발판에 대한 위치도 조정이 들어가게 되었다.

 

바운스 발판 앞 새로운 발판 추가

우선 좁은 발판이 끝나고 바로 바운스 발판이 나왔던 것과는 달리 일반 발판을 하나 추가 해 두어, 설명을 보면서 숨을 고를 수 있게 하였다.

 

또한, 바운스 발판 위쪽에 투명한 Box Collider를 만들어 두어, 매우 높게 뛰어서 바로 골인 지점에 도착하는 것을 방지하였다.

 

두 갈래길 삭제

또한, 처음에는 노란 발판을 어렵게 만들어 두어 어려운 길로 가느냐, 아니면 돌아서 가지만 일반 발판들로만 이루어진 쪽으로 가느냐를 선택하게 하려 하였지만 노란 색 발판이 생각보다 어렵지 않게 갈 수 있게 만들어 져서 샛길이 의미 없다고 판단하여 삭제하였다.

 

 

골인 지점

 

또한, 파티클과 Box Trigger를 통하여 골인지점을 제작 해 주었다.

particle 설정 중 일부

파티클의 모양을 Edge로 설정 해 주고 Rotation을 해 주었더니 위 사진 처럼 포탈과 같은 형태가 나오게 되었다.

 

다음 포스팅에서는 2 스테이지 Scene을 만들고, Scene 이동, 점수 저장 등의 기능을 구현 해 보도록 하겠다.