Customizable Navigation Bar

Friday, December 23, 2011

SOPA, Something We All Need To Take A Minute To Think About

Hey guys, this post is a little out of the ordinary for me. Now as some of you may know, there is currently an act that is trying to be passed in the US called SOPA, or the Stop Online Piracy Act.

Now I completely agree with the fact that online piracy has caused some troubles for companies and individuals, but the problem is what this bill is going to do to not only piracy, but privacy and what we will be able to do on the internet.

I am providing two links, one to a very opinionated video about SOPA, and one that is a much more informative video on SOPA. I recommend that you watch and share both with as many people as you can. This is more important than you realize.



By the way happy coding! and Happy Holidays!

Sunday, December 11, 2011

(Opinion) Why Clean Code is More Important Than Efficient Code

Hey guys, this next post isn't so much of a tutorial as it is a rant on why I think you should pay more attention to the cleanliness and clarity of your code instead of the efficiency. Now don't get me wrong, efficient code is extremely important, but that can come later, and if no one is able to figure out what you did, including yourself, you are only going to create problems.

My first pointer for code clarity, is separate what you are doing. What I mean is, just because you can fit everything on one line, doesn't mean you should. First example:

let's say that there is some function that takes an object as a parameter, and you have two choices that you can enter as that parameter. One way of doing this is:

someFunction((m_someBoolean) ? m_object1 : m_object2);

Alright so basically what is happening here is that before we pass the object, we are checking to see the value of a boolean and determining which object to pass. This is all done where we normally just pass in the value. Sure it's quick and is done on one line, but it's not as clear as to what is going on compared to what we could be doing. Something that I personally try to do, is keep my code as close to English as I can, that way it's easy to read, and the code comments itself.

Friday, December 2, 2011

Level Manager

Alrighty! So, I've finally come around, and like I promised ages ago, here's a new tutorial. This one is based on my LevelManager class. Basically this class just handles simple level transitions, and fades in and out a texture using GUI so that it masks the fact a new level has been loaded, because the freeze and jump to the next level is ugly otherwise.

The whole reason I came up with this script was because I needed something to hide the fact that a level was loading, and I was only using the free version of Unity at the time, and I still am as a matter of fact. The funding for the pro version eludes me at the moment, as I can't just pull $1500 - $2000 out of nowhere, and I'm not going to pirate software that I am going to use for development.


So before we being we need to create a new C# Script and call it LevelManager.cs


//Here was just include our normal using statements for UnityEngine and System.Collections. All classes created within Unity should have these included automatically

using UnityEngine;
using System.Collections;

//Now we create our LevelManager class, and what I want you to do is have it extend SingletonObject. This is a class that I created for a tutorial around mid October 2011 if you don't already have the scripts.

public class LevelManager : SingletonObject
{
        //The first thing that we are going to do to this class is create some public variables that we can change within the editor


        //The first is going to be called fadeTime. This is going to be a float value that we use to determine how long it takes for our texture to fade in and out. We are going to default it to 1 second

        public float fadeTime = 1.0f;

        //The next variable is going to be a texture array. I used this method so that I could associate a loading texture with a certain level number, that way not all of the loading screens looked the same etc.

        public Texture[] fadeTextures;

        //Now that we have the public variables created, I want to create two new private ones that are only used in this class. 


        //The first will be called m_currentGUIAlpha. This is a float value that will be used in the GUI functions of this class. When the value of this variable changes, the alpha of the loading texture across the screen will change as well, creating a fade in/fade out effect.

        private float m_currentGUIAlpha = 1.0f;

        //The next is just a boolean checking to see if we are currently fading in or out. I created this variable so that we would check to see if we are fading before we change any GUI properties, or do anything in the GUI, because there is no point in doing something if you don't have to, its inefficient and wastes CPU cycles that could be used for something more useful.

        private bool m_isFading = false;
     
        //Before we move on we want to make sure that the LevelManager class is persistant, or does not destroy itself when Unity loads a new level.

        private void Start()
        {
                DontDestroyOnLoad(gameObject);
        }

        //One thing that you are going to notice is that a lot of these functions are just overrides of ones already created. I like to give myself and others options when programming so that we don't always have to go out of my way to find information or so something. Call me lazy sure, but it also creates code that is easier to read and follow, which I think is much more valuable during development opposed to afterwards.


