오늘 목표는 1. 버튼 기능 구현, 2. 효과음 추가, 3. 블루 아카이브 스토리에 사용되는 리소스 적용이었다.

세 가지 목표 전부 달성했고, 몇 가지 수정을 추가로 했다.

 

 

1. 타이틀 글씨 색상 변경

먼저 타이틀 글씨 색깔을 변경했다. 분홍색이라고 생각했는데 다시보니 자주색에 가까웠다. 모모이 이름에 맞는 복숭아색으로 타이틀 색상을 변경했다.

 

 

2. 메인 화면 캐릭터 테두리 수정

어제 누끼를 땄던 위쪽 이미지는 다시보니 배경인 파란색에 동화되어서 테두리가 많이 지저분했다. 심지어 테두리와 내부 일부까지도 파란색이 침범했다. 처음엔 파란색 배경에 사용할 거라서 신경을 안썼는데, 배경을 바꾸니까 눈에 많이 띄어서 테두리 선을 다시 그리고 지우개로 지우는 작업을 많이 반복했다. 하면서 어차피 많이 신경쓰이지도 않을텐데 냅둘까, 고민을 좀 했는데 그래도 더 좋은 유저 경험을 위해서 필요한 작업이라 생각하면서 했다. 약 2~3시간 정도 걸렸다. 그냥 다른 이미지를 찾아볼 걸 그랬나 후회되기도 했다. 브러시로 노가다를 해서 자세히 보면 지저분하긴 하지만, 대충 보면 눈에 띄지는 않으니 그냥 이대로 만족하기로 했다.

 

 

3. 폭발 효과음 변경

폭발 효과음이 조금 찢어지는 느낌도 들고, 게임 효과음이라기 보다는 실제로 뭔가 폭발한 듯한 느낌도 들어서 적절한 다른 효과음으로 변경했다.

 

4. AudioController 수정

기존에는 소리마다 알맞은 크기로 재생했는데옵션에 BGM, 효과음 소리 조절 기능을 넣다보니 기본 소리를 고정해야만 했다. 그래서 재생은 재생만 하고, 볼륨 조절 함수를 다시 따로 만들었다.

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

[System.Serializable]
public class Sound
{
    public string name;
    public AudioClip clip;
}

public class AudioManager : MonoBehaviour
{
    public static AudioManager instance;

    [SerializeField] Sound[] sfx = null;
    [SerializeField] Sound[] bgm = null;

    [SerializeField] AudioSource bgmPlayer = null;
    [SerializeField] AudioSource[] sfxPlayer = null;

    void Start()
    {
        instance = this;
    }

    public float GetBGMVolume()
    {
        return bgmPlayer.volume;
    }

    public void PlayBGM(string p_bgmName)
    {
        for (int i = 0; i < bgm.Length; i++)
        {
            if (p_bgmName == bgm[i].name)
            {
                bgmPlayer.clip = bgm[i].clip;
                bgmPlayer.Play();
            }
        }
    }

    public void StopBGM()
    {
        bgmPlayer.Stop();
    }

    public void PlaySFX(string p_sfxName)
    {
        for (int i = 0; i < sfx.Length; i++)
        {
            if (p_sfxName == sfx[i].name)
            {
                for (int j = 0; j < sfxPlayer.Length; j++)
                {
                    // SFXPlayer에서 재생 중이지 않은 Audio Source를 발견했다면 
                    if (!sfxPlayer[j].isPlaying)
                    {
                        sfxPlayer[j].clip = sfx[i].clip;
                        sfxPlayer[j].Play();
                        return;
                    }
                }
                Debug.Log("모든 오디오 플레이어가 재생중입니다.");
                return;
            }
        }
        Debug.Log(p_sfxName + " 이름의 효과음이 없습니다.");
        return;
    }

    public void SetBGMVolume(float volume)
    {
        bgmPlayer.volume = volume;
    }

    public void SetSFXVolume(float volume)
    {
        for (int i = 0; i < sfxPlayer.Length; i++)
        {
            sfxPlayer[i].volume = volume;
        }
    }
}

 

그리고 오늘 목표로 했던 부분이다.

 

1. 버튼 기능 구현

 

