UE3声音开发介绍
为了增加视听效果一般会从声音上入手,但对于不同的游戏开发引擎来说,开发流程又大致相同,为此希望通过本篇文章的介绍你可以知道UE3声音的开发流程和注意事项。
一、各款声音引擎比较。
首先,为什么要开发声音,这里就不多废话了,它能增加视听效果,尤其是那种动作片大家都懂,“没声音,再好的戏也出不来”,同样“没声音,再好的游戏也出不来”。
以前接触过几款声音引擎,Fmod和WWise,最近在研究的UE3项目,它自己也有一款自带的声音引擎,总体来说,不同引擎,声音的大致开发流程和注意事项都有相近。
先说下FMod和Wwise的区别,Fmod的入手比较简单,它的API也很明了,对要快速上手开发的简单项目是比较好的选择。Wwise比起FMod上手比较复杂,它自带一整套声音编辑工具及声音资源管理方案,虽然掌握它需要一定的时间和精力,但是一旦熟悉之后,后期声音的添加、修改、管理等会很方便。总之,FMod和WWise的区别是,FMod的API较为基础和底层,很多额外功能需要自己去封装它的API来实现,最终会令控制代码比较繁琐难以维护和扩展,比如声音的淡入淡出,声音的衰减方式,声音资源的管理等,好处是它上手简单。WWise的API比较高级,接口明了,很多功能都封装在编辑器中,比如声音资源的压缩打包等都集成在内,容易通过编辑器来扩展声音需求而不需要对代码有太大改动,但是需要较长时间去熟悉它的编辑器。UE3自带的编辑器就有图形化的声音编辑工具,通过组合及编辑各声音节点的图表便可以满足各种游戏中的声音应用要求,UE3的声音引擎和WWise比较接近,它的编辑工具比较丰富和复杂,可扩展性高,以下是它的自带声音编辑工具SoundCueEditor的UI界面的一个截图。当然,今天我们的主角是UE3声音开发,所以FMod和Wwise就不在赘述了。
二、声音开发的一些基础。
先简单说一下对于开发声音需要了解的一些事项。首先是UI声音,UI声音一般是2D声音,不需要考虑衰减,所以做起来比较简单,只要了解播放、停止、循环、渐入渐出等一些接口即可。然后是3D声音,3D声音根据应用又可以分类为环境音、特效音、角色绑定声音等,环境音一般和具体环境有关,比如瀑布附近有水流声,树林有鸟叫声,它的位置一般固定不动,而特效角色音,一般绑定于某个物体的某个节点上,随着节点的运动声音源也跟着运动,总之3D声音都有一些共同属性。
1、都有一个3D位置。
2、声音的播放方向。
3、都有一些衰减方式(随距离线性衰减、对数衰减 OR 反对数衰减)。3,衰减的最大和最小距离。
4、更高级一点,根据多普勒效应,波在波源移向观察者时接收频率变高,而在波源远离观察者时接收频率变低,因为声音也是一种波,所以,声音还和它所绑定物体的速度有关,即声源的速度,声源在往收听者方向运动时,音频会变高,反之变低,当然这个速度考虑了和观察者之间的相对速度,因为观察者自己本身也有速度,也会影响声音的音频。不过游戏中声音的多普勒效应貌似考虑的不多,一来影响效率,二来对体验感影响并不大,三是很多时候声源或者收听者高速运动时,听到的声音要不异常刺耳、要不异常低沉,反而令声音显得不够自然。
3D声音除了自身属性会对音效有影响,还有一个很重要的因素便是收听者,收听者也有这么几个属性。
1、收听者的3D位置,一般是绑定于相机位置。
2、收听者的面朝,在各款声音引擎中,经常用面朝的上方和右方向量来表示,一般与相机坐标轴的上、右两个轴对应,要注意的是,有时候声音引擎和图形引擎的坐标系不一样,需要做一些简单的转换。
另外,更高级有点,3D声音还可以考虑环境的几何阻挡,具体做法一般是对3D世界中有声音阻挡的几何物体形状注册到声音引擎中,然后声音引擎便会考虑这些阻挡对声音造成的影响,不过一般游戏中,有声音阻挡的情况貌似不多,一来影响效率,二来似乎对游戏性影响并不大。
一般声音引擎都有一个声音设备对象,该对象可以设置声音引擎的一些重要属性,一个最常用的概念是声道,声音设备对象中一般会有一个MaxChannels的变量,是该设备对象支持的最大声道数,比如1,100,1000个,它的数量可以很大,但是具体音频硬件设备很可能只有32或者64声道,它是如何支持到设备对象的成百上千个声道呢,其实和操作系统的内存原理一样,我们所开发的设备对象类的声道数一般是指虚拟声道,如果虚拟声道播放的声音个数超过硬件设备的声道数时,声音引擎会对播放的声音进行排序,将权重低(一般是音量较低)的声音忽略掉,通过这个方式来模拟成百上千的虚拟声道。
三、UE3声音导入及编辑。
现在,进入正题,UE3的声音开发。首先开发声音,必须知道如何导入声音资源,UE3编辑器中导入声音的过程非常简单,下面用几张图来做介绍,另外要注意的一点是,官方说明UE3导入的声音目前非授权版本只支持导入WAV、OGG声音,但是本人找了好几个OGG来尝试,都导不了,也不知道是不是官方文档坑了俺,有谁知道的为什么的请告知我一下,目前尝试只有WAV可以导入。
1、打开UE3编辑器的ContentBrower
2、点击上图红框中的Import按钮,找到你放置WAV文件的位置,点确定导入,会出现一个对话框,下图红框内的文字或者选项一般是需要填写的,Package是你的包名,Grouping是包内的一个分组,Name是该声音的名字,AutoCreate Cue是问你是否需要创建一个SoundCue,这个很重要,因为如果你不创建一个SoundCue,你在程序中是没法引用的,所以我们把AutoCreate Cue勾起来,其他的一些选项,在编辑SoundCue的时候都可以修改,所以默认不去编辑他们。(后面还会介绍一种不需要勾AutoCreate Cue,换成手动创建Cue的方式)
点击确定之后,就出现了下图两个资源,一个是SoundNodeWave,一个是SoundCue,SoundNodeWave相当于一个声音源文件,SoundCue是通过组合一些节点选项及对这些节点属性进行设置来扩展SoundNodeWave的表现。虽然UE3支持的WAV初始文件大小会很大,不过不用担心这个,导入到UE3资源包内的WAV声音会被自动压缩,通过SoundNodeWave内的Compression可以设置它的压缩质量。
3、对Explode_Cue进行编辑,右键Explode_Cue选择EditUsing Sound Cue Editor,会出现如下UI界面:
这是默认导入的SoundCue的一个节点界面,左边喇叭状节点的是一个扬声器节点(SpeakerNode),点击它后可以在界面下方的属性编辑窗口内编辑声音输出的音量和音调,右边署名为Explode的节点的是一个声音波形节点(SoundNode Wave),它表示的是一个音频文件,UE3通过UI节点界面的图形组合方式进行声音应用的编辑,它另外还包含“衰减”、“循环次数”、“随机”、“音量”、“混合”、“延迟”等节点。
这里有件事让我想借机吐槽一下UDK。有时候,UDK有些很自然的功能,它会弄的很隐蔽,让你找不到北,官方教程也不会有说明,只能到民间散落的角落去搜集一些琐碎的线索,相当的蛋疼和坑爹。创建SoundCue的另一种方式,通过右键选newSoundCue来创建,但是它没有关联任何音频文件(SoundNode Wave),它的UI编辑界面如下:
可以看到,除了一个扬声器,其他空空如也,这时你会很自然地想到右键空白地方选择新建一个节点,这时纠结的事情来了,右键内容如下:
从上数到下,没有一个是SoundNode Wave,对着喇叭右键,对着窗口各个角落右键都找不到,也没有其他可编辑选项,YourSister!一下毫无头绪。好在网上UDK关于声音的资料还算多,本人后来在UE2.0版本民间资料的编辑器介绍中看到,首先打开空的SoundCue编辑界面,然后同时到ContentBrowser中先选取一个SoundNodeWave,(先后顺序不能错)如下图:
再然后,对着喇叭(扬声器)右键,总算出现了SoundNodeWave,如下图所示:
真是菊花残,满地伤啊!通过这个方式,就可以在一个SoundCue内导入多个声音波形节点(SoundNode Wave),再通过“随机”或者“混合”节点对这些声音进行各种应用操作,以下是用一个随机节点连接两个SoundNode Wave的截图,播放这个SoundCue会根据随机结点对各SoundNodeWave的权重设置来随机播放其中一个声音波形:
4、3D声音的衰减添加
对于2D声音,由于并没有位置信息,所以不需要考虑衰减。对于3D声音,你可以通过添加一个Attenuation(衰减)的节点来编辑节点的衰减方式,如下所示:
该图的意思是,Explode这个声音波形文件施加了Attenuation节点的衰减影响,点击Attenuation节点,在属性面板中可以编辑声音的衰减方式,如下图:
这里只挑3个比较常用的选项来说明,其他一般使用默认设置:
a,DistanceAlgorithm,即声音随距离衰减的曲线选择,有线性曲线,对数曲线,反对数曲线,自然衰减曲线,这里效率最高的是线性曲线,但不够逼真,自然衰减曲线效率最低,函数最复杂,但最逼真。
它们各自的适用情况如下:
线性曲线选项(ATTENUATION_Linear):比较适用于一般不需要严格的 3d 衰减设置的循环环境和低细节背景声音。还适用于交叉衰减的大半径环境声音。
对数曲线选项(ATTENUATION_Logarithmic):适用于那些需要更多精确的 3d 定位的声音。同时还适用于在近距离使声音产生“跳动”;也适用于即将发射的导弹和射弹。
反对数曲线选项(ATTENUATION_LogReverse):作为武器或其他声音中的一个图层使用,需要提高这些声音才能放大到它们 MaxRadius 的声音。
自然衰减曲线选项(ATTENUATION_NaturalSound):使用实例:适用于射击或者其他兴趣点或高频率内容,对于它们而言,使用对数衰减无法‘准确’地体现声音的衰减情况。
b,Radius Min,即衰减曲线开始影响的距离,从声效的原点到开始发生衰减处的距离。在0.0到这个距离之间声效的音量是100%。
c,Radius Max, 从声效的原点处到衰减结束处的距离。在RadiusMin到这个距离之间输入声效从100%衰减到0%。
另外,编辑器还有好多其他功能的结点可以通过编辑器来组合出不同效果,各位有兴趣可以去一一尝试,这里就不多做介绍,官方的音频专题下有具体结点的介绍。
四、UnrealScript的声音代码。
注:程序中播放的声音,都是通过关联Sound_Cue资源来播放的。
1、3D声音的播放。
声音可以通过Actor的PlaySound来播放,也可以通过函数CreateAudioComponent创建组件的方式来播放,本人找了许久,并未发现PlaySound对应的StopSound函数,而且PlaySound函数并未返回一个用来代表声音对象的东西,并且它的参数说明也不是很明了,所以,使用起来并不是很方便,播放之后就无法对其进行控制,有谁知道如何解决的请告诉我,不甚感激!这里我主要还是通过创建组件的方式来播放和停止声音,以下是CreateAudioComponent函数的原型
//=============================================================================
// Sound functions.
/* Create an audio component.
* may fail and return None ifsound is disabled, there are too many sounds playing, or if the Location is outof range of all listeners
*/
native final function AudioComponent CreateAudioComponent(
SoundCue InSoundCue, // 要关联播放的SoundCue
optional bool bPlay, // 创建后是否马上播放
optional bool bStopWhenOwnerDestroyed, // 当拥有者销毁时,是否停止播放
optional bool bUseLocation, // 指定的播放位置
optional vector SourceLocation, // 指定的播放方向
optional bool bAttachToSelf = true); // 当这个参数为true时,声音绑定在调用函数的Actor上,且指定的播放位置和方向无效
通过AudioComponent的Play和Stop等方法可以方便的对声音进行操作。AudioComponent还有很多其他有意思的变量可以设置,有兴趣可以一一去修改测试。
2、声音收听者的设置。
UE3的官方文档中说到,AudioDevice是声音设备,负责加载管理声音,并且在Update函数中更新声音收听者的位置、朝向、速度等信息,UnrealScript中,AudioDevice是一个Native类,且尚未提供Update函数的修改,我们无法直接通过AudioDevice来更新它的收听者位置等信息,默认情况下,通过测试可以看到,收听者位置和朝向是绑定于PlayerController的TargetView上的,一般TargetView是一个Pawn,如果游戏是第三人称视角而非第一人称视角,一般会希望将收听者绑定于相机之上,这时,只要通过SetTargetView将相机绑定为TargetView即可,这个做法也许并非官方比较正式的做法,可是它确实有效,也许是我没找着,或者是蛋疼的官方并未给出具体设置收听者方式的文档,总之,各位有更好方法的请让我知道一下。
3、2D声音的播放
2D声音一般用于UI或者是游戏背景音乐。一般是通过GfxMoviePlayer的SoundThemes(主题)来播放的,每个SoundTheme可以在编辑器的内容浏览器内通过编辑SoundCue映射表来添加声音,在脚本中通过PlaySoundFromTheme('SoundCue的映射名','主题名')来播放。
3、环境音
环境音也属于3D声音,但单独拿出来讲是因为它和普通3D声音有所区别,它和具体环境位置相关。要在关卡中添加环境音有两种方式,一种是静态地在关卡编辑器中通过右键添加AmmbientSound类的Actor,然后通过它的属性设置声音的Sound_cue以及在关卡中拖动调整其位置。另一种方式是在代码中动态地添加播放和关闭,代码大致如下
AmbientSoundComponent= new(self) class'AudioComponent';
if( AmbientSoundComponent != none )
{
AttachComponent(AmbientSoundComponent);
AmbientSoundComponent.SoundCue = SoundCue'资源名';
AmbientSoundComponent.Play();
}
AttachComponent该环境音的地点一般代表某个具体环境。
五、有趣的脚步声制作。
UE3自带强大的材质系统和射线拾取功能相关联,你可以通过射线拾取检测到角色脚底下所踩的材质是属于什么地质的,比如泥土、岩石、水等,你可以由此来播放不同的脚步声。脚部声的制作涉及到动画资源的编辑,这里简单介绍一下动画脚步的编辑,AnimSet编辑器下,某个动画的属性页下有一个AnimSequene,通过右边的时间轴界面将动画拉到某个姿势,比如左脚踩下的姿势,这时在AnimSequene下的Notifies添加一个Notify,并通过下拉标签选择AnimNotify_FootStep,然后设置FootDown为0,同理,右脚踩下,FootDown为1,保存修改,关闭编辑器。然后在UnrealScript中就可以在对应设置了该Mesh的Pawn类下添加一个事件函数:
Simulated event PlayFootStepSound(int FootDown)
{
If (FootDown == 0)
{// 左脚声}
Else if(FootDown ==1)
{// 右脚声}
}
再做一个扩展,添加脚底材质判断,这里我简化了判断方式,只是射线检测一下拾取到的Actor,
Function name GetMaterialBelowFeet()
{
..........//变量声明
LineBegin .X = Location.X;
LineBegin .Y = Location.Y;
LineBegin .Z = 65536.f;// 开始于天上
LineEnd.X = Location.X;
LineEnd.Y = Location.Y;
LineEnd.Z = -65536.f;// 结束于地下
HitActor = Trace(HitLocation,HitNormal, LineEnd, LineBegin, true, , , TRACEFLAG_Bullet);
// FluidSurfaceActor是一个流体Actor
If( FluidSurfaceActor(HitActor) !=none )
{
Return 'Water';
}
Return 'Default';
}
然后在PlayFootStepSound内做如下处理:
Simulated event PlayFootStepSound(int FootDown)
{
Local Name GroundType;
GroundType =GetMaterialBelowFeet();
If (GroundType == 'Default')
{
If (FootDown == 0)
{// 左脚声}
Else if(FootDown ==1)
{// 右脚声}
}
elseIf (GroundType == 'Water')
{
If (FootDown == 0)
{// 左脚踏水声}
Else if(FootDown ==1)
{// 右脚踏水声}
}
}