Разрешить XNA SoundEffectInstance воспроизводить себя
По сути, у меня есть звуковой эффект, который воспроизводится, когда в моей игре сталкиваются два предмета. Некоторые из предметов довольно близки друг к другу, поэтому звуковой эффект может быть воспроизведен в быстрой последовательности.
Используя SoundEffect.Play() это работает. Однако, чтобы сэкономить на сборке мусора, я хочу использовать экземпляр. К сожалению, это означает, что экземпляр не будет воспроизводиться до тех пор, пока не закончится воспроизведение последнего. Это не тот эффект, который был после. Есть ли способ перезаписать эту функцию или мне придется вернуться к простому старому SoundEffect?
2 ответа
Есть ли причина, по которой вы хотите "сэкономить на сборке мусора"? Если вы не столкнетесь с реальными проблемами производительности, вам, скорее всего, не о чем беспокоиться. Исходя из личного опыта, вы можете воспроизводить не менее десятка звуков в быстрой последовательности (используя SoundEffect.Play()
без проблем. Однако, если вы чувствуете, что в вашей игре много столкновений, вы можете сделать две вещи:
Во-первых, подумайте о создании простого SoundPlayer
класс, который обрабатывает все звуки, которые вы играете, и всякий раз, когда вы обнаруживаете более 10 играющих одновременно, предотвращайте воспроизведение следующего. Это не значит, что игрок заметил бы пропущенные звуки, если происходит много столкновений.
Во-вторых, посмотрите здесь ( http://forums.create.msdn.com/forums/t/91165.aspx) о том, как использовать DynamicSoundEffectInstance
предварительно смешать звуки. Это немного сложнее, но если заглянуть в будущее и смешать все звуки, которые собираются воспроизвести в одном буфере, вы в значительной степени гарантируете нулевую задержку, потому что эффективно существует только один звук (или один буфер аудиопотока) играть.
List<SoundEffectInstance> explosionSoundInstanceList;
explosionSound = Content.Load<SoundEffect>("sound/explosion");
explosionSoundInstanceList = new List<SoundEffectInstance>(MAX_EXPLOSIONS);
for (int i = 0; i < MAX_EXPLOSIONS; i++)
{
explosionSoundInstanceList.Add(explosionSound.CreateInstance());
}
private void PlayExplosionSound(float volume, float pitch, float pan)
{
ClampSoundValues(ref volume, ref pitch, ref pan);
for (int i = 0; i < explosionSoundInstanceList.Count; i++)
{
if (explosionSoundInstanceList[i].State == SoundState.Stopped)
{
explosionSoundInstanceList[i].Volume = volume / (i+1);
explosionSoundInstanceList[i].Pitch = pitch;
explosionSoundInstanceList[i].Pan = pan;
explosionSoundInstanceList[i].Play();
return;
}
}
return;
}
Работает хорошо. Ноль мусора на 360 после инстанцирования. Просто элегантно провалится после того, как вы достигнете предела.
Это то, что я использую.
Я зажимаю значения таким образом
private static void ClampSoundValues(ref float volume, ref float pitch, ref float pan)
{
volume = MathHelper.Clamp(volume, -1f, 1f);
pitch = MathHelper.Clamp(pitch, -1f, 1f);
pan = MathHelper.Clamp(pan, -1f, 1f);
}
По мере установки глупого значения будет исключено исключение.