시작하기 버튼을 눌렀을 때 씬을 넘어가야하나 고민을 좀 했는데, 어차피 크기가 크지도 않을 것 같고, 씬을 넘어가면 파괴되지 않도록 설정하는 등 설정하는 게 귀찮을 것 같아서 그냥 하나의 씬으로 진행하기로 생각했다. 시작하기 버튼을 누르면 GameManager에서 메인 화면과 BGM이 Fade Out되며 사라지고 새로운 장면이 나오는 연출을 넣었다.

옵션에는 BGM, 효과음을 조절하는 기능과, FPS를 30과 60중에 선택할 수 있도록 했다. 언어 변경도 엄두에 두고 있는데 우선 한국어만 표기해놨다. 옵션은 블루 아카이브 게임 내의 옵션을 캡쳐해 따와서 사용했다.

기본적으로는 BGM, 효과음을 최대로, FPS는 30으로 설정했다. 옵션을 변경하면 PlayerPrefs를 통해 정보를 저장하고 다시 실행했을 때 불러오도록 했다.

추가로, 버튼을 눌렀을 때 화면이 나와서 버튼이 눌러지지 않게 되지만 혹시 몰라서 게임이 시작되고 나서는 버튼을 눌러도 동작하지 않도록 했다.

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.UI;

public class ButtonManager : MonoBehaviour
{
    GameManager gameManager;
    AudioManager audioManager;
    private void Start()
    {
        audioManager = GameObject.Find("AudioManager").GetComponent<AudioManager>();
        gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
    }
    public void OnClickGameStartBtn()
    {
        if (gameManager.GetGameStarted()) return; // 게임 시작해서 화면 넘어갈 때 버튼 작동하지 않도록 설정
        audioManager.PlaySFX("ButtonStart");
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select(); // 버튼 선택한 뒤에도 하이라이트가 뜨게끔 더미 버튼 선택
        gameManager.GameStart();
    }
    public void OnClickOptionBtn()
    {
        if (gameManager.GetGameStarted()) return; // 게임 시작해서 화면 넘어갈 때 버튼 작동하지 않도록 설정
        audioManager.PlaySFX("ButtonClick");
        GameObject.Find("Canvas/Main/Option").SetActive(true);
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select(); // 버튼 선택한 뒤에도 하이라이트가 뜨게끔 더미 버튼 선택
    }

    public void OnClickOptionQuitBtn()
    {
        if (gameManager.GetGameStarted()) return; // 게임 시작해서 화면 넘어갈 때 버튼 작동하지 않도록 설정
        audioManager.PlaySFX("ButtonCancel");
        GameObject.Find("Canvas/Main/Option").SetActive(false);
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select(); // 버튼 선택한 뒤에도 하이라이트가 뜨게끔 더미 버튼 선택
    }

    public void OnClickGameQuitBtn()
    {
        if (GameObject.Find("GameManager").GetComponent<GameManager>().GetGameStarted()) return;
        StartCoroutine(CoroutineQuit());
    }

    private IEnumerator CoroutineQuit()
    {
        audioManager.PlaySFX("ButtonClick");
        yield return new WaitForSeconds(0.5f);
        Application.Quit();
    }

    public void OnClickFPS30Btn()
    {
        audioManager.PlaySFX("ButtonClick");
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select();
        GameObject.Find("Canvas/Main/Option/OptionWindow/FPS/Circle60/Selected").gameObject.SetActive(false);
        transform.Find("Selected").gameObject.SetActive(true);
        PlayerPrefs.SetInt("FPS", 30);
        Application.targetFrameRate = 30;
    }

    public void OnClickFPS60Btn()
    {
        audioManager.PlaySFX("ButtonClick");
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select();
        GameObject.Find("Canvas/Main/Option/OptionWindow/FPS/Circle30/Selected").gameObject.SetActive(false);
        transform.Find("Selected").gameObject.SetActive(true);
        PlayerPrefs.SetInt("FPS", 60);
        Application.targetFrameRate = 60;
    }

    public void OnClickKoreanBtn()
    {
        audioManager.PlaySFX("ButtonClick");
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select();
        PlayerPrefs.SetString("Language", "Korean");
    }

    public void OnClickJapaneseBtn()
    {
        audioManager.PlaySFX("ButtonClick");
        GameObject.Find("Canvas/Main/BtnTemp").GetComponent<Button>().Select();
        PlayerPrefs.SetString("Language", "Japanese");
    }
}

코드를 적다보니 주석을 별로 사용하지 않은 게 눈에 띄었다. 오랜만에 코드를 적다보니 주석 적는 게 습관이 안된 것 같았다. 그런데 막상 주석을 적으려고 보니 이름만 봐도 뭐하는 함수인지 알 것 같아서 적을 것이 생각보다 없었다.

 

