Happy Sunday! There's some extra code and extension methods in the repository that I didn't have time to include in the video, please check it out! And please add and comments and questions related to a follow up for Playlists and Music! 👍
Hi dear, was looking for channel that give tips and advanced techniques for Unity cuz must of them are for amateurs (with full respect) and do not respect clean code/architecture. But am having trouble while my projects grow over time and become more complex to manage and coupling problems. Those are topics I hope one day you will talk about them and show us the best practices: - Dialogue system. more as binary tree approach if we want player's choices driven dialogue. and how to set choices once the player load the game ? - UI. Saw you talked about Inventory, but in this case more about Setting UI for audio, video, language, ... and how to merge it with other UI like inventory and showing player states as an example. - Quest system. how to keep tracking of the player progress when scene changes ? and how to unlock events (spawn certain npcs/enemies/objects) associated to the specific quest once the current is completed (Side and main quest). - Tracking system. how npc can catch object that the player have to make specific actions/dialogue. - CutScene system. more focused in 2D games, how to implement robust cut scene old Pokemon games like (player following the npc to a position for example) and how to include dialogue into it (the cut scene)? Best regards and thank you for your effort.
@@chigo9679 Haha, well that’s a lot of requests. Too bad I can only make one video per week. In time, we’ll probably cover all those things you’ve requested. There is also a channel on the Discord server for requests if you think of anything else.
@@git-amend no rush at all. I subscribed and notifications is on if any video is uploaded cuz your channel is to valuable for an indie game dev. Keep Hoping you gona make those requests. Big thanks.
An additional optimisation for large projects: Create a ScriptableObject called SoundLibraryObject which holds references to all sounds in the game (private field with a public accessor). Each of these sounds are AudioSoundData. When applying a sound to an object, don't use SoundData, but instead use SoundLibraryObject and call the the SoundData from the library directly. What this means is that if you want to change a sound down the line, you don't need to hunt down the object it's attached to, instead just drag the sound into the sound library object, which will update everything automatically throughout your project. Excellent video. Learned a lot and those verbosity simplifications were very nice. I'm glad you showed the verbose version, then shortened it. I did have one question though, how do I change the parent object to which the sounds are spawned to. Currently it spawns to the SoundManager, but I have a child container in sound manager I want to spawn the sounds to and doing Instantiate(soundEmitterPrefab, container) doesn't seem to work. How would I set a custom container for the pool?
That's a great tip! Thanks for sharing! In regard to your question about setting a Parent, I would add an additional method to the Builder for that which defaults to the SoundManager, but can optionally be set.
Literally just got to the audio part of my little project and you make a video on the system. Thank you very much for your videos and explanations, as always!
@@git-amend Quick question if you don't mind. How would I go about stopping a specific sound. If for example I have a looping sound of a torch playing. I can activate and deactivate the torch and I would need to Play and Stop the emitter, what is the best way to handle it? Should I return a SoundEmitter in Play() method and then store reference to it in the torch script so I can Stop it whenever I need? or is there a better way to handle it? Thanks a ton for the video again.
@@bromanguy If you are playing all your sounds using SoundEmitters, then keeping a reference to it while active might be your best solution. However, also consider playing some audio without the pooling system if they are long running sounds like a torch. In this case, you could limit the size of your pool for the one shot sounds, but ensure that you still have enough voices configured in your settings to account for 10-20 long running audio clips in your scene as well. These looping or long running sounds could just be managed by the game objects that own them.
Another awesome video! I particularly appreciate how you show the design process at the beginning using the diagrams to show how you initially plan what each class will do/what data it will be responsible for, then showing how each class communicates with each other.
In programming i think the most important thing is Memory. I really want to see your perspective on this matter. - How can we use memory efficiently in Unity? - What is the gotchas or what should we avoid? - How can find our mistakes and profile it?
Absolutely gorgeous tutorial, I didn't knew about Unity's built-in ObjectPool, so thanks a lot!! About the code, i think it would be more SOLID to raise an event "onFire" and handle the SFX and VFX in its own class, like SFXCaller and VFX Caller. It's not big deal, I know, but since no one is saying it...
Thanks for the comment! You might like another video on this channel about building a Flyweight Factory which uses the Unity Object Pool in a slightly different way.
I never bothered with unitys ObjectPool class and always rewrote a new pool class for everything. I now see how easy it is to use. Great tutorial thanks !
Super cool tutorial about optimizing sounds! For your music and playlists follow up, I'd love to see how you go about triggering changes in music to deal with things like horizontal sequencing/vertical layering or stingers! Thanks for the amazing videos!
Hi, I think your videos are excellent, fantastic, best in class. Please make sure you look after yourself so you can keep uploading great content into the future. Don't feel pressured to keep pumping out videos at a high pace, please nurture your passion for your channel because it's great!
Hmm, this actually looks like a pretty simple refactor from my current audio managment. Little snip here, a little wrap there and poof! I dont think its really necessary for my current project but pooling audio seems like a cool optimization. Its nice to have a quick little audio solition to drop into a new project, and thanks to another recent video i can do that too!
Great video! I think also having a minimum time between instances could be a useful addition. That way sounds can't play at the exact same time and have their amplitudes stack (resulting in clipping). Also, randomization of volume can be a subtle but useful parameter.
We'll see. This video did not do quite as well as I had hoped. In the meantime, I did add some code to the repository for a Music Manager, check it out!
Recent Subscriber here. Really appreciate Your content and Your delivery of said content. As an Audio Designer, I have some notes: - You could define a WaitForSecondsRealtime = new(clip.length) for the Coroutine, execute playback AND pre-set "NextPitch" in it. It might seem trivial but I go by "Shoot, Reload" order where A sound is ready to just "Play", and after each play the cylinder is rolled. Might be my DAW head seeing a line of code as plugin latency. - My personal issue with pools: I really don't like creating / destroying AudioSources, so I instead go for a "Manual Voice Limit approach" where I have a SoundEmitter[] and a "SoundEmitter GetNext()" method to cycle through the collection. This would brute force a voice count. In Your example - at the firing rate of fire of 3 turrets - we wouldn't notice when one Emitter is stopped and retriggered.
@@git-amend for sequences, consider AudioSource.PlayScheduled(). In a for loop you could assign a "batch" of emitters to play a sequence. Dynamic UI notifications based on some params, music, You name it
Amazing video ! A definitive go-to guide for Game Sounds :) BTW , a very very small nitpick. Wouldn't pitch always be moving? Shouldn't it just be .pitch = rather than .pitch += ?
Glad you only covered what you did. Adding playlists and music would have been too much. I understand that these videos take a lot to make. I will support you more when my wallet lets me. Thanks.
Amazing video as always! Tweaked your implementation to allow for random and sequential sound playing, as well as syncronized multiple audio clips. One thing that I'm wondering: - Wouldn't a ScriptableObject be better than a Serializable for the SoundData? Many times the same SFX is applied to multiple game objects, so using a ScriptableObject would be generally better in terms of performance and memory efficiency. right? Or am I missing something here? Thanks!
Nice, glad you ran with it. In regard to SOs, I think you need to evaluate that based on your project. Either way is good, but if you are reusing the same ones often then SOs are a great alternative to what's done in the video.
Hi @git-amend ! Thank you for the great tutorials. It would be awesome to get some kind of license on your code. Like could you add that to the github repos?
I've been adding licenses as I have time or when I feel it's necessary. Since the code is primarily what is shown in the RU-vid videos, you can assume it is free to use without restriction. The goal is to help you improve as a programmer, and I hope you take what you learn here and make it your own.
I love your videos and learning many interesting details with each one. I noted you've creating new SoundBuilder with each call. Will not it lead to memory leaks or am I missing something ?
Great video! I am curious, I wanted to use Scriptable Objects instead of serializing the SoundData class the way you did in the video. Afaik it seems fine to literally just make that class into a scriptable object class without really changing much. Is there a problem if I do that? The only thing I wasnt sure about is the soundcount dictionary, but it seems to work fine.
With frequent sound, you enqueue every time sound played. But dequeue only happened when the queue count greater than max sound instances. I think we should also dequeue when sound emitter stop/return to pool right?
That's a good point. To implement something like that we could use a different data structure, like a Linked List. I'll see about adding an optimization to the repository. Cheers!
Hey pal! very great implementation tho but dont u think this system's complexity might be overkill for simple audio needs? like for games with straightforward audio requirements, this system might introduce unnecessary overhead??
Wow, the video tutorial is great and I have 2 questions 1. In a two-sided battle with 50 enemies on each side and holding guns, if each soldier made a sound it would be very annoying and unnecessary (so what should I do when handling this situation) 2. I see in your script that using IEnumerator and creating Audio Sources will reduce performance compared to using Audio sources and calling PlayOneShot? Thank !
Thanks for the comment. In regard to #1, I would implement a throttle on that particular sound similar to what I did with 'FrequentSounds' but limit that particular sound clip to only play 2-3 at any given time. You could do that with something like Dictionary - then you would have a queue for specific sounds, and limit it's capacity to a specific amount, just like in the video. That way you can take total control of those particular sounds that are being played by too many units. For #2, I'm not totally sure what you mean, but PlayOneShot can be useful too because you can play more than one clip from one AudioSource. However, if the GameObject containing that AudioSource is destroyed, you'll lose any audio it was playing. So, you could still use pooled AudioSources and combine with PlayOneShot if your game required it.
Tonight I implemented a Linked List as a small improvement over using a Queue, have a look at the repository and see if it gives you any ideas. In this version a SoundEmitter will keep a reference to it's own Node in the list so it can remove itself when it Stops playing in O(1) time. You could still use a Dictionary to keep track of how many counts of each SFX are playing at a given time as well.
Even though the example in the video is just one SFX to keep it easy to understand, try to picture in your minds eye how handing 100 different SFX might require a more complex solution.
2 week later I'm rewatching your video because I need to play hundreds of same sound in short time. Don't get me wrong, you do advanced things, but sometimes I've got feelings you overcomplicate things. Complicated or not - it's useful.
Maybe, but this video has not really resonated with my audience, as I suspected. Just like UI, things like audio and memory profiling are an afterthought for most people. However, I might still make one - but in case I don't, I did put some helpful code in the repository so that you can kick start your own Music management system.
2 месяца назад
I'll follow, in case you change your mind. Anyway, keep up amazing work man!
@@git-amend I really hope you build on this video at some point. Really appreciated this one. I've dabbled in FMOD but it seems like overkill for my purposes but resources for handling audio in a clean and scalable way in Unity seem to be few and far in between. It's all just "here's how to play a sound, go nuts". In any case, thanks for including the MusicManager in the repo!