Skip to content

Instantly share code, notes, and snippets.

@codeimpossible
Created May 7, 2021 12:45
Show Gist options
  • Save codeimpossible/6d60e9bdf486174d36c14218fd9c1289 to your computer and use it in GitHub Desktop.
Save codeimpossible/6d60e9bdf486174d36c14218fd9c1289 to your computer and use it in GitHub Desktop.
Sound Effect Scriptable Object

Sound Effect ScriptableObject

This is a scriptable object I use to make it easier to play collections of sounds. Very useful for things like footsteps, attack hits, attack swings, anythign that you want to play a variety of sounds for.

Currently only supports sequential or random playback, but could easily be updated to include pitch and volume randomization.

I inlcuded my CollectionExtensions class as well to give the .Random() extension for collections.

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NoirLib {
public static class CollectionExtensions {
private static readonly System.Random _rand = new System.Random();
public static T Random<T>(this T[] items) {
return items[_rand.Next(0, items.Length)];
}
public static T Random<T>(this List<T> items) {
return items[_rand.Next(0, items.Count)];
}
public static T RandomElementByWeight<T>(this IEnumerable<T> sequence, Func<T, float> weightSelector) {
float totalWeight = sequence.Sum(weightSelector);
// The weight we are after...
float itemWeightIndex = ((float)new System.Random().NextDouble()) * totalWeight;
float currentWeightIndex = 0;
foreach (var item in from weightedItem in sequence select new { Value = weightedItem, Weight = weightSelector(weightedItem) }) {
currentWeightIndex += item.Weight;
// If we've hit or passed the weight we are after for this item then it's the one we want....
if (currentWeightIndex >= itemWeightIndex)
return item.Value;
}
return default;
}
public static T Random<T>(this IEnumerable<T> sequence) {
// this ensures a more random distribution of items across smaller sequences
int max = sequence.Count();
int rate = UnityEngine.Random.Range(0, 101);
int idx = Mathf.Clamp(Mathf.RoundToInt(max * rate / 100f), 0, max - 1);
return sequence.Skip(idx).First();
}
}
}
MIT License

Copyright (c) [year] [fullname]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
using System.Collections.Generic;
using UnityEngine;
namespace NoirLib.DataObjects {
[CreateAssetMenu(fileName = "SoundEffect.asset", menuName = "TroubleCat Studios/Sound Effect", order = 0)]
public class SoundEffect : ScriptableObject {
[SerializeField] private int _index = 0;
public List<AudioClip> AudioClips;
public enum SoundEffectPlayStyle {
Sequential,
Random,
}
public SoundEffectPlayStyle Style;
public AudioClip GetClip() {
if (Style == SoundEffectPlayStyle.Random)
return AudioClips.Random();
_index++;
if (_index >= AudioClips.Count) _index = 0;
return AudioClips[_index];
}
public static void Play(SoundEffect effect, AudioSource source, float volumeScale = 1f) {
source.PlayOneShot(effect.GetClip(), volumeScale);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment