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());
        }
}
   

Monday, November 28, 2011

Internets!

Alright guys, so I just got internet at my new apartment around 20 minutes ago. Quite a delay from the date I moved in, I believe it's been almost a month now. Now that I have the internet at my new apartment I'm going on an internet surfing binge and then getting back to it!

Within the last month the teaching has gone fairly well, and I was offered another course to teach next semester, so that's awesome. The only problem is that it depends on how many students sign up for the course and whether or not there is enough to even bother having the course at all. So fingers crossed! It is calculus so I'm hoping things go through!

As for the tutorials, the new ones should be coming soon, I more or less just need to take an hour or so and get them set up on this site. Anyhow, off to work and happy coding!

Sunday, October 30, 2011

Moving This Weekend!!!

That's right you read it, I'm moving. Me and a friend are moving in together so this weekend is consisting of packing and driving! I'm actually pretty excited, and I don't get excited for much, I'm a pretty boring person. 

On top of that I have four tutorials in progress, and some updates on my projects in development, so expect new articles on those anytime. 

Also I would like to apologize now for the Adf.ly crap. I was just testing it out to see how it would work, I'm going to try and see if there is a less invasive way to get the benefits, I really hope there is, I hate ads.

Also, I can't remember if I mentioned this anywhere, but I am teaching math at St.Clair College in Chatham Ontario now, and it's awesome. The only problem with it is that I am on a contract and not a full time faculty. So basically if they don't want me next semester they don't have to sign me on again, and they don't have to give me notice, which is pretty poopy. This is where my being busy comes from because I have another job on top if it to fall back on just in case, and because of that I get maybe a day off a week, and I have to use that day to prep and mark for my classes. 

Anywho, I'm hoping to become more regular like I was before, I'd even like to start doing my video tutorials again, so here's hoping it happens! and happy coding!!!

Thursday, October 13, 2011

Holy Crap! A New Tutorial Finally! SingletonObject and SingletonUtility

That's right, I found some time to toss this beast up here. What this tutorial is going to cover is new way to do singleton objects within Unity3D.

The problem that I had been having with a way I was doing it before was that, even though I had each singleton object check to see if another one was loaded and set to the reference value, either both would be destroyed, or neither would be, and then you would just have a bunch of clutter within your level.

This new way of doing singletons has a separate class set up that keeps the references of the singletons and destroys new instances.

The reason I like to use singletons within my levels is not only to keep just one static reference to an object, but it makes debugging easier, and also removes the tedious work of having to go through each level and removing the testing objects that no longer need to be there. For example, I could go and create a level manager for each level, and go through all of the setup, then at the end get rid of them all(If you make it persistent like I do) or I can make them singletons and the game handles it for me when it loads each new level.


The first class I'm going through is your basic SingletonObject that the singletons are going to extend from. So the first script should be called SingletonObject.cs.

using UnityEngine;
using System.Collections;

public class SingletonObject : MonoBehaviour {

       //In our start function we want to register our singleton in the SingletonUtility class that we will see soon

        protected virtual void Start ()
        {
                SingletonUtility.registerSingleton(this);
        }
     
        //Next we want to make sure that any other instances of this object will be destroyed when a new level is loaded.

        protected virtual void OnLevelWasLoaded(int level)
        {

                // I also destroy most singletons on level 0 because that's my main menu level

                if(level == 0)
                {
                        Destroy(gameObject);
                        return;
                }
             
                SingletonUtility.destroyOtherExistingObjects(this);
        }
     
        //Now the next function spawnNewObject spawns a new object of the type specified and returns the reference to that Behaviour.

        protected static Behaviour spawnNewObject(System.Type objectType)
        {
                GameObject obj = new GameObject (objectType.ToString());
                Behaviour temp = obj.AddComponent(objectType) as Behaviour;
                SingletonUtility.registerSingleton(temp);
                Debug.LogWarning ("Cannot locate Singleton object, creating new one");
                return temp;
        }
}

     
//The way you use the spawnNewObject function is like so:
       
 //In the sub class that extends SingletonObject you want to create a static protected reference to an object of the same class. The example used here is the AudioManager class.     
      
protected static AudioManager m_instance;
       
//Once we get our static protected reference finished, we want to make a public static read only reference to that object. What that means is, any class will be able to reference the object that it points to, but won't be able to change it. It will look like this:


