본문 바로가기
개발일지/게임개발

[유니티 게임 개발] 동방을 걷다 프로젝트 13 - BGM 변화 기능 2024 05 30(AM 00:30)

by 라이티아 2024. 5. 30.

현재 듣고 있는곡

열이상 - 이요와 .ver - remix to Aliey

열이상 특유의 음감을 새롭게 해석한 좋은 리믹스다

 

 

지금 BGM을 메인 1곳에서만 사용하고 있는데, 이제 각 장소에 맞게 BGM을 변경해주는 기능을 넣어주려 한다

 

우선 하쿠레이 신사 진입시 BGM을 구현해 주려한다

 

사용하는 음악은 파츄리의 데모인

Mystical Dream ~ Snow or Cherry Petal의 remix버전을 사용하려 한다

잔잔하니 신사의 분위기와 잘 맞아 떨어진다

 

public AudioSource Sound;
    public AudioClip Main;
    public string sound_name;

    public void Playsound(string n){
        sound_name = n;
        switch(sound_name){
            case "Main":
                Sound.clip = Main;
                break;
        }
        Sound.Play();
    }

    void Update(){
        if(!Sound.isPlaying && C.isCameraActive == 1){
            Sound.Stop();
            Playsound("Main");
        }
    }

BGM재생 스크립트이다

 

매커니즘이 Update에 묶여 있는데, 이를 다른 스크립트에서 호출하는 형태로 변경해보려 한다

public void Playsound(string n){
        Sound.Stop();
        sound_name = n;
        switch(sound_name){
            case "Main":
                Sound.clip = Main;
                break;
            case "Hakurei":
                Sound.clip = Hakurei;
                break;
        }
        Sound.Play();
    }

우선 음악을 추가해서 할당해준다

 

그리고 UI매니저에서 상황에 맞게 BGM을 재생하도록 하려 한다

if(player.ismove == true && C.isCameraActive == 1){
            World_UI.SetActive(true);
            Shop_UI.SetActive(false);
            Fight_UI.SetActive(false);
            Hakurei_UI.SetActive(false);
            txtmanager.SetActive(false);
            Marisa_UI.SetActive(false);
        }
        else if(player.ismove == false && C.isCameraActive == 2){
            World_UI.SetActive(false);
            Shop_UI.SetActive(true);
            Fight_UI.SetActive(false);
            Hakurei_UI.SetActive(false);
            txtmanager.SetActive(false);
            Marisa_UI.SetActive(false);
        }

UI매니저는 이런 형태를 가지고 있고

1일때는 메인, 2일때는 하쿠레이 신사 배경음악을 재생해야 한다

하지만, 여기에 직접 Sound.play()를 해버리면 계속해서 갱신되기에 if문을 사용해서 바꿔주도록 하자

 

여기서 사용되는 함수가 isplaying이다

 

재생이 되고 있는지를 확인하는 함수이다

 

if(player.ismove == true && C.isCameraActive == 1){
            if(!BGMmanager.Instance.Sound.isPlaying && BGMmanager.Instance.sound_name != "Main")
                BGMmanager.Instance.Playsound("Main");
            World_UI.SetActive(true);
            Shop_UI.SetActive(false);
            Fight_UI.SetActive(false);
            Hakurei_UI.SetActive(false);
            txtmanager.SetActive(false);
            Marisa_UI.SetActive(false);
        }
        else if(player.ismove == false && C.isCameraActive == 2){
            if(!BGMmanager.Instance.Sound.isPlaying && BGMmanager.Instance.sound_name != "Hakurei")
                BGMmanager.Instance.Playsound("Hakurei");
            World_UI.SetActive(false);
            Shop_UI.SetActive(true);
            Fight_UI.SetActive(false);
            Hakurei_UI.SetActive(false);
            txtmanager.SetActive(false);
            Marisa_UI.SetActive(false);
        }

이를 활용하여 이런 매커니즘을 짜준다

 

현재 BGM이 재생되고 있지 않고, 재생되야 하는 BGM의 이름이 맞는지를 검사하는 방식이다

 

.....

 

뭔가 매커니즘이 이상하다 수정해야할 것 같다

실행했더니 오류가 나온다

Sound.Stop();

이 호출될때, 시작 직후는 BGM이 없기 때문에 NULL이 되버리는 문제가 있는 것 같다

 

if(Sound.isPlaying)
            Sound.Stop();

if문을 하나 걸치게 한다

 

도 안되서 그냥 시작할때 강제로 메인 BGM을 실행하도록 만들었다

void Start() {
        BGMmanager.Instance.Playsound("Main");
    }

 

 

NullReferenceException: Object reference not set to an instance of an object
BGMmanager.Playsound (System.String n) (at Assets/script/Sound/BGMmanager.cs:37)
UI_manager.Start () (at Assets/script/UI_manager.cs:23)


??????

왜 오류???

 

싱글톤으로 구현을 해두니 오디오 클립이 증발한다....

 

싱글톤을 죽입시다 싱글톤은 우리의 원수

 

private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);

            // AudioSource가 null일 경우 추가
            if (Sound == null)
            {
                Sound = gameObject.AddComponent<AudioSource>();
            }
        }
        else if (Instance != this)
        {
            Destroy(gameObject);
        }
    }

유사 싱글톤을 사용해 주기로 했다

if (Sound == null)
            {
                Sound = gameObject.AddComponent<AudioSource>();
            }

핵심은 이 부분이다

Sound가 NULL이 아니게 해주는 역할을 한다

 

그후 UI매니저에서

if((!BGMmanager.Instance.Sound.isPlaying || BGMmanager.Instance.sound_name != "Main") && BGMmanager.Instance != null)
                BGMmanager.Instance.Playsound("Main");

이런 끔찍한 조건문을 걸면 된다

조건문을 해석하면

((브금 재생중이 아니다 or 브금 이름이 main이 아니다) and 브금 매니저가 NULL 이 아니다)
가 된다

 

이상없이 작동되는 것을 알 수 있다