{"id":2852,"date":"2015-06-28T22:04:18","date_gmt":"2015-06-28T21:04:18","guid":{"rendered":"http:\/\/www.holyfingers.co.uk\/main\/?p=2852"},"modified":"2016-10-07T12:15:53","modified_gmt":"2016-10-07T11:15:53","slug":"development-diary-12-quality-settings","status":"publish","type":"post","link":"https:\/\/www.holyfingers.co.uk\/main\/blog\/2015\/06\/28\/development-diary-12-quality-settings\/","title":{"rendered":"Development Diary #12: Quality settings\u2026"},"content":{"rendered":"<p style=\"text-align: justify;\">This month I&#8217;ve been straying well outside my comfort zone to work on an in-game menu allowing players to change various quality settings during runtime. Unity offers a standard, built-in menu that appears when a game starts up but it hides several settings under &#8220;Quality Levels&#8221;, has a rather confusing input editor and requires the player to restart the game in order to make any changes. It&#8217;s also not customizable to any great extent and doesn&#8217;t really create the best first impression, so I thought I&#8217;d try and make my own.<\/p>\n<p style=\"text-align: justify;\">All the menu elements are 3d objects as opposed to uGUI buttons, I&#8217;m using <a href=\"http:\/\/www.hutonggames.com\/\" target=\"_blank\">Playmaker<\/a> for all the scripting and <a href=\"http:\/\/moodkie.com\/easysave\/\" target=\"_blank\">Easy Save 2<\/a> for saving\/loading data and, as I haven&#8217;t completely nailed down how I&#8217;m handling input yet, the setup responds only to mouse and keyboard input, hopefully controller and touch wont be too tricky to add in later on&#8230;<\/p>\n<p><!--more--><\/p>\n<p><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Menu_1.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Menu_1.png\" alt=\"Menu_1\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">These are all the settings I currently have working; <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/Screen-fullScreen.html\">toggle-fullscreen<\/a>, <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/Screen-width.html\">screen width<\/a> and <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/Screen-height.html\">height<\/a>, <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/QualitySettings-antiAliasing.html\">anti-aliasing level<\/a> and <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/QualitySettings-vSyncCount.html\">vertical-sync<\/a>. (Playmaker actions for accessing them are <a href=\"http:\/\/hutonggames.com\/playmakerforum\/index.php?topic=2354.0\">here <\/a>and <a href=\"http:\/\/hutonggames.com\/playmakerforum\/index.php?topic=4129.0\" target=\"_blank\">here<\/a>). <em>Settings Menu Update<\/em>, <em>Settings Menu<\/em> and <em>Resolutions<\/em> are empty objects at 0,0,0, everything else is a menu button. (<em>You can ignore everything from <\/em>Main Camera 60<em> down to <\/em>Field_Guide<em> in the hierarchy<\/em>) At the moment all the buttons are just Text Meshes, it made them easy to edit and I could just set the font to bold and back to indicate button state, I\u2019ll be changing most of them to icons at some stage but it should be pretty straight forward to swap them out for any kind of set up.<\/p>\n<p style=\"text-align: justify;\">As well as being able to accept new settings, the menu should indicate what the current settings are, if this is the first time the game has been run there also need to be some defaults already in place, it also should have a temporary method of storing choices before hitting the Apply button, this should only become active when the player has made changes. Here it is in action:<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/i.imgur.com\/3Sh3c8Q.gif\" alt=\"\" width=\"640\" \/><\/p>\n<p style=\"text-align: justify;\">The Saving and loading of values is handled by the <em>Settings IO<\/em> FSM on <em>Settings Menu Update<\/em>:<\/p>\n<p><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/SettingsIO_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/SettingsIO_FSM_Main.png\" alt=\"SettingsIO_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">On starting, <em>IO<\/em> checks to see if there is a settings file already available, if there is it loads the relevant values, updates the local variables and the actual quality settings themselves. If there is no file available it creates one out of a set of default values, <em>then<\/em> loads\/updates. The red state on the left is where updated values from the various menu buttons\u00a0are dealt with. The variables should mostly be self explanatory, the setting for screen size takes an integer but at various time&#8217;s we&#8217;ll need to find the aspect ratio as a float so we&#8217;re storing <em>Screen Width <\/em>\/ <em>Height<\/em> as both.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/SettingsIO_FSM_Annotated.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/SettingsIO_FSM_Annotated.png\" alt=\"SettingsIO_FSM_Annotated\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">There are quite a few things being updated simultaneously and from various different places, <strong><em>Check Settings File Exists<\/em><\/strong> broadcasts an <em>IO Busy<\/em> event, the individual FSMs on buttons are paused and wait for the <em>IO Idle<\/em> event we&#8217;ll send when we&#8217;re done, this should help make sure events are firing in the order we want. We then check for a playerSettings file using the <a href=\"http:\/\/docs.moodkie.com\/easy-save-2\/guides\/playmaker-saving-and-loading\/\" target=\"_blank\">Easy Save action<\/a> <em>Exists<\/em>.<\/p>\n<p style=\"text-align: justify;\">If no file exists we need to set some defaults, getting the <em>Screen Width<\/em> and <em>Screen Height<\/em> here will take the current screen dimensions as floats, this should give you the native resolution providing you have that set to default in your build settings. We convert and store them as integers as well.<\/p>\n<p style=\"text-align: justify;\"><strong><em>Save Defaults<\/em><\/strong> and <em><strong>Save New Settings<\/strong><\/em> are series of save actions to store relevant settings in the newly created playerSettings file. <em><strong>Save Defaults<\/strong><\/em> only runs if the initial check doesn&#8217;t find a settings file, it uses pre-set values from the state rather than stored variables, by default I have fullscreen set to true, anti-aliasing set to zero, v-sync set to every v-blank, resolution set to the native width\/height we got in the previous state. After a settings file is created we use <em><strong>Save New Settings <\/strong><\/em>instead, this will overwrite values in the file with the values from our local variables, this state is only entered via the <em>Apply New Settings IO<\/em> global event.\u00a0<strong><em>Load Settings<\/em><\/strong> is then the equivalent load actions from the same file and <strong><em>Apply Settings<\/em><\/strong> uses the quality settings actions to apply these values to their respective property. Finally, <strong><em>Idle<\/em><\/strong> broadcasts an <em>IO Idle<\/em> event and waits for further input&#8230;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\"><!--nextpage--><\/p>\n<p style=\"text-align: justify;\">Every button has its own FSM to handle input, deal with on\/over\/selected states and to store pertinent, pre-set values. Settings are changed by replacing the current values stored on <em>Settings IO<\/em> with these pre-sets before triggering <em>Save New Settings <\/em>to update the actual <em>playerSettings<\/em> file.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Fullscreen_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Fullscreen_FSM_Main.png\" alt=\"Fullscreen_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">This is the FSM on the <em>Fullscreen<\/em> button, it stores a boolean and acts as a toggle. The highlighted <em>Self<\/em> variable is a Unity Object of type UnityEngine.TextMesh, when using Get Component on a GameObject, Unity will take the first one it finds of the set type, so it&#8217;s a good idea to set that here.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Fullscreen_FSM_Annotated.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Fullscreen_FSM_Annotated.png\" alt=\"Fullscreen_FSM_Annotated\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\"><strong><em>Wait for IO Idle<\/em><\/strong> is empty and waits for an <em>IO Idle<\/em> event from <em>Settings Menu Update<\/em>, note that in addition to the <em>START<\/em> event the first state can be entered via the global event <em>IO Busy<\/em>. <strong><em>Initialize <\/em><\/strong>finds objects and components and store them as local variables.<\/p>\n<p style=\"text-align: justify;\"><strong><em>Get Current Fullscreen<\/em><\/strong> gets the <em>Fullscreen<\/em> boolean value from the <em>Settings Menu Update <\/em>FSM storing\u00a0it locally as <em>Current Fullscreen<\/em>, this allows us to compare the two and automatically select or deselect the button to begin with, without requiring a click.<\/p>\n<p style=\"text-align: justify;\">(<em>At this point, a lot depends on how you&#8217;re handling input, I have a slightly odd cursor set up, in order to tell when the player is hovering over a button with a mouse I compare the Owner to a globally determined <\/em>Hovered_Object<em>. You could alternatively use an <a href=\"http:\/\/docs.unity3d.com\/ScriptReference\/MonoBehaviour.OnMouseExit.html\" target=\"_blank\">OnMouse<\/a> event or another equivalent.<\/em>)<\/p>\n<p style=\"text-align: justify;\">When a button is first selected, the local <em>Fullscreen<\/em> boolean is set to true and the font style is changed to bold. <strong><em>Idle Selected <\/em><\/strong>checks every frame for a mouse over, when it detects one it triggers the <em>Over<\/em> event and switches to <strong><em>Over\u00a0Selected <\/em><\/strong>which checks every frame for a click event as well. <strong><em>Selected Cursor Over<\/em><\/strong> state is the equivalent for non mouse input and is entered and exited via the global events <em>Cursor Over <\/em>and<em> Cursor Off<\/em>, sent from elsewhere. Both <strong><em>Over<\/em><\/strong> states also scale the parent button up slightly, <em><strong>Idle Selected<\/strong><\/em> scales it back.<\/p>\n<p style=\"text-align: justify;\">Upon detecting a <em>Click<\/em> event, <strong><em>Update Changes Selected<\/em><\/strong> first sends an event to the <em>Apply Settings<\/em> button to indicate that a change has taken place before swapping over to <strong><em>Deselect<\/em><\/strong>, all the states here work identically to their selected counterparts except the text style is set to regular and the <em>Fullscreen<\/em> boolean is set to false.<\/p>\n<p style=\"text-align: justify;\">No values are actually sent to\u00a0<em>Settings IO <\/em>FSM until<strong><em> Update Settings<\/em><\/strong> receives the <em>Update Settings IO<\/em> global event from the <em>Apply Settings<\/em> button.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Button_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Button_FSM_Main.png\" alt=\"Button_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The FSM templates used on most of the other buttons are extremely similar to the one for <em>Fullscreen<\/em>, the <em>Unselected<\/em> states all work exactly as before. For resolution, AA-Level and V-sync, however, there always has to be a value selected, what&#8217;s more it can&#8217;t be deselected without simultaneously choosing a new one, they behave more like standard radio buttons.<em><br \/>\n<\/em><br \/>\n<a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Button_FSM_Annotated.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Button_FSM_Annotated.png\" alt=\"Button_FSM_Annotated\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The differences can be seen in the <em><strong>Select<\/strong><\/em> state which broadcasts a <span style=\"text-decoration: underline;\">de<\/span>select event to all the other FSMs on buttons of the same type, this makes sure only one is selected at a time. (Make sure you check the <em>Exclude Self<\/em> box in the <em>Send Event<\/em> action or the button will trigger its own <em>Deselect<\/em> event!) The <em><strong>Update Settings IO<\/strong><\/em> state has been moved so as to be available only while the button is selected, and the scaling has been removed from both <em><strong>Selected Over<\/strong><\/em> and <em><strong>Selected Cursor Over <\/strong><\/em>states. These states no longer check for click events either.<\/p>\n<p style=\"text-align: justify;\">The templates for resolution, AA and V-sync are identical except they check for and set their relevant variables instead of <em>width<\/em>\/<em>height<\/em> and the <em>Deselect<\/em> event is named differently. The <em>Aspect<\/em> ratio buttons do a slightly different job and have a few extra elements&#8230;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\"><!--nextpage--><\/p>\n<p>Aspect ratio isn&#8217;t something that can be set directly but it&#8217;s helpful if you have a large number of resolution options you want to narrow down.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Aspect_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Aspect_FSM_Main.png\" alt=\"Aspect_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The <em>Aspect<\/em> FSM keeps track of all the same objects and values the resolution button did plus\u00a0<em>Selector<\/em>, a blue quad which is the child of the owner button, and <em>Resolution<\/em>, a Game Object which is parent of all the resolution buttons. When an <em>Aspect<\/em> is selected it translates the <em>Resolutions<\/em> object left or right to show only those buttons that match the relevant ratio, effectively creating three sub-menus on the same row.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Aspect_FSM_Annotated.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Aspect_FSM_Annotated.png\" alt=\"Aspect_FSM_Annotated\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Rather than have a separate aspect variable associated with each and every resolution, it&#8217;s simpler to just work it out on the fly and store the result, this also makes it a bit quicker to add new resolutions later on. We get the <em>Screen Width<\/em> and <em>Screen Height<\/em> values from <em>Settings IO<\/em>, and divide the former by the latter, the resultant float <em>Current Aspect<\/em> is compared to the local <em>Aspect<\/em>. Selection works as before but additionally, activates or deactivates the <em>Selector<\/em> quad, sets a string value in the <em>Menu Cursor<\/em> FSM and moves the <em>Resolution<\/em> object to a preset position.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Main.png\" alt=\"MenuCursor_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The <em>Menu Cursor<\/em> FSM handles non-mouse input, it keeps track of button positions and places the cursor accordingly based on input, I&#8217;m just using keys at this stage but the principals should remain the same regardless. Each row of buttons is stored in an <em>Array List Proxy<\/em> on the <em>Settings Menu Update<\/em> object, each entry in the array represents a single button and column.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none aligncenter\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Inspector_Arrays.png\" alt=\"Inspector_Arrays\" \/><\/p>\n<p style=\"text-align: justify;\">The arrays are all labelled with a number, those containing resolutions also get a letter. This letter is just a short way of referencing the three different aspect ratio sub-menus. I haven&#8217;t shown them all, but array #3 has just the <em>Fullscreen<\/em> button in it, #4 just <em>Apply<\/em>, #5 is <em>V-sync<\/em> and #6 the <em>AA-levels<\/em>.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_1.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_1.png\" alt=\"MenuCursor_FSM_Annotated_1\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">We only use this system with non-mouse input so after <strong><em>Initialize<\/em><\/strong>, we wait for a <em>Key Up<\/em> event on WASD in <strong><em>Check Input<\/em><\/strong>. The arrays all have numbers to identify them but <em>Array List<\/em> actions require a string for reference so we need to store the <em>Current Row<\/em> integer as a string as well. The resolution buttons are spilt into sub menus depending on aspect ratio, each has its own letter, but they all effectively inhabit the same row (I&#8217;m calling this kind of row a <em>Multi<\/em>), the row letter is added on to the <em>Current Row String<\/em> but it&#8217;s only the <em>Current Row Int<\/em> that&#8217;s used for the switch. All the <em>Single<\/em> rows behave the same way and don&#8217;t require an offset so we can set it to zero, we can ignore the <em>Row Letter<\/em> for these rows as well so only the fist character of <em>Current Row String<\/em> is required.<\/p>\n<p style=\"text-align: justify;\">Our sole <em>Multi<\/em> row, the resolutions, requires an offset because it&#8217;s shifted left or right depending on the current aspect ratio. The translation is performed on the parent object <em>Resolutions<\/em> but here we&#8217;re getting the individual button positions from their <em>Self<\/em> space, so we just have to offset by the same amount we moved the parent.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_2.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_2.png\" alt=\"MenuCursor_FSM_Annotated_2\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Once the offset is figured out all the rows work the same way, <em>Check Column Fits in Row <\/em>uses the <em>Current Row String<\/em> as a reference and makes sure the <em>Current Column<\/em> is no higher than the last entry in the specified <em>Array List<\/em> (Arrays start at zero, hence the minus one!), if it is it will <em>Loop Right<\/em>, jumping back to the first entry, zero. <em>Check if Less than Zero<\/em> makes sure the <em>Current Column<\/em> never turns negative but instead will <em>Loop Left<\/em>, jumping to the last entry in the current array, which will be the same as the <em>Current Array Length<\/em> (Now already including the minus one!).<\/p>\n<p style=\"text-align: justify;\"><em><strong>Get Current Button<\/strong><\/em> uses the <em>Current Row String<\/em> and <em>Current Column<\/em> as Reference and Index in an array list get, <strong><em>Get Button Position<\/em><\/strong> takes its position and adds any necessary offset, before <em><strong>Move Cursor<\/strong><\/em> updates the cursor position and sends the <em>Cursor Over<\/em> event to the <em>Current Button<\/em>.<\/p>\n<p style=\"text-align: justify;\">(<em>We haven&#8217;t actually set up the actual, visible cursor during this tutorial and you can just leave it out, the button text will still scale up and go bold to indicate which one you have selected, this is just what works with mine. If you wanted to you could add in an extra sphere or sprite or whatever at the same <strong>z<\/strong> translation as your buttons, and just pass the <\/em><strong>Current Button x<\/strong>\/<strong>y<\/strong><em> positions to that.<\/em>)<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_3.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/MenuCursor_FSM_Annotated_3.png\" alt=\"MenuCursor_FSM_Annotated_3\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\"><em><strong>Idle<\/strong><\/em> waits for <em>Keys Ups<\/em> and then either adds or minuses one from <em>Current Row<\/em> or <em>Current Column<\/em>, before <strong><em>Check Top<\/em><\/strong> and <em><strong>Check Bottom <\/strong><\/em>make sure the rows loop just like we did previously with the columns. We finish up back in <em><strong>Check Row<\/strong><\/em> and the process starts again.<\/p>\n<p style=\"text-align: justify;\">After all this we still haven&#8217;t actually changed any settings, we still need to click the <em>Apply Settings<\/em> button&#8230;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\"><!--nextpage--><\/p>\n<p>The various parts of the <em>Apply Settings<\/em> button should be pretty familiar by now:<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Apply_FSM_Main.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Apply_FSM_Main.png\" alt=\"Apply_FSM_Main\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Unlike the other buttons though, <em>Apply<\/em> is unclickable in its <strong><em>Idle Unselected<\/em><\/strong> state, unable to do anything until the <em>Changes<\/em> event is sent from one of the other buttons.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Apply_FSM_States.png\"><img decoding=\"async\" class=\"ngg-singlepic ngg-none alignnone\" src=\"https:\/\/www.holyfingers.co.uk\/main\/wp-content\/gallery\/quality-settings-tutorial\/Apply_FSM_States.png\" alt=\"Apply_FSM_States\" width=\"640\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Once <em>Changes <\/em>have occurred, the button checks every frame for a <em>Click<\/em>, and then an <em>Apply Settings IO<\/em> event is broadcast, any button FSM currently in its <em>Idle Selected<\/em> state will send its local values to <em>Settings IO<\/em>. Finally, <strong><em>Apply Settings IO<\/em> <\/strong>then triggers an event on the <em>Settings IO<\/em> saving the currently set values to the <em>playerSettings<\/em> file. If only some of the settings have been changed the previously set ones will simply persist, buttons in an <em>Unselected<\/em> state don&#8217;t send any new values.<\/p>\n<p style=\"text-align: justify;\">At this stage the menu is working pretty much how I want it, as I said I&#8217;ll probably be changing some of the text for icons, I might reduce the number of options as well depending on their actual usefulness, this was mostly an exercise to see if I could get them all functioning! The next step is a similar setup for user created Save Games and possibly for customizing input, both of which I&#8217;m imagining will be more complex&#8230;<\/p>\n<p style=\"text-align: justify;\">As always, comments, crits and corrections are all welcome.<\/p>\n<p style=\"text-align: justify;\">\n","protected":false},"excerpt":{"rendered":"<p>This month I&#8217;ve been straying well outside my comfort zone to work on an in-game menu allowing players to change various quality settings during runtime. Unity offers a standard, built-in menu that appears when a game starts up but it hides several settings under &#8220;Quality Levels&#8221;, has a rather confusing input editor and requires the &#8230; <a title=\"Development Diary #12: Quality settings\u2026\" class=\"read-more\" href=\"https:\/\/www.holyfingers.co.uk\/main\/blog\/2015\/06\/28\/development-diary-12-quality-settings\/\" aria-label=\"Read more about Development Diary #12: Quality settings\u2026\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":2862,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[55,12],"tags":[64,88,75,89,76,90,57,46],"class_list":["post-2852","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-game-development","category-tutorials","tag-dev-diary","tag-easy-save","tag-playmaker","tag-settings","tag-toryanse","tag-tutorial","tag-unity","tag-wip"],"_links":{"self":[{"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/posts\/2852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/comments?post=2852"}],"version-history":[{"count":104,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/posts\/2852\/revisions"}],"predecessor-version":[{"id":3010,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/posts\/2852\/revisions\/3010"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/media\/2862"}],"wp:attachment":[{"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/media?parent=2852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/categories?post=2852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.holyfingers.co.uk\/main\/wp-json\/wp\/v2\/tags?post=2852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}