        //The first function that we are going to create is called fadeIn(). This function will return an IEnumerator because we want this to be a Coroutine, so that it will fade in only a certain amount over the course of the fadeTime that we set in the editor or at the top of this class.

        private IEnumerator fadeIn()
        {
                //Since we are fading in, that means that the Texture that will be covering the screen should start out completely transparent, so let's set our m_currentGUIAlpha to 0.0f

                m_currentGUIAlpha = 0.0f;

                //We are also fading now, so we want to take care of a few things within the GUI. Remember that we created a boolean variable that we check in our GUI function before we do anything. Since we want to, lets set that variable to true

                m_isFading = true;

                //We need to create a local variable to determine how much the alpha of the texture is going to change, so we are going to create a float value for that. We are also going to return this value in the IEnumerator within a loop so that the texture will fade in at the same rate the entire time. 


        //What we do is we divide 1 by the fade time, and then by 255, because 0 - 255 is commonly the range used in RBGA values, and we want to keep the loop going until our value is at or above 1. This is kind of confusing, but think of it this way:
        -if we were to just use fade time, we would end up with a larger value than what we would want, and the fade would end before we wanted it to
        -also, we divide by 255 because like I said, 0-255 is the range used by RBGA, and if we don't divide by this we get a much larger value than what we want, and the fade ends after a few frames instead of a few seconds

                float alphaChange = 1.0f / fadeTime / 255.0f;
             
                //Alright, so now that this is cleared up, we are going to create a loop that checks to see if m_currentGUIAlpha is less than one

                while(m_currentGUIAlpha < 1.0f)
                {

                        //Inside this loop we want to increase m_currentGUIAlpha by alphaChange, and then yield return alphaChange as well so that the loop will pause for a brief second and the texture will fade in nicely

                        m_currentGUIAlpha += alphaChange;
                        yield return alphaChange;
                }              
             
                //I usually yield break at the end of my Coroutines, you really don't have to, it is just a habit I got into.
                yield break;
        }
     
        //The next function I create is basically copy and paste of the fadeIn() function, except it's called fadeOut(). The only difference is that we set m_currentGUIAlpha to 1.0f right off the bat instead of 0.0f, and be subtract the alphaChange variable instead of add.

        private IEnumerator fadeOut()
        {
             
                //see we set it to 1.0f this time

                m_currentGUIAlpha = 1.0f;
             
                float alphaChange = 1.0f / fadeTime / 255.0f;
             
                while(m_currentGUIAlpha > 0.0f)
                {

                        //and we subtract instead of add this time as well

                        m_currentGUIAlpha -= alphaChange;
                        yield return alphaChange;
                }              
             
                //We also want to set m_isFading to false at the end of this function so that we don't do anymore GUI stuff when we don't have to, since now the texture is invisible anyways.


                m_isFading = false;
             
                yield break;
        }
     
        //What is coming up next is the start of a bunch of overridden functions. These are made for convenience and that's about it. The first set is called appLoadNewLevel() and it is a IEnumerator function. 


        //The first appLoadNewLevel() will be the most commonly used function, or at least it is for me since it automatically loads the next level. One thing that you could add is a check to see if the level exists and if not load the main menu for example. I made it quickly and to get the job done, that's about it since I know what I want things to do.

        private IEnumerator appLoadNewLevel()
        {
             
                //I like to have special sound effects in my games and projects to let the player know when they reached he end of the level, so I check to see if the level loaded currently is not the first one (0 is my main menu level) and if its not, I play my new level sound effect

                if(Application.loadedLevel != 0)
                {
                       // AudioManager.instance.playSFX("Load New Level");
                }
             
                //Then basically all I do is start the fadeIn Coroutine and load the next level

                yield return StartCoroutine( fadeIn());
                Application.LoadLevel(Application.loadedLevel + 1);
        }
     
        //The next function is the exact same except you pass in a specific level number. I use this in my credits level or if the player loads a level, basically when I know that the level that should be loaded next is not the one listed right after the current one, or this is the last level.

        private IEnumerator appLoadNewLevel(int level)
        {
                if(Application.loadedLevel != 0)
                {
                       // AudioManager.instance.playSFX("Load New Level");
                }
             
                yield return StartCoroutine( fadeIn());
                Application.LoadLevel(level);
        }
     
        //This function is also the same as the previous, but instead you pass a string value as a parameter, and the game will check to see if a level with that string name exists, and it loads it. This is useful if you don't know the index of the level you want to load, but you remember what you called the level.

