배경 음악, 물고기 잡았을 때 효과음, 떨어트렸을 때 효과음. 3개를 준비한다.
그리고 씬에 AudioManager 노드를 만들고 AudioSource 컴포넌트를 추가한다.
AudioSource와 AudioClip 개념은 유니티와 거의 동일하다.
AudioSource 컴포넌트가 붙은 노드는 일종의 MP3 플레이어가 된다.
이번 포스팅에서는 오디오 매니저가 클립 리스트를 가지고 있고
외부에서 오디오 매니저에게 클립의 키 값(음원 이름)을 주고서 재생해달라고 요청하는 방식에 대해 쓰려고 한다.
그리고 재생 요청을 받은 오디오 매니저는 자신이 가지고 있는 오디오 소스로 클립을 재생할 수도 있고
코코스 오디오 엔진에게 클립을 다시 전달해서 엔진이 재생시키도록 할 수 있다.
1. AudioManager
const {ccclass, property} = cc._decorator;
@ccclass('Clip')
class Clip
{
@property(cc.String)
key:string = "";
@property(cc.AudioClip)
audioClip:cc.AudioClip = null;
}
@ccclass
export default class AudioManager extends cc.Component {
private static instance: AudioManager = null;
public static get Instance(){ return this.instance; }
@property(cc.AudioSource)
audioSource:cc.AudioSource;
@property([Clip])
audioClips:Clip[] = [];
onLoad () {
AudioManager.instance = this;
}
}
오디오 매니저는 아주 심플한 형식의 싱글톤 클래스로 만들었다.
그리고 오디오 소스와 오디오 클립 리스트를 Properties 뷰에 노출시킨다.
오디오 클립은 cc.AudioClip이 아닌 커스텀 클래스인 Clip 타입으로 열어놓았다.
audioClips:cc.AudioSource[] 형태가 되면 키 값으로 클립을 재생하는 게 불가능하기 때문에
string 키 + cc.AudioSource 벨류를 합친 Clip 타입을 새로 만든 것이다.
AudioSource 컴포넌트를 붙인 노드에 AudioManager 스크립트도 붙여주고 오디오 클립 리스트를 채워 넣는다.
2. 오디오 매니저의 자체 오디오 소스로 클립 재생
PlaySound(key:String, loop:boolean)
{
this.audioClips.forEach(clip => {
if (clip.key == key)
{
this.audioSource.clip = clip.audioClip;
this.audioSource.loop = loop;
this.audioSource.play();
}
});
}
오디오 매니저에 위와 같은 함수를 작성한다.
전달받은 키 값으로 this.audioClips에서 클립을 찾은 뒤에 매니저가 가지고 있는 오디오 소스로 재생한다.
이 방법은 오디오 소스가 하나기 때문에 동시에 여러 클립을 재생할 수 없다. 동시 재생을 하려면 클립마다 오디오 소스가 필요하다.
클립 재생 요청이 들어올 때마다 오디오 매니저가 오디오 소스가 달린 노드를 생성했다가 클립 재생이 끝나면 다시 제거하는 방법이 있을 수 있다.
그리고 이런 방법은 직접 구현하는 것보다는 코코스 크리에이터 엔진을 이용하는 것이 낫다.
3. 오디오 매니저가 코코스 엔진에게 클립 재생을 요청
PlayBgmSound(key:String, loop:boolean)
{
this.audioClips.forEach(clip => {
if (clip.key == key) {
cc.audioEngine.playMusic(clip.audioClip, loop);
}
});
}
PlayEffectSound(key:String, loop:boolean)
{
this.audioClips.forEach(clip => {
if (clip.key == key) {
cc.audioEngine.playEffect(clip.audioClip, loop);
}
});
}
재생할 오디오 클립은 오디오 매니저가 가지고 있는 것을 그대로 사용하고, 클립 재생은 코코스 엔진에게 맡긴다.
cc.audioEngine.playMusic은 엔진 내부에서도 하나의 오디오 소스를 통해서 클립을 재생하는 함수다.
주로 BGM을 재생할 때 사용한다. 함수 설명에도 Play Background Music 이라고 적혀있다.
cc.audioEngine.playEffect는 한 번 실행될 때마다 새로운 오디오 소스를 생성해서 클립을 재생한다.
playMusic과 playEffect에 대응되는, 클립 재생을 멈추는 함수는 stopMusic과 stopEffect, stopAllEffect가 있다.
cc.audioEngine에 대한 더 자세한 설명은 맨 아래에서.
4. 오디오 매니저 이용하기
start() {
this.InitFishPool();
this.InitStatus();
this.InitRestartButton();
AudioManager.Instance.PlayBgmSound("Bgm", true);
}
BGM 재생은 GameScene 스크립트의 start 함수에서 위와 같이 실행한다.
public RemoveFish(catched:boolean)
{
if (catched)
AudioManager.Instance.PlayEffectSound("CatchFish", false);
else
AudioManager.Instance.PlayEffectSound("DropFish", false);
this.node.active = false;
this.node.stopAllActions();
}
물고기 Catch 사운드와 Drop 사운드는 모두 한 곳에서 재생하도록 한다.
Fish 스크립트의 기존 RemoveFish 함수에 파라미터로 catched:boolean을 추가한다.
이 물고기 삭제가 마우스 클릭으로 실행됐는지, 바닥에 떨어져서 실행됐는지 구분할 수 있다.
var finish = cc.callFunc(() => {
fish.getComponent(Fish).RemoveFish(false);
this.DropFish();
});
그리고 RemoveFish를 실행하는 곳으로 찾아가서 true나 false를 전달하도록 수정한다.
5. 사운드 음소거, 볼륨 조절
pause:boolean;
volume:number;
SetMute(pause:boolean)
{
this.pause = pause;
if (this.pause)
cc.audioEngine.pauseAll();
else
cc.audioEngine.resumeAll();
}
SetVolume(volume:number)
{
this.volume = volume;
cc.audioEngine.setMusicVolume(this.volume);
cc.audioEngine.setEffectsVolume(this.volume);
}
PlayBgmSound(key:String, loop:boolean)
{
if (this.pause)
return;
this.audioClips.forEach(clip => {
if (clip.key == key) {
cc.audioEngine.playMusic(clip.audioClip, loop);
}
});
}
PlayEffectSound(key:String, loop:boolean)
{
if (this.pause)
return;
this.audioClips.forEach(clip => {
if (clip.key == key) {
cc.audioEngine.playEffect(clip.audioClip, loop);
}
});
}
이 프로젝트에는 추가하지 않았지만, 게임 환경설정으로 음소거를 하거나 볼륨을 조절할 수 있게 하려면
위와 같이 음소거 여부, 볼륨에 대한 Setter 함수를 만들어서 사용하면 된다.
puaseAll, resumeAll, setMusicVolume, setEffectVolume 함수들은 현재 재생 중인 모든 오디오 소스에 적용된다.
그리고 이후에 재생되는 오디오 소스에도 적용이 된다.
cc.audioEngine.setVolume(audioID, 0.8);
cc.audioEngine.stop(audioID);
cc.audioEngine은 특정 오디오만 따로 컨트롤할 수 있다. 이때 필요한 건 컨트롤할 오디오의 ID다.
cc.audioEngine의 모든 play 함수들은 오디오를 재생하고, 그 오디오의 ID를 리턴한다.
이를 이용해 배경 음악의 볼륨을 서서히 증가시키는 FadeIn 기능을 구현하면 아래와 같다.
PlayBgmSound(key:String, loop:boolean, fadeIn:boolean)
{
if (this.pause)
return;
var bgmID;
this.audioClips.forEach(clip => {
if (clip.key == key) {
bgmID = cc.audioEngine.playMusic(clip.audioClip, loop);
}
});
var volume = 0;
if (bgmID != null && fadeIn)
{
this.schedule(function(){
volume += 0.1;
cc.audioEngine.setVolume(bgmID, volume);
}, 0.2, 10, 0);
}
}
PlayBgmSound 함수에 FadeIn 효과 적용 여부 파라미터를 추가했고
볼륨을 증가시키는 코드는 간단한 스케쥴러로 작성했다. 스케쥴러의 파라미터 4개는 차례대로
function(실행할 함수), interval(실행 시간 간격), repeat(반복 횟수), delay(첫 시작 딜레이) 를 뜻한다.
'Cocos Creator' 카테고리의 다른 글
cc.tween (0) | 2021.06.09 |
---|---|
[예제 게임] GameScene #5 (스프라이트 로드와 교체) (0) | 2021.06.07 |
[예제 게임] GameScene #3 (게임 일시 정지) (0) | 2021.06.03 |
[예제 게임] GameScene #2 (UI 배치, 클릭 이벤트, 스코어 갱신) (0) | 2021.06.01 |
[예제 게임] GameScene #1 (오브젝트 풀링) (0) | 2021.06.01 |