Search Unity

AudioMixer.SetFloat doesn't work on Awake

Discussion in 'Audio & Video' started by Rodolfo-Rubens, May 6, 2015.

  1. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
  2. gregzo

    gregzo

    Joined:
    Dec 17, 2011
    Posts:
    795
    Yep, filing a bug report and voting on the issue is all you can do really.

    Also, wrap your audio initialization in a aptly named method and call that from Start if you haven't already done that.
     
  3. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    Wth, this post is mine and I'm having the same problem as 2 years ago. smh.
     
  4. Stents

    Stents

    Joined:
    Jan 23, 2014
    Posts:
    18
    Mmm would be good if this was at least noted in the docs or something. Ran into this issue and spent an hour trying to debug it, only to find that it was a unity bug.
     
    Rodolfo-Rubens likes this.
  5. GfK

    GfK

    Joined:
    Aug 15, 2014
    Posts:
    107
    Same - just filed (yet another) bug report to that effect. I can't see why SetFloat would work from Start(), but NOT from Awake(). If it is intended behaviour then it would be nice to receive a warning, or a mention of it in the documentation.

    On a related note, it would also be nice if it was mentioned somewhere that the second parameter of SetFloat is meant to be in decibels, and not as logic would dictate (0 for "off" and "1" for full loud).

    Sometimes, I wish the Unity documentation had a face, then I'd have something to punch over oddities like this.
     
    deeprest likes this.
  6. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    Just encountered this when trying to load settings on Awake. However, it seems to work fine in builds.
     
  7. blueteak

    blueteak

    Joined:
    Feb 19, 2013
    Posts:
    140
    @GfK - Here's a bit of conversion code to use 0-1 volume translated to decibels.

    Code (CSharp):
    1. public void SetMasterVol(float vol) //vol: 0 - 1
    2. {
    3.     vol = (1 - Mathf.Sqrt(vol)) * -80f;
    4.     mixer.SetFloat("masterVol", vol);
    5. }
     
    HeyBishop, CleverAI and Olipool like this.
  8. imphenzia

    imphenzia

    Joined:
    Jun 28, 2011
    Posts:
    413
    Just to report that it doesn't work when set in OnEnable() either (which executes after Awake and before Start).

    My guess is that the internal works of the AudioMixer is resetting all attenuation to 0dB in it's own OnEnable() method. I will add a request for the AudioMixer documentation to clarify.
     
    Deleted User likes this.
  9. imphenzia

    imphenzia

    Joined:
    Jun 28, 2011
    Posts:
    413
    And if anyone needs to go the other way around:
    Code (CSharp):
    1. public float AttenuationToVol(float attenuation) //attenuation: -80 to 20
    2. {
    3.     return Mathf.Pow(-((vol / -80f) - 1f), 2f));
    4. }
     
    CleverAI and blueteak like this.
  10. mrmcduck

    mrmcduck

    Joined:
    Nov 26, 2015
    Posts:
    26
    Still not fixed in 2018.4 LTS.
    Workaround: Call method in Start() instead of Awake().
     
  11. tiggax

    tiggax

    Joined:
    Dec 29, 2017
    Posts:
    3
    It's wierd, i wrote a sound management script a year ago and the initialization of the float parameters for the audio mixer were called on the Awake() method, all worked well, i even tested the old project i wrote the script for, still worked.. now i am working on a new project and used that same script and got this problem, only works with the Start() method.

    Edit: Working on Unity 2018.3.0f2
     
  12. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    Hmm, August 2019 and this is still causing issues. I found this thread trying to figure out why my Ambient sounds were always at some blasting volume even when I set them in Awake().
     
  13. deeprest

    deeprest

    Joined:
    Jun 8, 2016
    Posts:
    17
    Unity 2019.2.6f1
    Bug still exists in November 2019, but only in the Editor.
    I've reported a bug for the editor. FogBugz link.
     
    Last edited: Nov 8, 2019
    Rabadash8820 and Aykutkaraca like this.
  14. Rabadash8820

    Rabadash8820

    Joined:
    Aug 20, 2015
    Posts:
    94
    From looking at the bug that @deeprest opened, apparently setting AudioMixer parameters in Awake is undefined behavior. The parameters must be set in Start. Weird...but there you have it.
     
  15. my_little_kafka

    my_little_kafka

    Joined:
    Feb 6, 2014
    Posts:
    87
    Won't it be possible to create a method to set the defalut values of the AudioMixer that could run from Awake?
    My entire framework initialises every system that can be configurable via loading a save file in Awake, all the input options, graphics options, language, accessibility - everything, but with audio I have to run a coroutine that runs after 0.01 seconds after the Awake in order to load the values from the save file. It's kinda hacky.
    Also, if it does work in builds, is it a defined behaviour? Like, can I make different methods to run if the game runs in editor and in the build, and it it's the build - will the changing of the values work in Awake flawlessly?
     
  16. deeprest

    deeprest

    Joined:
    Jun 8, 2016
    Posts:
    17
    If you load the settings file synchronously in Awake(), can you not apply the values in Start()? Start is called just before the first Update().
    I assume not. You must determine if it's worth your time to rely on "undefined behaviour". If it seems to work, then great, but it might not work for everyone/all platforms the same, so you might need to put time into fixing it later anyway.
    For the few audio settings I have, I handle them explicitly in Start(). Before this thread, I did something like the code below. We now know the #if directive should not be necessary, and is probably a bad idea.
    Code (CSharp):
    1.   void Start()
    2.   {
    3. #if UNITY_EDITOR
    4.     // workaround for Unity Editor bug where AudioMixer.SetFloat() does not work in Awake()
    5.     mixer.SetFloat( "MasterVolume", Util.DbFromNormalizedVolume( FloatSetting["MasterVolume"].Value ) );
    6.     mixer.SetFloat( "MusicVolume", Util.DbFromNormalizedVolume( FloatSetting["MusicVolume"].Value ) );
    7.     mixer.SetFloat( "SFXVolume", Util.DbFromNormalizedVolume( FloatSetting["SFXVolume"].Value ) );
    8. #endif
    9.   }
    I handle all settings generically in Awake(), then apply audio settings like this in Start().
     
    my_little_kafka likes this.
  17. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Ugh. I have different behaviour on two different scripts in the same project. In one script calling SetFloat(...) from Awake() is working fine, in another it's doing nothing.
     
  18. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Thanks for the link.

    It should be noted that the statements in the bug response and the docs page for AudioMixer.SetFloat(...) directly contradict each other. I gave feedback to that effect on the docs page, about to bug report it, too.
     
  19. NGC6543

    NGC6543

    Joined:
    Jun 3, 2015
    Posts:
    228
    Hey,
    If you have to use
    AudioMixer.SetFloat()
    on
    Awake()
    , try using async method instead.

    Code (CSharp):
    1.  
    2. using System.Threading.Tasks;
    3. void Awake()
    4. {
    5.     DelayedUpdateVolume();
    6. }
    7.  
    8.  
    9. async void DelayedUpdateVolume()
    10. {
    11.     await Task.Delay(100);
    12.     myAudioMixer.SetFloat("BGM", myVolume);
    13. }
    This async method still works even if the GameObject this script is attached to is disabled during Awake(), unlike Coroutine.
     
    Marrlie likes this.
  20. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,305
    This thread is *NOT* about initialization when object might be / will be / is disabled - that's a different - and thus unrelated - problem

    Moreover, shoving a Sleep is an band aid of the worst kind - it NEVER solves it properly
     
  21. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    True, in that case it is better to just call the SetFloat in Start since it is called right in the next frame.
     
    Last edited: Apr 24, 2020
  22. NGC6543

    NGC6543

    Joined:
    Jun 3, 2015
    Posts:
    228
    Yes, I just suggested an alternative workaround to that problem. It persisted long enough for me to wait for Unity to fix it
     
  23. Discipol

    Discipol

    Joined:
    May 6, 2015
    Posts:
    83
    2019.4.3f1 I just encountered this bug. Thanks to this thread for Start fix.
     
  24. r618

    r618

    Joined:
    Jan 19, 2009
    Posts:
    1,305
    well no - in that case it's better to sync your all game systems startup - including audio one - after some fixed delay
    so a timeout can (and until there's nothing better - should) be used, only not be specific to a single SetFloat on a specific mixer on a specific game object possibly in a specific scene and so on
    so @NGC6543 's code snippet shouldn't be taken literally but rather as an idea to solve the issue (which it does - unfortunately - good enough)
     
  25. NineCentGames

    NineCentGames

    Joined:
    Apr 23, 2020
    Posts:
    12
    I found a work around based on the information here in the 2019.4.5 LTS version. So thanks for that.

    But my goodness, I hope Unity fixes this... Maybe there is some reason why it's like this, but I haven't found anything.
     
  26. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    They responded to my bug report that they couldn't reproduce it and asking for a repro project. I've not had time to oblige.
     
    Rodolfo-Rubens and browne11 like this.
  27. browne11

    browne11

    Joined:
    Apr 30, 2015
    Posts:
    138
    Damn this bug! Just found it in 2019.4RST! Hours on hours of debugging. Send them this post, there is no need for a repo on this! Takes two seconds to setup and see it does not work.
     
    Lord_Eniac likes this.
  28. Liderangel

    Liderangel

    Joined:
    Jul 8, 2018
    Posts:
    101
    Bug is still here on 2019.4.1 LTS after 5 years.
     
    cdr9042 likes this.
  29. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    Hmm makes sense, but since I have an initialization scene, for me it works better to just call it on Start, I have no audio sources on this scene since it's loaded right after a bootstrap scene - so there is no risk of something playing an audio for 1 frame or something weird like that.
     
  30. Max_Bol

    Max_Bol

    Joined:
    May 12, 2014
    Posts:
    168
    In case some are still looking into this, the problem is not exactly with the SetFloat() of the AudioMixer as a few debug gave me the confirmation the the AudioMixer does indeed get the SetFloat() properly in its cache. The issue seems to be that the AudioMixer doesn't update (set) the property during a certain internal phase of the Unity's Awake() phase and simply skip it all alone if it is handled too soon. It's kinda like if the AudioMixer has some sort of "warmup" phase where anything cached during the early part of the Awake() which make it skips anything thrown at it.

    This could explains the kinda of hard-to-explain situation where, for some, the SetFloat() partially work.

    As of this moment, the only way of properly avoiding this issues is to force the SetFloat() to be done after the Awake() one way or another. Be it by setting it through the Start() or a coroutine with a tiny bit of wait or with a Delay.

    In case some are wondering, the problem is a per-scene issue as quick-switching scene doesn't fix the problem.
    Due to some double-layered checkup I set up in my project, a scene which is loaded twice doesn't fix the issue.

    To make it simple about what I'm writing about, it goes as this:
    Scene B is launched. During the Awake() in Scene B, something is missing (a reference is not found) which force the game stop the script after loading Scene A which contain the references (set on an object with DontDestroyOnLoad()) and then the game returns automatically to Scene B. During the 2nd visit in Scene B, the Awake() is called again and, this time, goes further as the past-missing reference is now found, but the SetFloat() doesn't get updated by the AudioMixer in the re-called Awake(). So, thinking about setting up a pre-load scene prior to your scene with the SetFloat() will mostly not work if it's in the Awake(). Just saying from my tests.
     
    Marrlie and Fewes like this.
  31. madscience2728

    madscience2728

    Joined:
    Sep 5, 2019
    Posts:
    5
    Yeah it's now 2021 this is my issue too....
     
  32. deeamezinapple

    deeamezinapple

    Joined:
    Nov 21, 2019
    Posts:
    1
    slap a coroutine with WaitForNextFrame then SetFloat. All I can say is unity gave up on this one, So you gotta wait for one frame and then SetFloat
     
  33. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    323
    I am also facing this bug o Unity 2020.2.3f1
     
    b3x2088 likes this.
  34. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    323
    This is "By Design" and won't be fixed!

    https://issuetracker.unity3d.com/product/unity/issues/guid/858150

    "As you can see the issue is resolved as By Design, meaning that this is expected behaviour for Unity. According to our developers "Awake is not the right place to apply the exposed values. This is because Awake gets called at many different times related to asset reloading in the editor slightly out of sync with the play state changes. On each play state, the editor will clear all exposed values, so this will override whatever values you applied in Awake(). You can easily fix this by moving your code to Start ()"."

    I really need this on Awake, so as a workaround made the Awake async and waited some time before setting the value.
    Code (csharp):
    1.  
    2. public async Awake()
    3. {
    4.    await Task.Delay(TimeSpan.FromSeconds(0.01f));
    5.    SetMixerValue();
    6. }
    7.  
     
  35. magehernan

    magehernan

    Joined:
    Jul 6, 2012
    Posts:
    7
    So... i am seen it on unity 2020.3.2f1
    I think the problem is the Snapshots, it has always minimum one and you can see it has a star.
    upload_2021-4-9_21-27-20.png
    When unity run it load the snapshot that have the star and set the values from it.

    I think the execution order afects this because if you load a scene then load the scene that has the script that on awake change the values it works fine.

    So another fix is load first a empty scene then it will work on awake.
     

    Attached Files:

    Nelson-William and ayhanavci like this.
  36. Ian_1337

    Ian_1337

    Joined:
    May 13, 2021
    Posts:
    49
    Thanks for the above!


    This works (I used this within my Main Menu)

    Code (CSharp):
    1.    
    2. using System.Threading.Tasks;
    3.  
    4.  private void Awake()
    5.     {
    6.         DelayedUpdateVolume();
    7.     }
    8.     async void DelayedUpdateVolume()
    9.     {
    10.         await Task.Delay(1);
    11.         UpdateMixer();
    12.     }
    13.  
    14.     void UpdateMixer() {
    15.         float masterValue = PlayerPrefs.GetFloat("mastervolume");
    16.         float soundValue = PlayerPrefs.GetFloat("volume");
    17.         float musicValue = PlayerPrefs.GetFloat("volume2");
    18.         audioMixer.SetFloat("mastervolume", masterValue);
    19.         audioMixer.SetFloat("volume", soundValue);
    20.         audioMixer.SetFloat("volume2", musicValue);
    21.     }
    My sliders are loaded first by LoadSettings() in the OnEnable.
     
    ms502040 and Rodolfo-Rubens like this.
  37. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    I just spent 2 hours debugging and searching google for this, with zero results. It wasn't until I googled SetFloat and Awake this finally showed up on the results. I wish they would fix this or at the very least, put it in the SetFloat() documentation!
     
    Last edited: Aug 24, 2021
  38. HeyBishop

    HeyBishop

    Joined:
    Jun 22, 2017
    Posts:
    238
    Zohmygosh. It is 2022.
    Seven years have gone by since this thread started.

    Fortunately, moving my initialization to Start() is fine.
     
    LeandroExHuMeD likes this.
  39. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    This is just one more of those Unity's pet bugs.
     
    HeyBishop likes this.
  40. triangle4studios

    triangle4studios

    Joined:
    Jun 28, 2020
    Posts:
    33
    Its simple. The mixer isn't yet initialized by the time unity calls awake. So settings get overwritten.
    Any of make a game? Then you know how many million lines of code goes into making this stuff. Cut them a break. I am here for the same problem, but I am not whining about it. I assume this was the issue and rather than plaguing an already busy company with my complaints, I will create my own work around. (Likely an enumerator that waits 1 second).
     
    Marrlie likes this.
  41. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    I will whin about it, the company I work for pay millions for the licensing and as a consumer we have the right to whin, and if we don't whin they won't improve. If you make a game and someone pay for them, they have the right to whin about an annoyance in your game. That's life.
     
  42. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    I personally see this as feedback. And seeing the number of people in this thread, it looks like a common issue. Reading the report, the issue was resolved "by design," so I don't expect to see this fixed. But I saw someone mentioning that it should at the very least be in the doc, which I agree with. I will check if I can add this behavior in the doc so other people don't waste their time finding this thread.
     
  43. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    _geo__ and mitaywalle like this.
  44. CCrowell

    CCrowell

    Joined:
    Mar 31, 2022
    Posts:
    9
    Wow. I feel like that's pretty short sighted to not assume people would want to set volume settings in Awake. I can't believe the problem has persisted for this long.
     
    angrypenguin likes this.
  45. OhiraKyou

    OhiraKyou

    Joined:
    Mar 27, 2012
    Posts:
    259
    This problem certainly sits in an awkward space, but it has its reasons and solutions.

    The orthodox method is to always initialize in isolation in Awake and only interface with other systems in Start (at which point one can assume other systems have also initialized). The Awake documentation specifically discourage reliance on Awake execution order in favor of only initializing in Awake and interfacing with other systems in Start. It should come as no surprise, then, that another system (the audio system) may not yet be initialized when one tries to use it in Awake. Or, rather, that its initialization order is inconsistent.

    It is, however, still important for volume to be set before another script attempts to play audio. So, it feels a bit like deferred initialization. Or, perhaps, post-processing of the audio system's initialization. More likely, it may simply feel as if the audio system, being important and built-in, isn't a system that should follow these initialization rules in the first place. I would suggest not considering it as such, to make it easier to switch to audio system packages that aren't built-in. And, a lot of important Unity systems aren't built-in anymore due to the move toward modular packages accessible through the package manager.

    In any case, it's still interfacing with another system. And, this sort of problem always crops up when one system's initialization depends on that of another. Normally, one would use custom events (such as UnityEvents) that one has full control over to reusably drive local execution order in these cases. But, without being able to initialize a system on demand as part of a custom event list, we must fall back to the script execution order, which is a global implementation of the same concept.

    So, a reasonable solution is to simply set a negative script execution order for a volume loader script in the project settings (before any script that plays audio). Then, Start should work as an effective post-initialization step that still runs before other audio consumers. Setting a positive execution order offset and using Awake may work similarly (if the audio mixer is using Awake for initialization), but, as previously stated, using Start is the orthodox approach to system interfacing.
     
  46. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    The initialisation rules you're referring to are specifically talking about scripts on GameObjects, and specifically in the context of the Awake() order being non-determistic. Emphasis mine:
    They're not talking about systems, and if what they're saying applies more broadly then they need to say so. Keep in mind also that an AudioMixer is represented as an Asset which exists independently of any Scene. And, I don't recall ever having this issue with any other Unity system or with any other asset type. It seems to be a weird quirk with AudioMixers in particular.

    I admit that I do delay any external interfacing to Start wherever I can, so it's possible that this is a thing elsewhere and I just haven't run into it. But in that case I'd still expect to be well aware of it via the documentation, which I'm not.

    If it's what we have to do then so be it, but I see it far more as a "workaround" than a "reasonable solution". A solution wouldn't just let us eventually get the job done, it'd stop people from running into the issue and spending time on it to begin with. Wanting an AudioMixer to start with a particular setting is pretty common, so giving us a way to set that through script in Awake(), even if it's not via SetFloat(), would be the way to go. At the same time, if SetFloat() is intentionally not to be used in Awake() then:
    a) it needs to be clearly documented for all relevant functions with a pointer towards the intended solution, and
    b) ideally, it ought to raise errors / warnings in the Editor console if we do it anyway**.

    * Though here's another end-user "workaround" to consider: disable the Audio package and import FMOD or another audio library of your choice, get direct access to everything. Of course that's only a productive thing to do if you also need the other functionality that gets you.

    ** Because, honestly now, who's going to read the docs for something as innocuously named as "SetFloat" before they run into trouble with it? So we should be actively informed at the time of need, which Unity does do elsewhere.
     
  47. nomadic

    nomadic

    Joined:
    Mar 4, 2010
    Posts:
    44
    If this lazy design is acceptable then please at least document the unintuitive behavior in the scripting reference.
     
    mitaywalle and angrypenguin like this.
  48. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Is Unity documentation team still using paper mails or pigeons? One year passed and even if we assume you are the only one who submited "information missing" feedback, it takes way too long and information is still not there...
     
  49. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,338
  50. The_Island

    The_Island

    Unity Technologies

    Joined:
    Jun 1, 2021
    Posts:
    502
    Yeah. They do fix some documentation, but they are also helping all teams at Unity simultaneously. And to be fair, I would like to blame them, but it should be our team's job to keep the documentation quality high and not another team's.

    So thanks, @Qriva, for reminding me. I asked around, learned the process, and made the changes in 2023.2. I need to find out how they do backporting, but I plan to get it done this week. I know there is nothing to celebrate about doing the bare minimum. But since I know how to do it now, I will try to do it more often when I have time between bug fixes. If you have anything else you would like to see in the Audio/Video docs, please share it here or in another thread. I will try to do them. :)
     
    Last edited: May 2, 2023