停止声音得方法有很多种,这里以一个例子讲解在实际应用中遇到得问题。我们知道在fmod中会提供一个StudioEventEmitter的类,它是继承自MonoBehaviour的,我们可以在上面配置一个event的名字,然后设置其播放的声明周期。
这是通常的一种做法,而实际使用中,由于MonoBehaviour特别多,会吃性能,所以我们通常的做法是,写一个池子复用。
比如:RuntimeStudioEventEmitter
我们只是将StudioEventEmitter中播放声音的方法copy到这个类中。
在fmod中其真正的播放的步骤就3步:
- 找EventDescription
- 创建EventInstance
- 执行start方法
所以这个类就比较好些了。代码如下:
public class RuntimeStudioEventEmitter
{
public String Event = "";
public List<ParamRef> Params = null;
public Vector3 Pos = Vector3.zero;
private FMOD.Studio.EventDescription eventDescription;
private FMOD.Studio.EventInstance instance;
// private bool hasTriggered = false;
public static bool isQuitting = false;
public FMOD.Studio.EventInstance EventInstance { get { return instance; } }
……//此处略去,可以照搬StudioEventEmitter
}
那上层就可以复用这个RuntimeStudioEventEmitter类了,可以做个池子。
这里的问题也就带出来了一个,如果这个RuntimeStudioEventEmitter是复用的,那么instance成员只记录了当前播放的实例,而之前的实例如何停止呢?
这里提供两个方法:
1、创建一个list,保存每次播放的实例,然后for循环停止
public List<FMOD.Studio.EventInstance> instances = new List<FMOD.Studio.EventInstance>();
for (int i = 0; i < e.instances.Count; ++i)
{
if (e.instances[i].isValid())
{
bool isPause = false;
e.instances[i].getPaused(out isPause);
if (isPause) //如果是pause状态,设置为非pause状态,然后才能释放,需要连fmod profiler查看
{
e.instances[i].setPaused(false);
}
e.instances[i].stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
}
}
2、使用EventDescription的getInstanceList获取实例,然后停止
events这个就要外部记录到底播放了哪些名字的event了。
for (int i = 0; i < events.Count; ++i)
{
FMOD.Studio.EventDescription eventDescription = RuntimeManager.GetEventDescription(events[i]);
eventDescription.getInstanceList(out array);
if (array != null)
{
for (int j = 0; j < array.Length; ++j)
{
if (array[j].isValid())
{
array[j].stop(mode);
array[j].release();
array[j].clearHandle();
}
}
}
}
两种方法经过测试都是可行的。