옵션의 소리 조절은 블루 아카이브와 동일하게 슬라이더 바를 활용했는데, SliderManager를 새로 만들어서 사용했다.

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

public class SliderManager : MonoBehaviour
{
    public AudioManager audioManager;
    public void BGMOnValueChanged()
    {
        audioManager.SetBGMVolume(gameObject.GetComponent<Slider>().value);
        PlayerPrefs.SetFloat("BGM", gameObject.GetComponent<Slider>().value);
    }

    public void SFXOnValueChanged()
    {
        audioManager.SetSFXVolume(gameObject.GetComponent<Slider>().value);
        PlayerPrefs.SetFloat("SFX", gameObject.GetComponent<Slider>().value);
    }
}

 

 

2. 효과음 추가

Freesound - Freesound

 

Freesound - Freesound

September 20th, 2022 mehrdad [Guest Blog post by Mehrdad Pourzaki, Lead Movement Communications Specialist at Wikimedia Foundation] Dear Freesounders, The Wikimedia Foundation, the global nonprofit that hosts Wikipedia and other Wikimedia projects, includi

freesound.org

어제는 효과음을 여기서 받았다. 영어권 사이트라서 그런지 뭔가 실사스러운 효과음이 많았다. 효과음마다 저작권 관련 내용도 달라서 사용하기 조금 불편하기도 했다. 어제 사용했던 폭발음도 조금 불만족스러워서 다른 사이트를 찾아봤다.

 

効果音ラボ - フリー、商用無料、報告不用の効果音素材をダウンロード (soundeffect-lab.info)

 

効果音ラボ - 商用無料、報告不用の効果音素材をダウンロード

2400音以上の音源を掲載したフリー効果音サイト。品質にこだわっており、テレビなどのプロの音響現場でも使われています。

soundeffect-lab.info

그러다가 이런 사이트를 발견했다. 일본 사이트인데, 효과음이 굉장히 수준높고 종류도 많았다. 출처를 표기하지 않아도 되었고, 상업적인 이용도 가능했다. 내가 들어본 효과음들도 많이 있었다. 배경 음악도 그렇고 일본에서 무료로 사용 가능한 퀄리티 높은 자료들을 많이 얻는 것 같다. 참 감사한 일이다. 크레딧에 무료로 제공해주신 분들의 링크를 반드시 기재해야겠다. 아무튼, 여기있는 효과음으로 폭발음의 효과도 바꿨고, 버튼을 누르는 효과음도 찾았다. 이후에 사용할만한 효과음도 많이 찾았다.

 

 

3. 블루 아카이브 스토리에 사용되는 리소스 적용

이 화면에서 테두리 및 배경, 중앙 바, 노란색 바 등을 따왔고, 중앙의 글씨는 TextMeshPro를 사용하기로 했다.

추가로, 여기서 오른쪽 위의 2개 버튼도 따와서 적용했다.

이 화면들로 넘어갈 때는 Animation을 활용했다.

 

 

결과적으로 오늘까지 완성된 부분은 이렇다.

오늘 수정한 부분이 나름대로 마음에 든다. 옵션까지 완성했으니 게임의 얼굴이라 할 수 있는 메인화면 부분은 다 된 것 같다. 아직 개선할 부분이 있긴 하지만, 우선 전체적인 기능을 완성하고 나서 하는 게 좋을 것 같다.

 

내일은 스토리 진행에서 AUTO, MENU 버튼 부분을 구현하고 게임개발부 캐릭터들이 나오며 대사를 나누는 장면까지는 나왔으면 좋겠다. 사실 AUTO, MENU 버튼을 만들려면 스토리 진행이 먼저 되어야 할테니, 그 부분을 먼저 구현해야겠다. 스토리가 진행되면서 캐릭터들이 움직이는 모션이나 표정 등의 변화도 있는데, 이런 부분에 관련된 자료가 있는지 먼저 찾아봐야겠다. 그리고 스토리는 로그를 통해 지나간 내용을 다시 볼 수 있어야 할테고, 이어서 볼 수 있게끔 해야할텐데, 어떤 방식으로 구현하고 저장할지 고민해봐야겠다. 스토리가 출력되는 방식도 블루 아카이브 스토리 부분을 유심히 보면서 분석해야겠다.

+ Recent posts