{"id":87477,"date":"2020-06-30T15:54:10","date_gmt":"2020-06-30T15:54:10","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=87477"},"modified":"2021-07-29T19:44:03","modified_gmt":"2021-07-29T19:44:03","slug":"how-to-create-a-settings-menu-in-unity","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/how-to-create-a-settings-menu-in-unity\/","title":{"rendered":"How to Create a Settings Menu in Unity"},"content":{"rendered":"<p>Virtually every game you play, especially on a personal computer, allows you to change the graphics settings to get the best performance and appearance you can on your device. These games save those settings and then reload them whenever the user reopens the project. Perhaps you might be wondering how it does all that? In the case of a typical Unity project, this is done by accessing the quality settings and changing the values to match with the player&#8217;s selection. Saving those settings is also simple by utilizing the Unity Player Preferences system. This method of saving data and preferences has been discussed before in <a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/c-programming\/saving-game-data-with-unity\/\">this article<\/a>.<\/p>\n<p>Soon to follow is a tutorial showing how you access these parameters and allow the user to change them at their leisure. There are options for selecting a quality preset, where the game automatically chooses settings based on how nice the user wants the game to look, as well as options for setting the game to windowed or fullscreen. They&#8217;ll also be able to select the exact anti-aliasing and texture quality preferences they have as well as the resolution and the master volume. While these aren\u2019t all the options the user can change, this article should give any Unity developer an idea of how to create a graphics settings menu.<\/p>\n<p>As there are quite a few moving parts outside of the code, this tutorial is primarily focusing on the coding work involved in making a settings menu. You can use the codeless template below to follow along or recreate the user interface seen in the article yourself. An introduction to creating a user interface is detailed <a href=\"https:\/\/www.red-gate.com\/simple-talk\/dotnet\/c-programming\/using-unity-ui-and-c-to-create-a-tic-tac-toe-game\/\">here<\/a>. The template and complete version of the project also has music included for testing the master volume settings once it is programmed and ready. This music was created by Kevin MacLeod, and more info on it can be found directly below.<\/p>\n<p>Music credit:<\/p>\n<p>Night In Venice by Kevin MacLeod<\/p>\n<p>Link: <a href=\"https:\/\/incompetech.filmmusic.io\/song\/5763-night-in-venice\">https:\/\/incompetech.filmmusic.io\/song\/5763-night-in-venice<\/a><\/p>\n<p>License: <a href=\"http:\/\/creativecommons.org\/licenses\/by\/4.0\/\">http:\/\/creativecommons.org\/licenses\/by\/4.0\/<\/a><\/p>\n<p>Of course, if you prefer a song from your own computer, feel free to use it. In addition, the project borrows a stone texture created by LowlyPoly. That asset can be viewed in the Unity Asset Store <a href=\"https:\/\/assetstore.unity.com\/packages\/2d\/textures-materials\/floors\/hand-painted-stone-texture-73949\">here<\/a>. This asset is included in both the <a href=\"https:\/\/github.com\/prof-smash\/SettingsMenu-codeless\">template<\/a> and the <a href=\"https:\/\/github.com\/prof-smash\/SettingsMenu-Complete\">complete project<\/a> when downloaded from the links below.<\/p>\n<h2>Project Overview<\/h2>\n<p>To load an already existing project, click the <em>Add <\/em>button in the Unity Hub and navigate to the project in the dialog that appears. Select the folder containing the project, then click <em>Select Folder<\/em>.<\/p>\n<p>First, here\u2019s a quick overview of the project. From the start, you should see an already completed user interface shown in Figure 1, created using Unity&#8217;s default assets, with all the settings that can be changed. Next to it is a sphere object with the stone texture applied. This image has been included to help the user better tell the differences between the different settings.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"243\" class=\"wp-image-87478\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-46.png\" \/><\/p>\n<p><strong>Figure 1: The Graphics Settings menu<\/strong><\/p>\n<p>The menu should consist of four drop-downs, a checkbox, and a slider. The drop-down for selecting resolutions has a few options already, but they are mere placeholders and can be ignored as Unity is capable of automatically filling in all resolution options available to the user. Options in the other three drop-downs all correspond to their respective Unity graphics settings. It has already been done, but if you were to recreate this menu from scratch, you would need to take care to match the order of drop-down options (except the resolution drop-down) with the order of options seen in the Unity settings. That order can be seen by clicking <em>Edit-&gt;ProjectSettings <\/em>then, in the window that appears (Figure 2), selecting <em>Quality <\/em>on the right-hand side.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"567\" class=\"wp-image-87479\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-23.jpeg\" \/><\/p>\n<p><strong>Figure 2: The project&#8217;s visual quality settings.<\/strong><\/p>\n<p>If you wish to set the default quality preset, you can do so by clicking the <em>Default <\/em>arrows matching with the build type (PC, Android, etc.) and selecting the preset. If downloading the projects from the Github links, the presets will have been modified to give each option more definition. For instance, by default, the <em>Very Low <\/em>preset&#8217;s <em>Texture Quality <\/em>is at half resolution, but the template has it set to eighth resolution. Feel free to edit them to your liking, but it is not required. You can also see individual settings, such as <em>Texture Quality <\/em>and <em>Anti Aliasing,<\/em> further down which this project allows the user to change. There are plenty of other settings here as well, but for the purpose of this tutorial, the options the user can change are limited to just a few. Accessing the other options in code is simple and will be explained in the coding section.<\/p>\n<p>At the bottom is the master volume slider, which works a little differently from the other settings. Manipulating this slider changes the volume of the <em>MainAudio <\/em>audio mixer seen in the <em>Assets <\/em>window. If you were to double-click this asset, the <em>Assets <\/em>window would change to an <em>Audio Mixer <\/em>window where you could change audio settings from there. If building all this from scratch, you would create an audio mixer using right-click context menu in the <em>Assets <\/em>window, expose the <em>Volume <\/em>parameter, then link that with the <em>AudioSource <\/em>game object with the <em>Output <\/em>field.<\/p>\n<p>Finally, there are two buttons on the left side of the menu, one for saving settings and one for closing the game. Between these two buttons, the save button is where most of your attention will go. As mentioned above, the Player Preferences system is used to save graphics settings. When the user reloads the project, any settings they saved are loaded according to their saved preferences.<\/p>\n<p>Feel free to click around the editor and check out the other objects hidden under <em>UI <\/em>in the <em>Hierarchy <\/em>to get a better feel for what all the different objects are. When you&#8217;re ready, double-click the <em>SettingsMenu <\/em>script asset in the <em>Assets <\/em>window to begin the coding process.<\/p>\n<h2>SettingsMenu<\/h2>\n<p>To start, you&#8217;ll need the following using statements to accomplish everything this project sets out to do. Most of these should appear at the top of the script by default, but, to be safe, each one is listed.<\/p>\n<pre class=\"lang:c# theme:vs2012\">using System;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\nusing UnityEngine.Audio;\r\nusing UnityEngine.UI;<\/pre>\n<p>Within the class itself, you&#8217;ll need to be able to reference many of the objects within the settings menu. You also need to be able to change the volume of the audio mixer. Finally, two private variables are declared. The first is a float called <code>currentVolume<\/code><em>, <\/em>which, as the name implies, stores the current volume. This variable primarily exists for saving purposes, since it&#8217;s unfortunately not easy to get the current volume of the <em>MainAudio <\/em>mixer. Next comes an array of resolutions. Remember when it was said that Unity automatically detects the possible resolutions for a user and fills out the drop-down from there? Those resolutions will be stored inside this array to be used later.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public AudioMixer audioMixer;\r\npublic Dropdown resolutionDropdown;\r\npublic Dropdown qualityDropdown;\r\npublic Dropdown textureDropdown;\r\npublic Dropdown aaDropdown;\r\npublic Slider volumeSlider;\r\nfloat currentVolume;\r\nResolution[] resolutions;<\/pre>\n<p>Finally, the default <code>Update<\/code> method can be commented out or deleted, but keep the <em>Start <\/em>method. You&#8217;ll be coming back to this method later.<\/p>\n<p>Now comes the time to begin properly coding the different methods that make this menu tick. A good place to start would be the <code>SetVolume<\/code> and <code>SetFullscreen<\/code> methods.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void SetVolume(float volume)\r\n{\r\n\taudioMixer.SetFloat(\"Volume\", volume);\r\n\tcurrentVolume = volume;\r\n}\r\npublic void SetFullscreen(bool isFullscreen)\r\n{\r\n\tScreen.fullScreen = isFullscreen;\r\n}<\/pre>\n<p>As you can see, the act of changing the settings is quite simple. In both methods, the actual change is occurring in just a single line. With <code>SetVolume<\/code><em>, <\/em>you get the <code>audioMixer's<\/code> <code>SetFloat<\/code> method and pass in the <em>volume <\/em>parameter. How does Unity get this value? In the editor, the volume slider is given this method for its <code>OnValueChanged<\/code> event. In doing so, the slider is told that its current value is passed into <code>SetVolume's<\/code> <code>volume<\/code> parameter, thus providing the <code>audioMixer<\/code> with the new master volume value to be changed to. Finally, <code>currentVolume<\/code> is given the value of <em>volume <\/em>to hang onto whenever the user saves their settings.<\/p>\n<p><code>SetFullscreen<\/code> has the same idea, but with one less line of code. Additionally, it also gets the Unity <code>Screen<\/code> class, and then the <code>fullScreen<\/code> boolean variable from there. Like with <code>SetVolume<\/code>, the <code>fullScreen<\/code> value is changed according to the value passed into the <code>isFullscreen<\/code> parameter, which gets its value from whatever the current value of the <code>FullscreenToggle<\/code> checkbox in the user interface.<\/p>\n<p>Next up is <code>SetResolution<\/code>, which puts the <code>resolutions<\/code> array declared earlier to use:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void SetResolution(int resolutionIndex)\r\n{\r\n\tResolution resolution = resolutions[resolutionIndex];\r\n\tScreen.SetResolution(resolution.width, \r\n              resolution.height, Screen.fullScreen);\r\n}<\/pre>\n<p>Similar to the previous two methods, <code>SetResolution<\/code> uses a value passed in from the corresponding drop-down. The current resolution is then set using the <code>resolutionIndex<\/code> parameter, before passing the exact width and height of that resolution into <code>Screen's<\/code> <code>SetResolution<\/code> method.<\/p>\n<p>The next two methods, <code>SetTextureQuality<\/code> and <code>SetAntiAliasing<\/code> are similar to each other in that they both call the <code>QualitySettings<\/code> class and change a value within that class. In addition, they both get the quality preset drop-down choice and set it to the value of six, which in this case would be the \u201ccustom\u201d option.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void SetTextureQuality(int textureIndex)\r\n{\r\n\tQualitySettings.masterTextureLimit = textureIndex;\r\n\tqualityDropdown.value = 6;\r\n}\r\npublic void SetAntiAliasing(int aaIndex)\r\n{\r\n\tQualitySettings.antiAliasing = aaIndex;\r\n\tqualityDropdown.value = 6;\r\n}<\/pre>\n<p>Speaking of the quality presets, the last major method for this settings menu is for the quality preset drop-down. This one has a few more steps to it than the others, but the reasons are a little strange. If you changed the quality settings presets when in the <em>Project Settings <\/em>window, you may need to adjust these values.<\/p>\n<pre class=\"lang:c# theme:vs2012 \">public void SetQuality(int qualityIndex)\r\n{\r\n\tif (qualityIndex != 6) \/\/ if the user is not using \r\n                               \/\/any of the presets\r\n\t\tQualitySettings.SetQualityLevel(qualityIndex);\r\n\tswitch (qualityIndex)\r\n\t{\r\n\t\tcase 0: \/\/ quality level - very low\r\n\t\t\ttextureDropdown.value = 3;\r\n\t\t\taaDropdown.value = 0;\r\n\t\t\tbreak;\r\n\t\tcase 1: \/\/ quality level - low\r\n\t\t\ttextureDropdown.value = 2;\r\n\t\t\taaDropdown.value = 0;\r\n\t\t\tbreak;\r\n\t\tcase 2: \/\/ quality level - medium\r\n\t\t\ttextureDropdown.value = 1;\r\n\t\t\taaDropdown.value = 0;\r\n\t\t\tbreak;\r\n\t\tcase 3: \/\/ quality level - high\r\n\t\t\ttextureDropdown.value = 0;\r\n\t\t\taaDropdown.value = 0;\r\n\t\t\tbreak;\r\n\t\tcase 4: \/\/ quality level - very high\r\n\t\t\ttextureDropdown.value = 0;\r\n\t\t\taaDropdown.value = 1;\r\n\t\t\tbreak;\r\n\t\tcase 5: \/\/ quality level - ultra\r\n\t\t\ttextureDropdown.value = 0;\r\n\t\t\taaDropdown.value = 2;\r\n\t\t\tbreak;\r\n\t}\r\n        \r\n\tqualityDropdown.value = qualityIndex;\r\n}<\/pre>\n<p>To start, you first check if the user selected the \u201ccustom\u201d option. If they did, then there would typically be no reason to change the settings because the user is indicating they want to tweak the individual values themselves. But otherwise, the game sets the quality level preset to the user&#8217;s selection. Next comes a switch statement that changes the values of the texture quality and anti-aliasing drop-down boxes depending on which option the user selected.<\/p>\n<p>Why bother with this? It is, admittedly, a little inelegant. This is done to update the drop-downs to show what the option is currently set to in code after selecting the preset. Without it, the drop-downs would show incorrect information. It would be inaccurate to say anti-aliasing is disabled when the \u201cultra\u201d option is chosen without changing some information in the editor itself. On top of that, at the very end of the method, the <code>qualityDropdown<\/code> value is set to <code>qualityIndex<\/code>. What&#8217;s the point when the user already selected this? When changing the values of the texture quality and anti-aliasing drop-downs, the <code>SetAntiAliasing<\/code> and <code>SetTextureQuality<\/code> methods wind up being called. Remember that they&#8217;re called whenever the value is changed. When this happens, the quality preset menu changes to say \u201ccustom\u201d which would not be correct in this instance, so it sets the drop-down to show what the user actually selected. It looks like the code runs the risk of firing over and over again due to all the value changes, but in testing this code, nothing of the sort occurred. As mentioned, though, it is a little \u201chacky.\u201d<\/p>\n<p>With all these methods created, the user can now change their game&#8217;s settings to their liking. Now you just need to permit them to save the settings and exit the game. In addition, the project needs to be able to load the saved settings. Best to start with the two remaining buttons. The exit game button is very simple, as it only has one line of code. Saving, on the other hand, is a little more involved.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void ExitGame()\r\n{\r\n\tApplication.Quit();\r\n}\r\npublic void SaveSettings()\r\n{\r\n\tPlayerPrefs.SetInt(\"QualitySettingPreference\", \r\n               qualityDropdown.value);\r\n\tPlayerPrefs.SetInt(\"ResolutionPreference\", \r\n               resolutionDropdown.value);\r\n\tPlayerPrefs.SetInt(\"TextureQualityPreference\", \r\n               textureDropdown.value);\r\n\tPlayerPrefs.SetInt(\"AntiAliasingPreference\", \r\n               aaDropdown.value);\r\n\tPlayerPrefs.SetInt(\"FullscreenPreference\", \r\n               Convert.ToInt32(Screen.fullScreen));\r\n\tPlayerPrefs.SetFloat(\"VolumePreference\", \r\n               currentVolume); \r\n}<\/pre>\n<p>As promised, the Player Preferences are being used to save the user&#8217;s preferred settings. Doing so requires creating a key with an attached value. The key can be named anything you like, and the value comes from any variable. In this case, each key is a string with a name that corresponds to its setting, and the current option selected in the various drop-downs are assigned to those keys. The last two keys, <code>FullscreenPreference<\/code> and <code>VolumePreference<\/code>, are a little different from the others. Since <code>Screen.fullScreen<\/code> is a boolean, you need to convert it to an integer. This is because Player Preferences can only save an integer, float, or string. Meanwhile, <code>VolumePreference<\/code>, a float, is simply being given the <code>currentVolume<\/code> variable you&#8217;ve been hanging on to.<\/p>\n<p>The next method, <code>LoadSettings<\/code>, is very much like <code>SaveSettings<\/code> but in reverse. Using Player Preferences, you search for a key with a matching name. If there is one, you get the value of that key and assign it to the drop-down value. And since the game settings change the moment their corresponding menu values change, the graphics and volume settings changes immediately according to the user&#8217;s saved preferences. Of course, if there is no saved setting, then a default value is assigned.<\/p>\n<pre class=\"lang:c# theme:vs2012\">public void LoadSettings(int currentResolutionIndex)\r\n{\r\n\tif (PlayerPrefs.HasKey(\"QualitySettingPreference\"))\r\n\t\tqualityDropdown.value = \r\n                     PlayerPrefs.GetInt(\"QualitySettingPreference\");\r\n\telse\r\n\t\tqualityDropdown.value = 3;\r\n\tif (PlayerPrefs.HasKey(\"ResolutionPreference\"))\r\n\t\tresolutionDropdown.value = \r\n                     PlayerPrefs.GetInt(\"ResolutionPreference\");\r\n\telse\r\n\t\tresolutionDropdown.value = currentResolutionIndex;\r\n\tif (PlayerPrefs.HasKey(\"TextureQualityPreference\"))\r\n\t\ttextureDropdown.value = \r\n                     PlayerPrefs.GetInt(\"TextureQualityPreference\");\r\n\telse\r\n\t\ttextureDropdown.value = 0;\r\n\tif (PlayerPrefs.HasKey(\"AntiAliasingPreference\"))\r\n\t\taaDropdown.value = \r\n                     PlayerPrefs.GetInt(\"AntiAliasingPreference\");\r\n\telse\r\n\t\taaDropdown.value = 1;\r\n\tif (PlayerPrefs.HasKey(\"FullscreenPreference\"))\r\n\t\tScreen.fullScreen = \r\n        Convert.ToBoolean(PlayerPrefs.GetInt(\"FullscreenPreference\"));\r\n\telse\r\n\t\tScreen.fullScreen = true;\r\n\tif (PlayerPrefs.HasKey(\"VolumePreference\"))\r\n\t\tvolumeSlider.value = \r\n                    PlayerPrefs.GetFloat(\"VolumePreference\");\r\n\telse\r\n\t\tvolumeSlider.value = \r\n                    PlayerPrefs.GetFloat(\"VolumePreference\");\r\n}<\/pre>\n<p>Finally, it&#8217;s time to return to the <code>Start<\/code> method left alone earlier. All remaining code from here on goes inside this method. As mentioned before, Unity is capable of getting a list of all possible resolution options available to the user and filling in the resolution drop-down with those options. To do that, you first need to clear the placeholder list, create a new list of strings, and set the <code>resolutions<\/code> array to hold all the possible resolutions available. In addition, you&#8217;ll also create a new integer named <code>currentResolutionIndex<\/code> for use in selecting a resolution that matches the current user&#8217;s screen.<\/p>\n<pre class=\"lang:c# theme:vs2012\">resolutionDropdown.ClearOptions();\r\nList&lt;string&gt; options = new List&lt;string&gt;();\r\nresolutions = Screen.resolutions;\r\nint currentResolutionIndex = 0;<\/pre>\n<p>In order to find a matching resolution and assign it, you&#8217;ll need to loop through the <code>resolutions<\/code> array and compare the resolution width and height to the user&#8217;s screen width and height to find a match. While you&#8217;re at it, you&#8217;ll also add every resolution option to the <code>options<\/code> list.<\/p>\n<pre class=\"lang:c# theme:vs2012  \">for (int i = 0; i &lt; resolutions.Length; i++)\r\n{\r\n\tstring option = resolutions[i].width + \" x \" + \r\n             resolutions[i].height;\r\n\toptions.Add(option);\r\n\tif (resolutions[i].width == Screen.currentResolution.width \r\n          &amp;&amp; resolutions[i].height == Screen.currentResolution.height)\r\n\t\tcurrentResolutionIndex = i;\r\n}<\/pre>\n<p>With the list created and a matching resolution found, the only task remaining is to update the resolution drop-down with the new options available and call <code>LoadSettings<\/code> to load any saved settings. You&#8217;ll also pass in <code>currentResolutionIndex<\/code> into <code>LoadSettings<\/code> to be used in case a saved resolution preference was not found.<\/p>\n<pre class=\"lang:c# theme:vs2012\">resolutionDropdown.AddOptions(options);\r\nresolutionDropdown.RefreshShownValue();\r\nLoadSettings(currentResolutionIndex);<\/pre>\n<p>Adding this code not only completes the <em>Start <\/em>method, but also completes the entire script. While many of the individual methods act similarly to each other, the specifics are a little different with each one, thus creating a lot to go through. However, this code won&#8217;t do anything without being assigned to the different user interface elements first. Complete that, and the project will be finished. Remember to save your work if you haven&#8217;t already!<\/p>\n<h2>Final Tasks<\/h2>\n<p>To assign the different methods to their respective UI elements, you first must make sure the <em>UI <\/em>object is expanded to show all child objects in the <em>Hierarchy<\/em>. This is done by clicking the small arrow next to the <em>UI <\/em>object. From here, the process for assigning methods to menu elements is largely the same for each element. The following assigns the <em>ResolutionDropdownMenu <\/em>object to its respective method. First, select the object and scroll down in the <em>Inspector <\/em>window until you find the <em>On Value Changed <\/em>event list. Once found, click the small plus button on the lower right corner of the list to add a new event as shown in Figure 3.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"939\" height=\"578\" class=\"wp-image-87480\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-24.jpeg\" \/><\/p>\n<p><strong>Figure 3: Creating a new <em>On Value Changed <\/em>event.<\/strong><\/p>\n<p>Click and drag <em>UI <\/em>from the <em>Hierarchy <\/em>into the object field. Doing this allows you to use functions from the <em>SettingsMenu <\/em>script currently attached to <em>UI<\/em>. Note that the template should have the <em>SettingsMenu <\/em>attached in advance. If doing from scratch, you&#8217;d simply select <em>UI <\/em>and drag the <em>SettingsMenu <\/em>script onto it as shown in Figure 4.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"939\" height=\"578\" class=\"wp-image-87481\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-25.jpeg\" \/><\/p>\n<p><strong>Figure 4: Setting the object field in the event.<\/strong><\/p>\n<p>Next, click the drop-down that currently says <em>No Function<\/em>. Navigate to <em>SettingsMenu <\/em>to show more options. You&#8217;ll need to select the <em>SetResolution <\/em>option, but there are two of them. Selecting the one under <em>Static Parameters <\/em>would create a new field in the event list where you can enter input for a parameter. The input changes constantly based on the player&#8217;s desires, so a better way to handle this is to select <em>SetResolution <\/em>under <em>Dynamic Int, <\/em>which is the top part of the function menu as shown in Figure 5.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"651\" height=\"664\" class=\"wp-image-87482\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-26.jpeg\" \/><\/p>\n<p><strong>Figure 5: Choosing a function from the <em>Dynamic <\/em>portion of the submenu.<\/strong><\/p>\n<p>Everything but the save and exit buttons is set this way. Table 1 below shows all menu elements with their corresponding function. Keep in mind that different elements may show the <em>Dynamic <\/em>portion of the function list differently. For instance, when setting <em>VolumeSlider&#8217;s <\/em>value change function to <em>SetVolume, <\/em>you&#8217;ll select the function under the <em>Dynamic Float <\/em>section of the menu.<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<p><strong>Object Name<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>Function<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>ResolutionDropdownMenu<\/p>\n<\/td>\n<td>\n<p>SetResolution()<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>FullscreenToggle<\/p>\n<\/td>\n<td>\n<p>SetFullscreen()<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>GraphicsPresetDropdown<\/p>\n<\/td>\n<td>\n<p>SetQuality()<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>AntiAliasingDropdown<\/p>\n<\/td>\n<td>\n<p>SetAntiAliasing()<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>TextureQualityDropdown<\/p>\n<\/td>\n<td>\n<p>SetTextureQuality()<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>VolumeSlider<\/p>\n<\/td>\n<td>\n<p>SetVolume()<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Table 1: All UI elements and their respective functions<\/strong><\/p>\n<p>As mentioned, the save and exit buttons are set a little different. Instead of adding an <em>On Value Changed <\/em>event, you&#8217;ll be adding an <em>On Click <\/em>event. Like before, the object the function is pulled from is the parent <em>UI <\/em>object. When selecting a function, you&#8217;ll select <em>SaveSettings() <\/em>for the save game button and <em>ExitGame() <\/em>for the exit button. There is no dynamic portion of the submenu to look through, so you should only see one option for the function. Figure 6 has an example of setting a function to a button.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"907\" height=\"490\" class=\"wp-image-87483\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-27.jpeg\" \/><\/p>\n<p><strong>Figure 6: Setting the function for <em>On Click<\/em>.<\/strong><\/p>\n<p>The last step before testing is to let <em>SettingsMenu <\/em>know what all the different drop-downs are as well as the audio mixer and the volume slider. Select the <em>UI <\/em>object from the <em>Hierarchy <\/em>and find the <em>SettingsMenu <\/em>component. Each empty field in the component is given a corresponding object. The <em>Audio Mixer <\/em>receives <em>MainAudio <\/em>from the <em>Assets <\/em>window. All four drop-down fields get a drop-down object (Figure 7), making sure that the given object matches what the field is asking for. For instance, <em>Resolution Dropdown <\/em>should get the <em>ResolutionDropdownMenu <\/em>object from the <em>Hierarchy. <\/em>Finally, the <em>Volume Slider <\/em>field gets the game object of the same name.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"915\" height=\"778\" class=\"wp-image-87484\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-28.jpeg\" \/><\/p>\n<p><strong>Figure 7: Filling in the empty <em>Settings Menu <\/em>fields.<\/strong><\/p>\n<p>While you can test out the project from the editor, you probably won&#8217;t be able to see the changes as well, if at all, when selecting different options in the menu. It is recommended you build an exe and play the game from the exe file. To do this, go to <em>File-&gt;Build Settings <\/em>in the top menu. In the window that opens, drag the <em>SampleScene <\/em>scene from the <em>Scenes <\/em>folder in the <em>Assets <\/em>window, into the <em>Scenes In Build <\/em>box as shown in Figure 8.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-87485\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-29.jpeg\" width=\"725\" height=\"530\" \/><\/p>\n<p><strong>Figure 8: Selecting the scene to build.<\/strong><\/p>\n<p>Once you&#8217;ve done that, click the <em>Build <\/em>button, choose a build location, then run the game once the build is finished. Try messing around with the different settings and watch as the visuals of the game get higher or lower quality depending on your selection. Over to the right, you should be able to see the Sphere look better or worse, depending on your settings. If changing anti-aliasing, the edges may not be as smooth. Meanwhile, changing the texture quality makes the sphere appear more \u201cgrainy.\u201d The differences can be subtle, so an easy way to see these effects is to jump from the <em>Ultra <\/em>graphics preset to the <em>Very Low <\/em>preset. You can also adjust the master volume for desired sound output. Note: if for any reason the volume slider appears to be doing nothing, double-check the name of the volume parameter in the audio mixer. You can do this by double-clicking <em>MainAudio <\/em>in the <em>Assets <\/em>window, clicking the exposed parameters button, and viewing the list of parameters. There should be one named Volume. If there isn&#8217;t, right-click the exposed parameter and rename it, or click the master mixer, navigate to the Inspector, right-click <em>Volume, <\/em>and select Expose.<\/p>\n<p>Of course, you should also try saving your settings with the save button, closing the game, then reopening to see that your preferred settings have indeed been loaded from the start. Figure 9 shows the app in action.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-87486\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2020\/06\/word-image-30.jpeg\" width=\"926\" height=\"519\" \/><\/p>\n<p><strong>Figure 9: Project in action.<\/strong><\/p>\n<h2>Conclusion<\/h2>\n<p>It&#8217;s often expected of any game to have some settings that can be tweaked and changed to a user&#8217;s liking. The options can be as simple as volume changes or as big as how the game displays its graphics. At first, one may think that creating such a menu for users can be a little challenging, but hopefully, this tutorial should prove that it&#8217;s easier than one may think. But why do this in the first place? Imagine a scenario where you have your Unity project you want to put out to the world, but some people don&#8217;t have the computer power to run it on normal settings. If you give them the tools to let the game run more smoothly on their machine, even if costs a little prettiness to do it, you give that user a chance to still use your software. In short, creating these options for your users creates the potential to expand your audience.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Video game enthusiasts expect that they can make changes to the game\u2019s environment and that the setting changes will be saved. In this article, Lance Talbert shows how it can be done in Unity.&hellip;<\/p>\n","protected":false},"author":317499,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,53],"tags":[95506],"coauthors":[52549],"class_list":["post-87477","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-featured","tag-automate"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/87477","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/317499"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=87477"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/87477\/revisions"}],"predecessor-version":[{"id":87488,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/87477\/revisions\/87488"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=87477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=87477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=87477"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=87477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}