#Sounds stuff
1 messages · Page 1 of 1 (latest)
That was the name
Darn
Sounds stuff
"So could I assign the names the same way as I do now in the inspector or not?"
You wouldn't need to use any names, that's the beauty of it. You just reference these assets in scripts, just like you would reference an AudioClip directly
Because the end goal is making it easy to use for my teammates mostly
This is like an AudioClip but with extra data
Hmmmm
The AudioManager doesn't need to find anything, it just gets this SoundAsset and it can directly access its audio clip and related data
If someone wants to add another sound, how would someone go about doing that
Because currently it's just an easy drag and drop
At the clip
thing
It's basically exactly the same thing, except instead of pressing that + in the AudioManager, you'd create a SoundAsset in a project folder.
Then you fill in the exact same data
Does it add to the SoundAsset or will it be each an independant file?
Also I read the text wrong
Each SoundAsset will be an independent file/asset
Which you reference from scripts instead of using a hardcoded name
But if I understand it right with the method you're suggesting there would be no interaction with the inspector, correct?
Not with AudioManager, but each SoundAsset has its own data with its own inspector
You select the asset and you edit its properties
Which are the same properties as in this Sound class from Brackey's
An audio clip, volume, pitch and loop
You can't attach extra data on these source audio files, so you have to make a new asset type that wraps around the audio clip and includes the extra data
Sorry that I'm taking up all of your time, I'm just having a hard time to paint a picture of what you're suggesting
Maybe it's easier if you have the scripts so you can see what it looks like in the editor
If you post your AudioManager script, I can edit it to this new workflow.
You want the file or just the code?
Just the code is fine
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
public static AudioManager sound;
public Sound[] sounds;
private bool cooldown;
[SerializeField]
public enum Name
{
yes,
no
}
public Name name1;
private void Awake()
{
DontDestroyOnLoad(gameObject);
if (sound == null)
sound = this;
else
{
Destroy(gameObject);
return;
}
foreach (Sound s in sounds)
{
s.source = gameObject.AddComponent<AudioSource>();
s.source.clip = s.clip;
s.source.volume = s.volume;
s.source.pitch = s.pitch;
}
}
public void Play(string name, bool overlap = true, float delay = 0)
{
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null)
{
Debug.LogWarning($"Sound {name} not found");
return;
}
if (overlap)
s.source.Play();
else if (!s.source.isPlaying && !cooldown)
{
s.source.Play();
StartCoroutine(Cooldown(delay));
}
}
public float SoundDuration(string name)
{
Sound s = Array.Find(sounds, sound => sound.name == name);
return s.source.clip.length;
}
private IEnumerator Cooldown(float delay)
{
cooldown = true;
yield return new WaitForSeconds(delay);
cooldown = false;
}
public void Stop(string name)
{
Sound s = Array.Find(sounds, sound => sound.name == name);
s.source.Stop();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class Sound
{
public string name;
public AudioClip clip;
[Range(0f, 1)]
public float volume;
[Range(0.1f, 3)]
public float pitch;
public bool loop;
[HideInInspector]
public AudioSource source;
}
Those are the only 2 classes I use
Also tysm for all the help :)
I want to suggest another improvement. You have this Stop(string name) method, but this means that you can only have one sound of each type playing at once. Like, you can't play two Charge sound effects. Is that not an annoying limitation?
I've not run into that yet due to me not having used it much
So I don't really know the limitations :P
I think it's a bit yucky, but I'll keep that functionality the same for this conversion
I honestly don't get how the Stop affects that only 1 can play at the same time
Or do you mean if you stop one
That it stops them all
In which case yes
Yeah it's not supposed to stop all sounds if you mean that
I know, but what if you have two Charge sounds playing? Which one does it stop?
I don't know?
Haven't run into a situation where 2 of the same sounds play at once that I also am stopping
But can you even play one sound overlapping? There's one audio source for each sound, so it can't play the same sound multiple times
That's pretty limiting
I guess so?
I'd have probably hit that wall if I were further with using sounds
I just like perfecting things even though I have barely used it lmao
Here's the updated AudioManager: https://hastebin.com/onoyepemey.csharp
And here's the new SoundAsset: https://hatebin.com/ulipvdgybq
Why is one hastebin and the other hatebin lmao
Because hastebin rate limited me for trying to upload to quickly
Interesting lol
And here's an example of how this would be used in scripts:
public class Player : MonoBehaviour
{
[SerializeField]
private SoundAsset jumpSound;
private void Jump()
{
AudioManager.sound.Play(jumpSound);
}
}
And in the inspector you'd drag in the sound asset you want Player to play when he jumps
How do I create the scriptable object in the assets?
Or do I not have to do that
Should probably mention this is my first time working with scriptable objects 😅
You do, and it will appear as an option under Create when you right click in a folder
Yeah was thinking about that
I'm assuming it's from scripts that are using the AudioManager. You can just comment out those lines for now.
There it is
Alright im blind then
Yup just saw that lol
The name you give the file doesn't matter because you won't use that name anywhere in the code
Got it
Hang on, it just finds any audio source within assets?
No matter the foldering?
When you select one in the editor
You mean the list you pick from when assigning the audio clip?
Yeah, it doesn't organize it
Well it's amazing though that it just looks for all audio and just puts in that convenient list
Okay so for each sound, I need another scriptable object right?
Yep
Which would just be Create > Sound Asset
Exactly. That would be slow.
Oh wait I've to define the sound within the class?
You define it as a serialized field so that you can select which audio you want it to play from the inspector
It's more work than just hardcoding it, but it means that you can easily swap to a different sound, even during playmode testing.
And you avoid any hard coded references, which is always good
But that would mean audio would be assigned per object
So my Player Jump example would look like this
Instead of just being accesible from everywhere
Yeah got that
You can still think of it as accessible from everywhere, but instead of choosing what sound you play from code, you're choosing it from the inspector
You can reference any sound asset in any script
Hmmm
So if some object were to have 5 different sounds
I'd have to define all 5 at the top?
Instead of just being able to use them without having to define them
Yes. I can understand if you think that's too verbose.
But shorter code isn't always better code
And look, here's your enum that can be added to
It's just in the editor instead of in code
that's pretty neat
Is there no convenient way though to define it in the code without having to define it in the code
If that makes any sense
Oh wait no im being dumb
Then you're back where you started, getting them by string name and searching for them
Which is horribly inefficient I suppose?
It can be improved by using a Dictionary instead of an array.
Besides just being inconvenient
There's no trivial way to get an auto-complete list of the sounds available in code. The asset selector window above is as close as you can get to that.
Hm
Is there some sort of component or script that I can just attach to an object that stores the sound effects that it needs
And then other script on that component can use it or whatever
You can reduce the amount of code by defining all the sound assets in one line:
[SerializeField]
private SoundAsset jumpSound, chargeSound, attackSound;
Yeah I knew that, but thanks
Are you also trying to avoid having to select the sound asset?
I'm trying to avoid my teammates having to put [SerializeField] private SoundAsset soundAsset in the code
Any way you can just drag something on it that does that lmao
supreme laziness
I think this will actually be better for lazy teammates. They don't have to memorize the names of sounds or check when they've forgotten, and they can't accidentally write a typo
That's a lot of pros for the cost of one line
Yeah I figured that much, so regardless I was going to use this system but I wonder if there are any other teeny tiny ways to optimise it
Also thanks a lot for all the help, again
I wonder, do you use this sort of system for your own games or?
And I have a few extra settings on them
Sure, I could add those later probably if I'd want to
And a custom inspector to make it easier to work with
For now this is fine though I think
You've an entire custom inspector?
Well, a custom editor for AudioAsset specifically
It's a feature Unity has, you can make custom editor GUI for specific types
Doesn't have to be. Depends how complicated you want it to be.
I mean, you quite seem to know what you're doing so probably wouldn't have taken you long
Also this is by no means asking you to do it for me, I'm just curious how long it took you to make etc lol
What you gave me is plenty, and I am ever so grateful of it
Here's how my AudioAsset looks like
Yo that's mad
This took a few days for all the features
Definitely
Problem, it's not finding the scriptable objects?
That's pretty weird
What happens if you click that crossed out eye in the top right corner?
Absolutely nothing
Are you able to drag and drop the asset onto the variable?
Except becoming dark grey instead of light grey, so it enables and disables but doesn't do anything
Couldn't do it at first idk why now
Sounds like maybe the file name is still just Sound?
The file name must match the class name
So it must be SoundAsset.cs
The file name of each scriptable object?
No, the file name of the C# script file that contains the SoundAsset class definition
Eh?
Whatever .cs file you wrote public class SoundAsset : ScriptableObject etc
It must be named SoundAsset.cs
Or just SoundAsset in Unity
So this is supposed to be called SoundAsset
Yes
Did the project recompile after you renamed it?
I assume it did?
Maybe try just making a non-change in any script, like adding a space somewhere
To force it to recompile
The SoundAsset class is definitely defined inside that SoundAsset script file?
It's not some other class in there?
?
And the list is still empty?
If you mean this list then yes
Maybe the assets you've already made are somehow corrupt because of the wrong file name
Try making a new Sound Asset
:)
Huh
I suppose because it's a scriptable object
It does not reset values if adjusted during play mode (after closing play mode)
Interesting
Yeah, it's often useful but sometimes annoying
Yup
The benefit of having the one of these more global ones is that you've an overview of every sound though
Here you've to individually select each object
to adjust the settings
True, but my project has over 600 AudioAssets. An unorganized list becomes a lot less useful when you have that many items.
That's a lot of audio
And that's only the audio clips I've made an audio asset for
Wow
I suppose this way would be better short term
But long term the overview would get jumbled
Due to the sheer amount of audio
It would be possible to make a custom editor window that displays all the assets in a similar list, if you really wanted to
And you can make it more organized, based on folders for example
Seems hard
Yeah figured that much
I wonder is there an easy way to group some together
Like these 2 in 1 menu
Since one is for charging and the other one is when it shoots
I have AudioAssetCollections, but that's more for playing a random sound in a collection of slightly different sounds
Right fair
In the case of charging and shooting, you could make a ScriptableObject that has a "start sound" and an "end sound"
And maybe an optional looping middle sound
complexity 100
I read on the internet a while ago that you cannot only have the first one have the header if you do it this way
So I imagine you don't know a way around other than, split them up too?
Like this
Yeah, not much else you can do about that
Yeah thought so
The next one you can keep going with , no problem though
Mainly just want it for this one specifically because it's a hot mess of serializedfields
Also FYI, not my code
Honestly kinda questionable how he made it but ig it works, so y'know ¯_(ツ)_/¯
Why does it say this
When it asks for 3 arguments
Also don't mind the strings they're placeholders lol
I wanna mainly change the order bc I feel like my teammates won't be happy if new folder isn't on top lol
You have to include the argument names. You can find examples of it online.
Yeah I'll look it up later
Anyway, thanks so much for all the help
Much appreciated!
@tired lava Hey how would I go about pausing all audio?
Because I've been sitting here for a while and I cannot figure it out
Is that even a possibility with the current code that I've?
You can do AudioListener.pause = true; to pause all audio sources, but I'm assuming you want to do this for a pause menu and this would make it impossible to have audio in the menu.
For now that’ll be fine thanks so much
Can’t believe I wasn’t able to find that
Probably just overly damn blind lmfao
@tired lava Hey it's me again, uhm we're currently trying to add a settings menu that lowers the sound of all sounds, which we did by using a multiplier, like so:
private static readonly int defaultValue = 1;
private static readonly int multiplier = 1;
[Range(0f, 1)]
public float volume = defaultValue * multiplier;
But this would prevent us from being able to change sounds individually (most importantly the background music and the sounds)
So we thought we'd maybe add an enum option and loop through that to keep it seperate, but we're not quite certain how to do that
public enum Type
{
Sound,
Soundtrack
}
public Type type;
Bottom gives this dropdown option within the inspector
@tired lava , pinged the wrong one first, woops
This looks reasonable. I have a similar setup, an enum like this:
public enum AudioGroup
{
Master,
SFX,
Music,
Dialog
}
and what I do is I map these to AudioMixerGroups, which you can set on an AudioSource and then change the volume of the group to affect all audio sources in that group without needing to loop through all of them yourself.
Could you please provide an example of that?
You have to set up the AudioMixer and its groups in the editor and then reference them in code. The code would look something like this, in your script that receives the Sound scriptable object and sets up the AudioSource:
[SerializeField]
private AudioMixerGroup soundGroup;
[SerializeField]
private AudioMixerGroup soundtrackGroup;
private AudioMixerGroup GetAudioMixerGroup(Type type)
{
return type switch
{
Type.Sound => soundGroup,
Type.Soundtrack => soundtrackGroup
};
}
...
// In your method where you are setting up the AudioSource:
audioSource.outputAudioMixerGroup = GetAudioMixerGroup(sound.type);
@past dagger
And then you change the volume of each group somewhere else, probably in your UI logic
You can find tutorials on that
Thanks alot, I'll look into it :)
Wait, one more thing, would this just be within the AudioManager or would this be an entire seperate class, from what I think I would just be able to put it within the AudioManager, no?
Because I assume the AudioMixerGroup is the enum, it just doesn't match your example from before?
No, AudioMixerGroup is a built-in Unity type representing the audio mixer group you have to create in the editor
Oh
The GetAudioMixerGroup method converts the Type enum (you should rename it) to its defined group
You could also reference the AudioMixerGroup directly in the Sound scriptable object, but I personally use my enum for more than just setting up the audio mixer
So I've tried stuff, but I'm a bit stuck on how to adjust the volume, since from what I understand I need
AudioManager.soundtrackGroup.audioMixer.SetFloat(param, param);
But then as string it wants an audioMixer which I do not really have, which I tried to add in on top but of course I never really assigned it anywhere so it'd always be null
public static AudioMixerGroup soundGroup, soundtrackGroup;
public static AudioMixer soundMixer, soundtrackMixer;
So currently rather stuck on this end, don't know what to do with the AudioMixer part of it
This'd about be the relevant code
AudioManager
public static AudioMixerGroup soundGroup, soundtrackGroup;
public static AudioMixer soundGroups, soundtrackGroups;
private AudioMixerGroup GetAudioMixerGroup(AudioGroup audioGroup)
{
return audioGroup switch
{
AudioGroup.Sound => soundGroup,
AudioGroup.Soundtrack => soundtrackGroup,
};
}
private void SetupSources(Sound sound)
{
if (sound.source == null)
sound.source = gameObject.AddComponent<AudioSource>();
sound.source.outputAudioMixerGroup = GetAudioMixerGroup(sound.audioGroup);
sound.source.clip = sound.clip;
sound.source.volume = sound.volume;
sound.source.pitch = sound.pitch;
sound.source.loop = sound.loop;
}
Sound Class
using UnityEngine;
//Don't question why the order is 29 to be in the right place, I don't know either, I figured it out by trial and error.
[CreateAssetMenu(fileName = "New Sound", menuName = "New Sound", order = 29)]
public class Sound : ScriptableObject
{
public enum AudioGroup
{
Sound,
Soundtrack
}
public AudioGroup audioGroup;
public AudioClip clip;
private static readonly int defaultValue = 1;
private static readonly int multiplier = 1;
[Range(0f, 1)]
public float volume = defaultValue * multiplier;
[Range(0.1f, 3)]
public float pitch = defaultValue;
public bool loop;
[HideInInspector]
public AudioSource source;
}
You should only have one AudioMixer with many groups, not one mixer for each group.
Do you want to do it from AudioManager?
I think so?
@past dagger Have you looked up a tutorial on how to use audio mixers for an audio settings menu?
Unity Audio Mixers, adjustable with sliders and saving its values to persist! EVERYTHING YOU NEED TO KNOW comprehensive guide
How to add audio to your game (the basics of audio): https://youtu.be/eNi67i5my84
How to play a specific clip instead of a random one:
[SerializeField] AudioClip clip; //Just use a clip instead of a list
audioSource.P...
Learn how to make an in-game options menu using Unity!
● Sign up for the Devdog Christmas Calender: http://bit.ly/DevdogGiveaway
● START MENU in Unity: https://youtu.be/zc8ac_qUXQY
● Ultimate Game UI: https://www.assetstore.unity3d.com/#!/content/53973?aid=1101lPGj
♥ Support Brackeys on Patreon: http://patreon.com/brackeys/
··················...
The problem kinda lies with I don't see how I'd implement it with this system
Or I'm just dumb
Or really tired kek (or both)
Sorry if I'm a bother
@past dagger I think you can follow the first tutorial. You don't have to do this from the AudioManager. It complicates things a bit because then you'll need your UI script that reads the values from the sliders to reference the AudioManager to do all the volume changing.
You definitely don't want your AudioManager to manage UI related things
So where should my AudioMixerGroup variables be placed then? Not in the settings class right?
The AudioManager needs to know which groups to assign to the AudioSources it spawns, so only the AudioManager needs references to the groups.
So by that logic I should put the variables in the settings?
Is the AudioManager the settings?
No
If the AudioManager needs references to the groups, it needs variables for the groups
Yeah but should I put them within audiomanager like I've now
Or is that wrong?
The AudioManager looks fine to me now, except you don't need the two AudioMixer variables and they shouldn't be static
Ah okay, thanks