public static AudioManager instance
{


        //This is what makes the object read only: The keyword get. What get allows us to do is add extra functionality when we want to reference an object that this variable is pointing to. If we want to do something special when we change the variable, we use the keyword set instead


        get
        {


        //We do a double check if the reference is null, first we check the reference and then we check if there are any objects of that type floating in the world


                if (m_instance == null)
                {
                        if ((m_instance = (FindObjectOfType (typeof(AudioManager))) as AudioManager) == null)
                        {


                                //If we don't find any objects of the AudioManager type, or whatever type this class is in your project, we use the spawnNewObject function and pass the type in, and make sure the static protected reference points to that object


                                m_instance = spawnNewObject(typeof(AudioManager)) as AudioManager;
                        }
                }

                //Once our m_instance variable is pointing to that object, we return it so that any class can read the variable perform necessary functions with it, but can't change it


                return m_instance;
        }
}



So that's how the SingletonObject class works so far. The next part of this tutorial is the SingletonUtility class, which is a small class that handles the checking for duplicate singletons and keeps everything organized.


So the new script will be called SingletonUtility.cs

using UnityEngine;
using System.Collections;

//Notice that we do not extend MonoBehaviour in this class. We do not need to since it's not being attached to anything

public class SingletonUtility
{
        //The first thing we need to do is create a dictionary that is going to hold every reference to the spawned SingletonObjects. This is in the System.Collections.Generic library, and instead of just including that whole library for one little thing, we can just reference the library and pull Dictionary out of it. The dictionary is going to use string values as keys, which will be generated from the type of the object added to it. This will make sure that there is only one of each singleton object.

        protected static System.Collections.Generic.Dictionary<string, Behaviour> registeredSingletons = new System.Collections.Generic.Dictionary<string, Behaviour>();

        //Notice how we also made it static. This is because all of the references are static objects, and they are created as soon as the objects spawn. If you were to add them to this object and it wasn't static, you would be trying to add it to something that doesn't exist yet, and it wouldn't know what to do. Because of this, all functions within this class are also going to be static.
     

        //The first function in the SingletonUtility class is called destroyOtherExistingObjects(). This class goes through the dictionary and checks to see if the new object passed into the function is already referenced or has a duplicate in the world

        public static void destroyOtherExistingObjects(Behaviour objectType)
        {
                //So first we check if the object is in the dictionary by checking the string value of its type

                if(registeredSingletons.ContainsKey(objectType.GetType().ToString()))
                {

                        //If it is we find every single object of that type and put it in an array

                        Behaviour[] temp = GameObject.FindObjectsOfType(objectType.GetType()) as Behaviour[];
                             
                        //If that array is larger than one, and is not the same object as the one already inside our dictionary, we get rid of it       

                        if(temp.Length > 1)
                        {
                                for(int j = 0; j < temp.Length; j++)
                                {
                                        if(temp[j] != registeredSingletons[objectType.GetType().ToString()])
                                        {
                                                GameObject.Destroy(temp[j].gameObject,0.0f);
                                        }
                                }
                        }
                }
         }
     
        //The next function we add to this class is called registerSingleton(). This function is called when we use that read-only keyword get like up in the example I used for AudioManager. This function checks to see if the object passed can be added to the dictionary, and destroys all other objects of that type.

        public static void registerSingleton(Behaviour obj)
        {

                //So check the string value of the object's type and destroy other objects of that type

                if(! registeredSingletons.ContainsKey(obj.GetType().ToString()))
                {
                        Debug.Log(obj.gameObject.name + " registered as singleton");
                        registeredSingletons.Add(obj.GetType().ToString(), obj);
                        destroyOtherExistingObjects(obj);                        
                }
                //otherwise destroy that object and any other object of that type
                else
                {
                        destroyOtherExistingObjects(obj);                        
                }
        }
}


Now that's it for the two new classes in the tutorial. I'm sorry about the ridiculous wait time, and I'm hoping to get the others completed soon and up for your guys to see. Anyways, happy coding!

Wednesday, October 5, 2011

All Coded Out Today

Well guys I had some free time today, so I decided I'd get into some more hardcore coding. My mission today was to create a mesh fracturing tool, something that is much more work than I had originally thought it would be. I spent a good 4 hours on it today, and have nothing special to show for it.