        private IEnumerator appLoadNewLevel(string level)
        {
                if(Application.loadedLevel != 0)
                {
                     //   AudioManager.instance.playSFX("Load New Level");
                }
             
                yield return StartCoroutine(fadeIn());
                Application.LoadLevel(level);
        }
     
        //The next set of functions are delayed but do the exact same thing. I created these just in case I wanted to reward the player or have the character dance or something after the level was finished, and then load the next level once it was finished


        //If you do use these functions the first one will be the most common, where you just pass a delay in as a parameter. This function loads the next level and plays the sound effect accordingly just like the other functions, but first it waits for however long you told it to.

        private IEnumerator appLoadLevelDelayed(float delay)
        {
                if(Application.loadedLevel != 0)
                {
                      //  AudioManager.instance.playSFX("Load New Level");
                }
             
                //See, first we wait, and then we fade and load

                yield return new WaitForSeconds(delay);
                yield return StartCoroutine(fadeIn());
             
                Application.LoadLevel(Application.loadedLevel + 1);
        }
     
        //Once again like before, but you pass the level index in as well

        private IEnumerator appLoadLevelDelayed(int level, float delay)
        {
                if(Application.loadedLevel != 0)
                {
                       // AudioManager.instance.playSFX("Load New Level");
                }
             
                yield return new WaitForSeconds(delay);
                yield return StartCoroutine(fadeIn());
             
                Application.LoadLevel((level < Application.levelCount) ? level: 0);
        }
     
        //I feel like a broken record here, but once again, like before, except you pass the name of the level instead of the index and everything is taken care of for you.

        private IEnumerator appLoadLevelDelayed(string level, float delay)
        {
                if(Application.loadedLevel != 0)
                {
                      //  AudioManager.instance.playSFX("Load New Level");
                }
             
                yield return new WaitForSeconds(delay);
                yield return StartCoroutine(fadeIn());
             
                Application.LoadLevel(level);
                yield break;
        }
     
        //Now something that you might have noticed was that I created all of the previous functions privately instead of publicly. I did this just for my own organization, and I wanted to create public functions that you could simply call instead of having to start a Coroutine from outside of this class just to load a new level.


        //These next functions just take care of the Coroutine problem for us, and creates simple, easy to read functions that can be called from any class easily. These functions speak for themselves, if there is anything that causes confusion, send me a message and I will edit the post fixing any problems.

        public void loadLevel()
        {
                StartCoroutine(appLoadNewLevel());
        }
     
        public void loadLevel(float delay)
        {
                StartCoroutine(appLoadLevelDelayed(delay));
        }
     
        public void loadLevel(int level)
        {
                StartCoroutine(appLoadNewLevel(level));
        }
     
        public void loadLevel(int level, float delay)
        {
                StartCoroutine(appLoadLevelDelayed(level, delay));
        }
     
        public void loadLevel(string level)
        {
                StartCoroutine(appLoadNewLevel(level));
        }
     
        public void loadLevel(string level, float delay)
        {
                StartCoroutine(appLoadLevelDelayed(level, delay));
        }
     

        // Basically what is left is the class's OnGUI function

        private void OnGUI()
        {

                //First we want to check and see if we are fading in or out, because if we aren't we don't need to do anything.

                if(m_isFading == true)
                {

                        //First thing we want to do is create a local variable to hold the GUI color, only because we cant access individual properties of them in C# for some reason. Don't believe me? Just try it. 

                        Color fadeColor = GUI.color;

                        //Then we want to set the alpha of that color to m_currentGUIAlpha to give the fade effect and set the GUI.color to the new transparent one

                        fadeColor.a = m_currentGUIAlpha;
                        GUI.color = fadeColor;
                     
                        //Next we want to draw the texture across the entire screen. What I also did in this function was check to see what level was loaded and load a different texture if there were enough in the texture array.

                        GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), (fadeTextures.Length > 1 && fadeTextures.Length >= Application.loadedLevel) ? fadeTextures[Application.loadedLevel]: fadeTextures[0], ScaleMode.StretchToFill);

                        //Now that that is over with we want to set the color back to what is was so it doesn't interfere with other GUI objects in different classes and whatnot

                        GUI.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);
                }
        }      
     
        //One last thing we want to do is start a fade out when a new level is loaded to complete the effect

        protected void OnLevelWasLoaded(int level)
        {              
                StartCoroutine(fadeOut());
        }
}