대부분의 Wwise SDK 함수는 AkSoundEngine
클래스를 통해 Unity에서 사용할 수 있습니다. C++의 네임스페이스 AK::SoundEngine
, AK::MusicEngine
등을 대체한다고 생각하면 됩니다. 원본 SDK와 비교하여 API 바인딩에서 변경한 내용은 API 제한 사항 을 참고하세요. 더욱 복잡한 상황의 경우 코드에서 Wwise 함수를 호출해야 합니다. API에서 모든 함수 안에 있는 GameObjectID
는 Unity GameObject 개념으로 대체됩니다. AkGameObj 컴포넌트를 수동으로 추가지 않은 경우 런타임에서 자동으로 해당 GameObject에 추가됩니다.
Event와 Bank에 문자열이 아닌 숫자 ID 사용하기
네이티브 Wwise API에서는 문자열이나 ID를 사용하여 Wwise 프로젝트에서 이벤트나 명명된 오브젝트를 트리거할 수 있습니다. Wwise_IDs.h
파일을 Wwise_IDs.cs
로 변경하면 C::에서도 그렇게 할 수 있습니다. Assets > Wwise > Convert Wwise SoundBank IDs를 클릭하세요. 이 작업을 위해서는 Python(파이썬)이 설치되어 있어야 합니다.
Wwise에 MIDI 전송하기
AkMIDIPostArray
클래스의 AkMIDIPost
멤버를 채워 넣거나 다음 메소드를 호출하면 Wwise에 MIDI를 전송할 수 있습니다.
다음은 사운드 엔진에 MIDI 메시지를 전송하는 기본 스크립트입니다.
public class MyMIDIBehaviour : UnityEngine.MonoBehaviour
{
private void Start()
{
AkMIDIPostArray MIDIPostArrayBuffer = new AkMIDIPostArray(6);
AkMIDIPost midiEvent = new AkMIDIPost();
midiEvent.byType = AkMIDIEventTypes.NOTE_ON;
midiEvent.byChan = 0;
midiEvent.byOnOffNote = 56;
midiEvent.byVelocity = 127;
midiEvent.uOffset = 0;
MIDIPostArrayBuffer[0] = midiEvent;
midiEvent.byOnOffNote = 60;
MIDIPostArrayBuffer[1] = midiEvent;
midiEvent.byOnOffNote = 64;
MIDIPostArrayBuffer[2] = midiEvent;
midiEvent.byType = AkMIDIEventTypes.NOTE_OFF;
midiEvent.byOnOffNote = 56;
midiEvent.byVelocity = 0;
midiEvent.uOffset = 48000 * 8;
MIDIPostArrayBuffer[3] = midiEvent;
midiEvent.byOnOffNote = 60;
MIDIPostArrayBuffer[4] = midiEvent;
midiEvent.byOnOffNote = 64;
MIDIPostArrayBuffer[5] = midiEvent;
SynthEvent.PostMIDI(gameObject, MIDIPostArrayBuffer);
}
}
Unity에서 오프라인 렌더링하기
Unity 통합은 Wwise SDK 안에서 오프라인 렌더링하기 기능을 제공하여 오디오 샘플을 가져올 수 있는 방법을 간소화해줍니다.
warning | 주의: Care must be taken to ensure that only the asynchronous AkUnitySoundEngine.LoadBank and AkUnitySoundEngine.UnloadBank APIs are used from the main thread when offline rendering is enabled. 더 자세한 설명은 오디오 렌더링 커스텀 예약을 참고해 주세요. |
AkUnitySoundEngine.StartDeviceCapture
sets up a specific output audio device for capture so that the number of available samples can be determined by calling AkUnitySoundEngine.UpdateCaptureSampleCount
and the audio samples can be retrieved by calling AkUnitySoundEngine.GetCaptureSamples
.
다음 예시는 Unity의 스크린 캡처 기능과 함께 Unity 통합을 사용하여 오프라인 오디오 렌더링을 실행하는 방법을 설명해줍니다. 이 기능이 구현됨으로써 다중 조작 후반 처리 단계를 쉽게 실행하여 캡처된 오디오 샘플과 비디오 프레임을 동영상으로 조합할 수 있게 되었습니다.
public abstract class WwiseOfflineRenderer : UnityEngine.MonoBehaviour
{
public bool IsOfflineRendering { get; set; }
public bool StartWithOfflineRenderingEnabled = false;
private bool IsCurrentlyOfflineRendering = false;
public float FrameRate = 25.0f;
protected ulong OutputDeviceId = 0;
public abstract string GetUniqueScreenshotFileName(int frameCount);
public abstract void ProcessAudioSamples(float[] buffer);
protected void Start()
{
OutputDeviceId = AkUnitySoundEngine.GetOutputID(AkUnitySoundEngine.AK_INVALID_UNIQUE_ID, 0);
if (StartWithOfflineRenderingEnabled)
{
IsOfflineRendering = true;
Update();
}
}
private void LogAudioFormatInfo()
{
var sampleRate = AkUnitySoundEngine.GetSampleRate();
var channelConfig = new AkChannelConfig();
var audioSinkCapabilities = new Ak3DAudioSinkCapabilities();
AkUnitySoundEngine.GetOutputDeviceConfiguration(OutputDeviceId, channelConfig, audioSinkCapabilities);
UnityEngine.Debug.LogFormat("Sample Rate: {0}, Channels: {1}", sampleRate, channelConfig.uNumChannels);
}
protected void Update()
{
if (IsOfflineRendering != IsCurrentlyOfflineRendering)
{
IsCurrentlyOfflineRendering = IsOfflineRendering;
if (IsOfflineRendering)
{
#if UNITY_EDITOR
AkSoundEngineController.Instance.DisableEditorLateUpdate();
#endif
LogAudioFormatInfo();
AkUnitySoundEngine.ClearCaptureData();
AkUnitySoundEngine.StartDeviceCapture(OutputDeviceId);
}
else
{
AkUnitySoundEngine.StopDeviceCapture(OutputDeviceId);
#if UNITY_EDITOR
AkSoundEngineController.Instance.EnableEditorLateUpdate();
#endif
}
}
var frameTime = IsOfflineRendering && FrameRate != 0.0f ? 1.0f / FrameRate : 0.0f;
UnityEngine.Time.captureDeltaTime = frameTime;
AkUnitySoundEngine.SetOfflineRenderingFrameTime(frameTime);
AkUnitySoundEngine.SetOfflineRendering(IsOfflineRendering);
if (!IsOfflineRendering)
return;
UnityEngine.ScreenCapture.CaptureScreenshot(GetUniqueScreenshotFileName(UnityEngine.Time.frameCount));
var sampleCount = AkUnitySoundEngine.UpdateCaptureSampleCount(OutputDeviceId);
if (sampleCount <= 0)
return;
var buffer = new float[sampleCount];
var count = AkUnitySoundEngine.GetCaptureSamples(OutputDeviceId, buffer, (uint)buffer.Length);
if (count <= 0)
return;
ProcessAudioSamples(buffer);
}
}
Unity에서 오디오 입력 음원 플러그인 사용하기
오디오 입력 음원 플러그인은 C# 스크립트를 통해 사용할 수 있습니다. Wwise SDK 설명서에서 오디오 입력 음원 플러그인을 참고하세요.
다음은 오디오 입력 음원 플러그인에 시험음을 전송하는 기본 스크립트입니다.
public class MyAudioInputBehaviour : UnityEngine.MonoBehaviour
{
public uint SampleRate = 48000;
public uint NumberOfChannels = 1;
public uint SampleIndex = 0;
public uint Frequency = 880;
private bool IsPlaying = true;
bool AudioSamplesDelegate(uint playingID, uint channelIndex, float[] samples)
{
for (uint i = 0; i < samples.Length; ++i)
samples[i] = UnityEngine.Mathf.Sin(Frequency * 2 * UnityEngine.Mathf.PI * (i + SampleIndex) / SampleRate);
if (channelIndex == NumberOfChannels - 1)
SampleIndex = (uint)(SampleIndex + samples.Length) % SampleRate;
return IsPlaying;
}
void AudioFormatDelegate(uint playingID, AkAudioFormat audioFormat)
{
audioFormat.channelConfig.uNumChannels = NumberOfChannels;
audioFormat.uSampleRate = SampleRate;
}
private void Start()
{
AkAudioInputManager.PostAudioInputEvent(AudioInputEvent, gameObject, AudioSamplesDelegate, AudioFormatDelegate);
}
public void StopSound()
{
IsPlaying = false;
}
private void OnDestroy()
{
AudioInputEvent.Stop(gameObject);
}
}
Unity에서 맞춤 위치 지정 적용하기
기본적으로 AkGameObj
컴포넌트는 특정한 Unity gameObject
에 연결되어 있으며 트랜스폼(transform) (필요시 상쇄값도 포함)을 사용하여 전체 위치 지정을 설정합니다. 이 방법은 보통 1인칭 슈팅 게임과 같은 수많은 게임에 적합합니다. 하지만 3인칭 게임과 같이 맞춤 카메라 각도가 있는 게임의 경우, Unity의 메인 카메라와 같이 한 게임 오브젝트에 오디오 리스너(audio listener)를 연결해서는 위치 지정의 두 방면 (거리 감쇠와 공간화)를 다루기가 어렵습니다. 게임에 따라 플레이어가 맞춤화된 다른 위치 지정을 경험하도록 하고자 할 수 있습니다.
이런 경우를 위해 AkGameObj
컴포넌트 클래스는 Unity 사용자가 위치 지정을 오버라이드할 수 있게 해줍니다. Unity에서는 세 가지 가상 메소드인 GetPosition()
, GetForward()
, GetUpward()
를 통해 AkGameObj
로부터 하위 클래스를 만들고, 이 하위 클래스 컴포넌트를 사용해서 Unity gameObjects
의 위치 지정을 맞춤화할 수 있습니다.
다음은 커스텀 컴포넌트를 사용하여 기본 AkAudioListener
작동 방식을 덮어쓰는 방법을 보여주는 간단한 예시입니다. Wwise를 사용하여 통합된 3인칭 프로젝트의 경우 기존의 AkAudioListener
와 연관된 AkGameObj
를 제거하세요. 그리고 다음 스크립트를 MainCamera 오브젝트에 연결하고 AkAudioListener
를 연결하세요. 마지막으로 오디오 리스너의 위치가 따를 대상 Unity gameObject
(예를 들어 플레이어 아바타와 같이)를 지정하세요. 이렇게 하면 모든 방사체의 거리 감쇠가 선택된 Unity gameObject
의 위치를 청자의 위치 (화면 안의 거리 리스너)로 사용하며, 모든 방사체의 거리는 여전히 메인 카메라의 방향을 청자의 방향 (화면 밖의 방향 리스너)으로 설정합니다.
#if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.
using UnityEngine;
using System;
using System.Collections.Generic;
[AddComponentMenu ("Wwise/AkGameObj3rdPersonCam")]
[ExecuteInEditMode]
public class AkGameObj3rdPersonCam :
AkGameObj
{
public Transform target;
{
return target.GetComponent<
AkGameObj> ().GetPosition ();
}
}
#endif // #if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.