I'm building this mesh fracturing tool in two parts. By this I don't mean that I am separating it into sections, I mean that I will be building it twice; Once to get it working, a quick and dirty prototype, and once to get it working more efficiently and properly using Voronoi and Delaunay Triangulations.

The way I have it set up currently is that it goes through the current mesh and adds random points within it, then regenerating triangles between the mesh and the new added points. The problem that I seem to be running into is that, I create the new mesh with all of the generated fragments, they all have the proper Mesh Renderers and Mesh Filters attached, but when the fractured mesh as actually instantiated into the world, there is nothing visible. Now it's not the fact that the normals are wrong, because I've already checked that, and I've gone through basically every option I can think of right at this moment, but I think I just need a break from it. Coming back to this with a fresh brain will probably help.

Other than that, the sound effects have come in, so the editing will happen shortly and the platformer will be 100% complete soon. I'll be putting it on Kongregate and letting the public test it, so hopefully any lasting bugs will be short lived.

On top of that I'm in the process of getting the next 5 tutorials completed all based on the ones listed in the Platformer's page at the bottom.

Last but not least, me and a buddy have started on a project, and I have been building a prototype of it. I will be creating a video showing the quick and dirty prototype I've built. It's been built basically in a couple of hours but in short it's a twist on the common Tower Defense games that I think will be refreshing and nice to see.

As you can see there's quite a few things I have planned over the next little while. This is all on top of working two jobs, one stupid one with 35-44 hours a week, and another which is teaching business math at the college near where I live. I'm also moving at the end of the month so I need to prepare for that as well, but who needs sleep anyways right?

Anyhow, I'm going to get back at it, something at least, maybe the prototype, maybe a tutorial, but definitely not the mesh fracturing tool for a bit, I've had a but too much of that for one day. Happy Coding!

Monday, September 19, 2011

Free Time Is Approaching!!!

I feel as though I am letting you guys down with my lack of tutorials and updates, and I really don't want to use my lack of time for an excuse once again but, the fact that there are only 24 hours in a day seems to be my problem.

But don't fret! More free time is approaching! I am slowly transitioning from my current job to a better one with less hours and more pay!! Woop woop!!

I recently got a job teaching math at college. Two days a week, whoopie i know, but the fact that I now have two days of only 2 hours of work will let me go full force into development of my own games and these tutorials.

I have a new platformer almost finished, I more or less just need to create the music and sound for it,( it's a real pain being a one man team). Yesterday I went through all of my textures and revamped them, so the game basically got a complete makeover. Other than the sound effects I just have to create a few static backgrounds just so you aren't looking into a skybox and do some performance testing. I'm hoping to get this game on Kongregate so when I do I will let you know!

I will also be creating a few new more in-depth tutorials on some managers for audio and level transitioning. There's also going to be a few new Editor scripts that I am updating and creating specifically for the next game I am creating, this time with a team(a small one, but I won't be doing everything this time, which is nice!).

I am creating a page for my new platformer, I haven't decided on a name yet so for right now I'll probably just  leave it as platformer and maybe create a few names and have a poll and let you guys choose. Here is a picture of the very first level.

As you can see the art is very low budget and cheap, but I'm not an artist, and like I said, all of the textures were done in one day. As was most of the models. Most of the models were created, rigged and animated within one day. They are blocky, but how many programmers do you know can model, rig, animate, unwrap, texture, create sound and music, and design games as well! Just you take it easy on my art skills!

I want all of my textures to look as if they were painted on, on some of the objects it looks good, like personally I thought my skybox turned out great, but other things just look like a blurred mess so I may update them again later. The nice thing about Kongregate is that I can re-upload a patch if necessary, whether I am updating art or code, or even adding new levels ooooh.

So on my new Platformer page I'm going to have a few other pictures of the game, and I'll try recording some footage so that you can see it in action even without all of the proper sound effects and particle effects in the game. I'm also going to create a list of the tutorials that I am going to create out of the scripts that I've made for the game. A big part of the development of this game was to create a bunch of scripts that I can re-use in a bunch of games on top of this one.

But anywho, I need to create the page and grab some pictures and decide on what I'm going to do with this in the future. So happy coding guys!!!!!

Thursday, July 21, 2011

Oh yeah...Ooops!

Oh boy am I ever sorry guys. So much for the bi-weekly updates right? I recently started working, (*cough* not saying where because it's not in the industry *cough*) and have been thrown on the night shift. As exciting as that sounds, after getting about 3 hours of sleep a day and working for 11, I am pooped.

I really want to keep these tutorials going, so when I get a few days off, I am going to catch myself back up and make a whole ton of them. Also, the RTS is on hold as well, I am making something a bit quicker first, and I will most likely be able to construct tutorials out of this as well, because there are a few tricks I've come up with since the older tutorial days, but don't worry!

I have every intention on creating the RTS! I also will have some Unreal Engine tutorials coming up since I had a bit of a project, which now, sadly is on hold as well, (not my choice this time! it was the rest of the team!!). I figure it's good to have some knowledge in both, you may learn a different approach in both unity and unreal if you have experience in both, so that can be helpful.

Just letting you guys know that I'm still around, but either don't have the time, or don't have the energy to create these tutorials. I will try though!!!!!

Anyhow, happy coding guys!!

Thursday, June 9, 2011

Cranky Cat: A Positively Perplexing Puzzle Pursuit!

Hey guys, just a quick game that I thought I would share called Cranky Cat. I know one of the programmers working on this game and he does really good work.

The game was built in around 3 months by a small team of 7, two programmers, two artists, two audio geeks and one jack of all trades and is currently on the Android market, and is awaiting the response from Apple for the iPhone, since they like to take their sweet time on things.

Here's a quick video of the game's trailer



Wednesday, May 11, 2011

Wednesday's Editor Tools 2: QuickComponentDelete

Ok guys, sorry about the massive delay between posts. I've just had a few things to take care of now that I am finished with school and back home temporarily.

This next editor script is going to make it easy for you guys to quickly delete components from multiple objects and their children. This is useful for when you make a booboo while attaching components or you swap one of your scripts out for something else.

Basically what this script is going to do is open up a display wizard and take in a string of the component that you want to remove from the objects in your selection.

What we are going to do is create a new C# file called QuickComponentDelete, and make the class extend ScriptableWizard.


using UnityEngine;
using System.Collections;
using UnityEditor;

public class QuickComponentDelete : ScriptableWizard
{
       
        /*We need something to take in a store the string name of the component you want to remove, so let's create a public string*/

        public string typeString;

        /*Next up let's create a static function called openWizard, and give it the MenuItem attribute so that we can find it in the menus on the toolbar. This static function is what will be called when you click on the QuickComponentDelete option in the menu*/

        [MenuItem("GameObject/Delete Components in Children Wizard")]
        static void openWizard()
        {

        /*Basically all we want this function to do is open ip a display wizard. There are other wizard functions that will take care of the functionality that we want, we just need a way for the user to access it*/

                ScriptableWizard.DisplayWizard("Set the string of type", typeof(DeleteComponentsInChildren), "Set");
        }

        /*The next function that we are going to create is called OnWizardUpdate(). This is an event that is called when the display wizard is opened or updated in some way shape or form. All that we are going to do is set the string variable helpString to something that will tell the user what to do.*/


        void OnWizardUpdate()
        {
                helpString = "Set the string of the Component type you want to delete:";
        }

        /*The next function we create is called OnWizardCreate(). The functionality added here is what gets called when the user clicks the create button. The create button will be called something else depending on what you name it. We have it called "Set" in this script, as you can see in the ScriptableWizard.DisplayWizard() function call*/

        void OnWizardCreate()
        {

                /*What we are going to do first is grab all of the object transforms in the current selection*/

                Transform[] allTransforms = Selection.GetTransforms(SelectionMode.Deep);
                /*Afterwards we are simply just going to grab the components of the string type that was passed and Destroy them on each object*/

                foreach(Transform currentTran in allTransforms)
                {
                        if((currentTran.GetComponent(typeString) != null))
                        {
                                Object.DestroyImmediate(currentTran.GetComponent(typeString));
                        }
                }
        }
}


That's it for this script. You'll notice that a lot of these editor scripts are very short and simple, but they save you quite a bit of time in the long run.

That's it for this week's tutorial, follow me on twitter, and keep coding!

Wednesday, April 13, 2011

Wednesday's Editor Tools 1: Import Utility

Alright, so since the poll said that you guys wanted bi-weekly updates, here they are! Starting now, I will be posting every Sunday and Wednesday. Wednesday's are going to cover editor tools, so that your life is made easier during production.

This first script is going to be called ImportUtility. Now a brief description of what this class does is check to see what is currently being imported, and making materials and prefabs if necessary. This will save you a ton of time in the long run, since creating multiple prefabs or materials at a time can be very tedious.

So, let's get started and create a new C# script called ImportUtility.cs.

using UnityEngine;

/*Since this is extending an Editor class, we are going to have to include the UnityEditor directory*/

using UnityEditor;

/*Since this class is going to need to know when an object is imported, we extend from AssetPostprocessor. AssetPostprocessor fires events when a resource is imported and even fires of different ones depending on whether or not it is a texture, a model or an audio asset.*/

public class ImportUtility : AssetPostprocessor
{

        /*The first event that we are going to overwrite is called OnPreprocessTexture. This event is called right before a texture asset is going to be imported so you can fiddle around with settings such as converting the texture to a normal map, which is what we are going to be doing*/

void OnPreprocessTexture()
{

        /*One thing that all projects should have is a naming convention, it makes things more organized and neat, and when you hand your assets off to someone else they know what they have before they even open up the file! So what we are going to do is check the name of the asset being imported, and if the name contains "_norm" we will convert the texture to a normal map on import*/

                if(assetPath.ToLower().Contains("_norm"))
                {

                /*Cast assetImporter as TextureImporter for extra options when importing a texture*/

                        ((TextureImporter)assetImporter).convertToNormalmap = true;
                }
        }

        /*The next event we overwrite is called OnPostProcessTexture. This is similar to the OnPreProcessTexture event, except this one isn't called until after the object is imported. So what are we going to do once we import this asset? On thing that I can think of that would be helpful is if it automatically created a material and applied the texture to it on import, so guess what we are going to do.*/

        void OnPostprocessTexture(Texture2D texture)
        {

                /*If the name of the asset contains _diff, then we will create a diffuse material for it*/

                if(assetPath.ToLower().Contains("_diff"))
                {
                        /*So let's create a new diffuse material and apply the texture being imported to it*/

                        Material mat = new Material(Shader.Find("Diffuse"));
                        mat.mainTexture = texture;

                        /*What we want to do next is set up a path to where the new material is going to go in our project folder. So we will remove the _diff from the path and add _MAT.mat so you know that it is a material just by looking at it, and Unity knows to save this asset as a material*/

                        string path = assetPath;
                        path = path.Remove(path.LastIndexOf("_"));
                        path += "_MAT.mat";

                        /*Once that is finished, we will use a class called AssetDatabase to create the material in the project folder, and rename the material to the texture's name so that they match*/

                        AssetDatabase.CreateAsset(mat, path);
                        AssetDatabase.RenameAsset(path, texture.name);
                }
        }

        /*So now we've completed the texture importing part of this class. Now we are going to be moving onto the models*/


        /*Before we import any model, let's make sure that we have a few settings set up a certain way*/

        void OnPreprocessModel()
        {

                /*cast assetImporter as ModelImporter to get special model importing tools and functions*/

                ModelImporter importer = (ModelImporter)assetImporter;

                /*We want unity to import the models using the units that maya or max uses, just to keep everything consistent between tool to engine*/

                importer.useFileUnits = true;

                /*We also don't want to automatically add colliders unless specified, so let's turn this option off too*/

                importer.addCollider = false;

                /*Unity will also import any materials applied in the hypershade(Maya) or material editor(Max) automatically. Now if this is what you want, then go nuts and use it, but I find it to be a pain since i create my own materials anyways, so I turn this option off as well*/

                importer.generateMaterials = 0;

                /*Now there are also options for for automatically importing animations, compression rates etc. that you can player around with. For the project that I was working on when i created this, this was more or less enough*/

        }

        /*So once we have those import options set up, we need to create prefabs for the models that are being imported, because they are handy, and more efficient*/

        void OnPostprocessModel(GameObject root)
        {

                /*recursiveColliderCheck() is a function declared below that will go through each object in the model and check to see if the name of it contains collider. If it does it adds a MeshCollider component to it and moves to the next one*/

                recursiveColliderCheck(root.transform);

                /*We are going to take the same approach for generating the prefab asset path as we did with the material*/


                string prefabPath = assetPath;
                prefabPath = prefabPath.Remove(prefabPath.LastIndexOf("."));
                prefabPath += ".prefab";

                /*If the prefab already exists then we don't need to create a new one, otherwise go through the steps*/


                if(AssetDatabase.LoadAssetAtPath(prefabPath, typeof(object)) == null)
                {

                        /*First we will create an empty prefab to store the mesh in*/

                        Object prefab = EditorUtility.CreateEmptyPrefab(prefabPath);

                        /*This is a temporary GameObject that will be the parent of the mesh. I had explained in a previous tutorial why we want to do this but I will explain again. Animations are done locally, so if the object animating is not parented, it will jump to where ever it was during that animation and play it. So if the animation started at the origin (0,0,0), the object will jump there and animate. If the object is parented, it will stay where the parent of the object is and animate at (0,0,0) locally.*/

                        GameObject obj = new GameObject("____delete me");

                        /*We move the gameobject to the root's position and parent it*/

                        obj.transform.position = root.transform.position;
                        root.transform.parent = obj.transform;

                        /*In order to store the GameObject in the prefab we need to use a static function EditorUtility.ReplacePrefab(). You pass the object going in and the prefab that you are replacing, and you are good to go*/

                        EditorUtility.ReplacePrefab(obj, prefab);

                        /*Before you do this line, go into the editor and create a new tag called delete. We need this so that we know what to delete after importing*/

                        obj.tag = "delete";

                        /*Then we will rename the prefab to the name of the mesh*/

                        AssetDatabase.RenameAsset(prefabPath, root.name);
                }
        }

        /*Now that we have done this to textures and models, we are going to do the same to audio. For me, the default audio settings were fine, so I leave OnPreprocessAudio out. Instead I just skip ahead to OnPostProcessAudio and create a prefab for it just like I did with the models*/

        void OnPostProcessAudio(AudioClip clip)
        {

                /*So once again, edit the asset path and create a new empty prefab*/

                string path = assetPath;
                path.Remove(path.LastIndexOf("."));
                path += ".prefab";
                Object prefab = EditorUtility.CreateEmptyPrefab(path);

                /*And create a new GameObject*/

                GameObject obj = new GameObject("____delete me");

                /*What you are going to want to do then is add an AudioSource component and set the clip to the clip being imported*/

                AudioSource audio = obj.AddComponent<AudioSource>();
                audio.clip = clip;

                /*Once that is complete we will replace the prefab and set the tag to delete*/

                EditorUtility.ReplacePrefab(obj, prefab);
                obj.tag = "delete";
                AssetDatabase.RenameAsset(path, clip.name);
        }

        /*This function is called in the OnPostprocessModel event. It is recursive, so what it does is check through each child of the object and add a MeshCollider if the name of the child contains collider*/

        private void recursiveColliderCheck(Transform tran)
        {
                if(tran.name.ToLower().Contains("collider"))
                {
                        tran.gameObject.AddComponent<MeshCollider>();

                        /*If the object has grandchildren we want to check those too, so for each child in this object, we call the function again*/

                        foreach(Transform currentTran in tran)
                        {
                                recursiveColliderCheck(currentTran);
                        }
                }
        }

        /*This event is called once every asset is imported. What we use this event for is deleting all of the GameObjects we created with the tag delete. We cannot delete the objects during the events because Unity will just completely crash. Of it works for you, then thats awesome, but that was the workaround that i ended up trying out and it works like a charm*/

        static void OnPostprocessAllAssets (string[] importedAssets , string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
        {

                /*So let's find all of the objects in the scene with the tag delete*/

                GameObject[] list = GameObject.FindGameObjectsWithTag("delete");

                /*We will then destroy these objects and you will never know that they existed*/

                foreach(GameObject obj in list)
                {
                        Editor.DestroyImmediate(obj);
                }
        }
}
        
That's it for this script. It seems simple, but it will save you a lot of time in the long run. Making prefabs individually is a real pain, and is very tedious, so why not get something to do it for you.

This is it for Wednesday, keep coding!