Customizable Navigation Bar

Friday, September 27, 2013

Unity3D Tutorial Requests 1: The Colour Picker

This is the start of a new series where I do a tutorial based on what you guys request. This request was for the ability to choose the colour of an object through a colour picker, and this is what I came up with. A very basic colour swapping script, and also a slighty more advanced script that uses vertex colours instead of the material colours.

I created a video tutorial that can be seen here. The text version is right underneath.


Now before you start this tutorial, grab the resources HERE.

Once you import the resources, open up the level included with the package.

You should see 4 assets in your project window. A C# script, a texture, a shader and a material. For this first half of the tutorial, we are only going to be using the script and the texture. You'll get a warning from the shader, but that is OK, because we will be fixing that in the second half.


Now open up the ChangeColour script so we can fill it out, and change the colour of the cube in the scene.

using UnityEngine;
using System.Collections;

public class ChangeColour : MonoBehaviour
{
    //Before we start, we need to store some variables that can be accessed in the editor, and can be used throughout the script.

    //Our first variable will be the texture displayed on the screen, so we can choose the colour from it
    public Texture2D colourTexture;
 
    //Next, we want to store the Renderer of the cube in the scene, this way we can change the colour of the material on it
    public Renderer colouredCube;

    //lastly we store a Rect that describes where our texture is going to be displayed on the screen.
    private Rect textureRect = new Rect (10, 10, 200, 200);

    //Now everything else is done within the OnGUI function.
    void OnGUI ()
    {
        //Simply just draw our texture in the position we gave it at the beginning
        GUI.DrawTexture (textureRect, colourTexture);

//We want to check what event is happening during OnGUI. In this case we want to check if the mouse button has been released, so that we know if the user clicked on the texture or not
        if (Event.current.type == EventType.MouseUp) {

            //get the mouse position
            Vector2 mousePosition = Event.current.mousePosition;

    //if the mouse position is outside the texture being displayed on the screen, just exit out because we dont want to do anything.
            if (mousePosition.x > textureRect.xMax || mousePosition.x < textureRect.x || mousePosition.y > textureRect.yMax || mousePosition.y < textureRect.y) {
                return;
            }

            //if we made it here, we know that the mouse is somewhere on the texture. Since we know this, we need to figure out a way to get the colour of the texture, wherever the mouse currently is. In order to do this, we need to calculate the UV coordinates of the mouse on the texture
            float textureUPosition = (mousePosition.x - textureRect.x) / textureRect.width;
            float textureVPosition = 1.0f - ((mousePosition.y - textureRect.y) / textureRect.height);

            //Once we have the UV coordinates, we use a function called GetPixelBilinear on the texture. This will return the colour of the texture at the given UV coordinates.
            Color textureColour = colourTexture.GetPixelBilinear (textureUPosition, textureVPosition);

           // and now that we have our colour, we just apply it to the cube's material
            colouredCube.material.color = textureColour;
        }
   }
}

Now that our script is finished, create a new GameObject and drag the script onto that object. You will see that the script asks for a Texture2D and a Renderer in the editor, so drag the Colours texture and the Cube onto the Change colour script to attach them.


Now that you have the objects attached to the script, you should be able to hit play, and choose the colour of the cube by clicking on the texture.


Now that we have this simple version working, lets try something else. We are going to get the exact same effect, but instead of changing the material colour, we are going to change the vertex colours of the mesh itself. Changing the colour of the object's material will cause Unity to instantiate a brand new material, which will add to the draw calls of the game. If you are working on mobile, the less draw calls you have the better, so this is why we will go over the vertex colouring.

So open up your ChangeColour script again and lets add that functionality.

In your script lets create a new function called changeMeshColour, make it return void, and make it so that it has a colour parameter, like so

void changeMeshColour (Color newColor)
{
    //Now the first thing we are going to so is create a colour array that is the same size as the mesh's vertex count
    Color[] colorArray = new Color[colouredCube.GetComponent<MeshFilter> ().mesh.vertexCount];

    //then we will go through each vertex and set it to the colour that was passed into the function
    for (int i = 0; i < colorArray.Length; i++) {
        colorArray [i] = newColor;
    }

    // and then we just reassing the mesh's colour array to the one we just created.
    colouredCube.GetComponent<MeshFilter> ().mesh.colors = colorArray;
}

And that's it!

so now that we have that function in our script, in our OnGUI function, we replace

colouredCube.material.color = textureColour;

with

changeMeshColour (textureColour);


So this is what your script should look like once everything is completed.

using UnityEngine;
using System.Collections;

public class ChangeColour : MonoBehaviour
{
       public Texture2D colourTexture;
       public Renderer colouredCube;
       private Rect textureRect = new Rect (10, 10, 200, 200);

    void OnGUI ()
    {
        GUI.DrawTexture (textureRect, colourTexture);

        if (Event.current.type == EventType.MouseUp) {

            Vector2 mousePosition = Event.current.mousePosition;

            if (mousePosition.x > textureRect.xMax || mousePosition.x < textureRect.x || mousePosition.y > textureRect.yMax || mousePosition.y < textureRect.y) {
                return;
            }

            float textureUPosition = (mousePosition.x - textureRect.x) / textureRect.width;
            float textureVPosition = 1.0f - ((mousePosition.y - textureRect.y) / textureRect.height);

            Color textureColour = colourTexture.GetPixelBilinear (textureUPosition, textureVPosition);
            changeMeshColour (textureColour);
        }
   }

    void changeMeshColour (Color newColor)
    {
        Color[] colorArray = new Color[colouredCube.GetComponent<MeshFilter> ().mesh.vertexCount];

         for (int i = 0; i < colorArray.Length; i++) {
             colorArray [i] = newColor;
        }
        colouredCube.GetComponent<MeshFilter> ().mesh.colors = colorArray;
    }
}

Now, in order to get this script to work, and to have the colour of your cube to change, we also need to create a new shader that supports vertex colouring. So open up the VertexColours shader in the project window and lets add that functionality.

For the most part this is just a basic shader, I'm only going to walk you through specific parts

Shader "Custom/Vertex Coloured" 
{
    Properties 
    {
     _MainTex ("Base (RGB) Alpha (A)", 2D) = "white"{}
    }

    Category
    {
        Lighting on
        ZWrite on
        Cull back
        Blend SrcAlpha OneMinusSrcAlpha

        //The call to BindChannels tells the graphics card which data it needs to pay attention to.
        BindChannels {
        Bind "Color", color
        Bind "Vertex", vertex
        Bind "TexCoord", texcoord
        }

        SubShader 
        {
            Pass
            {
            //This makes the material take ambient light and display itself as a regular diffuse
            ColorMaterial AmbientAndDiffuse

                SetTexture[_MainTex]
                {
                    //this combines the texture with the vertex colour which is displayed as primary. The keyword DOUBLE makes the outcome twice as bright. Without this it will end up much darker than it is supposed to be
                    Combine texture * primary DOUBLE, texture * primary
                }      
            }
        }
    }
}

And that is all for the shader. Now drag the Vertex Colours material onto the cube, hit play, and you should be able to choose the colour of the cube again, but in this case, you could have 40 cubes all different colours, and they could still be batched by Unity, saving draw calls.

Well, that's all for today folks. If you had trouble somewhere along the way, or just want the completed project, you can find it HERE. If you liked this tutorial, please share it, and let people know where you got it from.

Also follow me on Twitter at https://twitter.com/purdyjo

Take it easy everyone!

Friday, September 20, 2013

LGUI, My Unity GUI Project

One of the first projects that I took on when we started LoneWolfPack Interactive was creating a new interface system for Unity. We were looking to develop for mobile devices, and after hearing and reading horror stories about the built in Unity GUI system on mobile, we decided that we needed to look at other options.

There were already other GUI options out there, such as EZGUI and the super popular NGUI, but at the end of the day we decided to create our own system. This way we could customize it, add in our own features, and even possibly toss it on the asset store once we got it to where we liked it. As of right now, I am only comfortable with calling it an alpha. There are still a lot of features I would like to add to it, a few bugs here and there that I would like to fix, and a few things that I would like to completely restructure. For now though, it is in a very usable state, and so far it has been used in every one of our games.

What I want to do is show you where we started, where we are now, and what I have planned for it. I'm going to start with the very first iteration of LGUI, which I made a brief post about last year. The horrifying way that I had approached it still gives me shivers, and the second iteration of the system is barely recognizable.

LoneWolfPack Interactive's very first game was called President 3D. We made a mobile version of a popular card game, thinking that it would be a good first project to see how everyone worked together. The first thing I had tackled was an interface system, which was interesting since I didn't really have any ideas in my head as to how it would look or function.

LGUI 1.0 was awful. There were Z-fighting issues everywhere, the editor was ridiculous, and it was missing simple things like scroll bars. There was also the issue of forcing the near clipping plane to a really really small value just so you could have the GUI close to the camera without it going into something within the scene. Doing anything with LGUI was a struggle, even for me, and I was the one who made the thing. This caused our first version of President 3D to have a really ugly interface. We couldn't do what we wanted with it, but we were just happy to have something functional for the most part.

This was how you chose the textures for the buttons and such. You had to click and drag a rectangle to where the texture was on the altas...

This screen was used to position the GUI on the screen. Not only do you have no idea which object is in front of another, but the GUI is aspect ratio locked, so everything would be distorted on different screen sizes.

This is a really really early version of President, but it gives you the idea on how simple the interface for the game looked and what we were stuck with.

So once we released President 3D to the Google Play Store, the first thing I wanted to do was completely scrap LGUI and start from scratch while Jermaine, our other programmer, started on our next project CuBlitz.

The one thing I really wanted to do was create a system that could support both 2D and 3D GUI. I wanted to be able to have a interface like you would see anywhere else, where you have options buttons and a general HUD overlay on the screen, but at the same time have that same system be able to be used for things like buttons on a door's keypad within the level. So that is what I set out to do.

My first obstacle was to figure out a way to have the 2D overlay always draw over top of everything else. I had a few ideas floating around, but what I ended up doing was creating a second camera that would only draw the 2D interface. In order to do this I needed to create a separate layer for just the 2D interface, and make sure that only the LGUI camera would draw that layer. It was a simple bit of code really; since the layers are flags within Unity, I could use simple bit operations to make sure cameras would skip the LGUI layer. Like this:

foreach (Camera c in GameObject.FindObjectsOfType (typeof(Camera)))
{
    if (c.gameObject.layer != LayerMask.NameToLayer ("LGUI"))
    {
        c.cullingMask = c.cullingMask & (c.cullingMask + (1 << LayerMask.NameToLayer ("LGUI")));
    }
}

Once that was done I then tried to see what and how much code I could scavenge from the deceased and now rotting LGUI 1.0. After fiddling around with positioning 2D objects in a perspective camera, it dawned on me that I am an idiot, and the entire 2D interface made more sense with an orthographic view. Not only could I skip the trigonometric functions to figure out where objects were supposed to go, it completely solved the Z-fighting issues I had near the edges of the screen.

The next idea I had was to set up the interface in a way that could be stretched, similar to what Unity does with their buttons and scroll bars. The buttons in the built in Unity GUI system use a very small texture that gets stretched out. To do this I created a completely different mesh, where I could stretch the middle and edges separately.

The left mesh is what is used for basic textures that would be used for icons etc. The mesh on the right is for buttons and anything that can be stretched out

And this is what I ended up with:
All four of these buttons use the same texture. The top left is using the basic mesh, and it shows the unstretched 21x21 texture used. The rest of the buttons use the stretchable mesh, and can be stretched to whichever width and height you want without losing detail.
As you can see it turned out really nice, and you can have sharp looking displayed while using extremely small textures.

The next feature I wanted to make sure that was in was compatibility with LTexturePacker, our texture packing tool. Reducing draw calls is important when it comes to mobile, and using atlases and combining materials helps with that greatly. One of the benefits of LTexturePacker is that it exports an XML file with all of the sprite data, plus it exports an enumerator so that you can easily set the UVs in code with the tool. What I wanted to do was set up the editor so that it would read this XML file and you could choose which texture you wanted from a foldout menu. Like this:
With LTexturePacker integration you can pack your textures into an atlas and easily plop them onto your buttons and textures in LGUI

Once LGUI was running and had these features added to it, we decided that we would make an upgrade to President 3D. We scrapped the old interface and built it from the ground up using LGUI 2.0. The main menu was no longer 2D, it was now set up as a 3D menu, where everything was placed on cards being dealt out to the player. It created a much more dynamic feeling menu, and looked a lot cooler.




We took a similar approach in the CuBlitz menu. Most of the main menu was placed in the 3D world and the camera zoomed around the room to go to different menu locations.




Now that LGUI is in a very usable condition, I can finally bring out a list of things I really want to do with it. I'm no longer trying to figure out a way to make a scroll area, or how to mask objects, I can actually take a step back and say, "this is good, but how do I make it great?".

The one recent update I made was an overhaul to the text system for LGUI. I took advantage of Unity 4's markup text and dynamic fonts on mobile to make LGUI's text much more interesting. Now that dynamic fonts are available for all platforms, you can create boldfaced, italics and regular text using the same font file. On top of that you can change the colour, boldness and italics of individual words and letters making for much more interesting labels. Using the new text mark up also reduced the draw calls for the text because now they can all use the same material and have completely different styles and colours. Unity 4 added a lot of features that I still haven't had a chance to completely try out yet (LoneWolfPack Interactive only upgraded to 4 about a month ago), and I am looking forward to seeing what else we can optimize in LGUI.

I've been looking around at other interface systems and games in general to see what they do, what they can't, and how a different approach to things may help build LGUI into a much more functional, easier to use, and useful tool than it already is. As I said earlier, I am only comfortable calling LGUI an alpha. It has the basic features, but it needs a set of scripts to allow this to become a more artist friendly, and robust tool. Here are my future tasks for LGUI:

  • The ability to rotate 2D GUI
    • This is the biggest shortfall with LGUI so far. Anything you create in 2D cannot be rotated, and the way that the 2D is set up it would basically need a rewrite. As of right now it just checks if the mouse is within it's Rect position on the screen, and you can't take rotation into account if you are doing a check that is so simple.
  • Flipping GUI
    • Right now you can't flip the texture on the LGUI objects, so you need a separate texture for something like a left or right arrow. 
  • Better movement and easing tools
    • There is a really basic utility script that has different lerping functions, but it would be nice if you could just call a function and tell your object to bounce to another part of the screen in the time that you want it to.
  • Keeping size ratio of texture
    • Right now there is a script for 2D objects to keep the size ratio of them the same no matter what the screen resolution and aspect ratio is, which is nice, but it shouldn't be a separate script, and it should also be a part of the 3D objects as well, that way you can scale up the texture to which ever size you want and not have to worry about fiddling around and remove stretching
  • Better audio control
    • Right now if a button uses audio it creates its own AudioSource. If you have hundreds of buttons it can be very inefficient, it would be better to have a static audio source that all LGUI objects use and it moves around and plays when necessary.
  • Using custom handles
    • Unity has something called handles. This is what you use when you drag to scale, move or rotate and object, modify the size of colliders etc. It would be really nice to have handles for LGUI objects that way you can just drag and scale or move them instead of copying and pasting values into the editor.
So while LGUI is still extremely useful, you can see that I still have a long ways to go before it is what I would consider finished. I hope you enjoyed reading about my failures, where we are now and where we want to go. That's all for this week guys, and if you did like it remember to share!

Friday, September 13, 2013

Why You Need A GDD And Asset List

As a developer, and someone who knows fellow developers in the game industry, one thing that I can say for certain is that organizing yourself and your team is much easier said than done. Throughout development there may be a point, where you , or someone you work with won't know what to do next, or won't know where something fits in. In order to overcome this, most developers create a Game Design Document(GDD) and an asset list, so that every single thing that you will ever need to know about your project is in one location.

A GDD is a document (very large and in depth in most cases) that contains every single detail that you would ever want to know about your game. It contains details about your art style, your story, the characters, the user interface, everything. The GDD is your game in its entirety; every detail you would ever want in the game even if it isn't possible to accomplish. This document is there so that anyone that will ever work on the project can determine what it is that you are wanting to accomplish, and what it is that they are going to have to do to make that happen. Your final project may only end up being 10-25% of what is actually in the GDD, but the whole point is so that if anyone has any questions at all they have a reference point and don't have to ask you 30 questions.

The GDD is not a write once and done type of document. If anything in the design changes you need to update the GDD so that everyone else knows what changed. This way, down the road you don't end up with wasted work. This process does sound like a pain (because we would all rather be at our computers grinding away at our sweet new project), but the hour you spend updating the GDD every once in a while will save you many hours of explaining and searching later on.

The GDD is also important even if you are working alone. Your game may be your baby but you may notice plot holes, things missing, or things that just don't make sense once you have everything written down. The GDD also helps you think about things that you may have not thought about beforehand. How do you really want this game to look? What sort of functionality do you want in the interface? What type of music would fit this game? If I am doing this to make money, how am I going to accomplish that? You'd be surprised at just how much is missing from your idea once you start writing things down.

Now, there is no real standard as to how you should organize your GDD. As long as it flows, makes sense, and has everything in it, you should be perfectly fine. In general though, there are a few categories that you will want to start with, and it usually flows something like this:
  • Story
  • Characters
  • Level/Environment Design
  • Gameplay
  • Art
  • Sound and Music
  • User Interface, Game Controls
Some of these sections may not apply to your game, and there may be sections that do apply that you do not see here, such as an economy section if you are creating a free to play game with in game currency.

Now that you have a basic understanding of how to show off your idea and organize, you can start your asset list, to organize yourselves and your development.

Your asset list is just as powerful for determining what your game is going to look like, sound like, and to figure out what was missing from your idea. This is where you get into the most detail with your design. Every single asset that will be in the game should be listed here, whether its a modular piece to a building, a plane that you use for grass in your environment, or a bottle that will be sitting on a counter; every single thing that you can think of.

The asset list is great for determining the actual scale of your game, because suddenly you go from having a sweet idea to having a list of 300 or so models that need to be created, unwrapped, textured and placed into your levels, and having a couple dozen sound effects just for ambient noise, gun sounds, animal sounds and any other sounds you can think of. Those are just the basics. There are also particle effects, cinematics (if that's your thing), a list of all of the concept art you'll be needing to determine what things will look like, animations, and I'm sure there are plenty of others that I am not thinking of as well.

The great thing about the asset list, is that once you have completed it, suddenly you have a giant to-do list, and you will never be wondering what you should be working on next. You can even take your asset list to the next level. Set up an excel sheet that marks the progress on each asset, and have a sheet track the overall progress of your game's completion. Another thing you can do with your asset list is determine a priority of your assets and colour code everything. The more organized you are, the easier things will be down the road.

Completing a GDD and asset list will only benefit you. It's great to have everything in one place so that you don't need to worry about people wondering what they need to do next. Because I am super nice, I prepared a skeleton for a GDD, and a template for an asset list, just for you. Approaching the GDD and asset list can be a daunting task, and I always find that filling out a skeleton is a lot easier than starting from scratch.

The skeleton for the GDD can be found here: GDD

The template for the asset list can be found here: Asset List

That's all for this week, hopefully this post was somewhat helpful! Share it with your friends if you thought it was!

Friday, September 6, 2013

Minimum Viable Product: Why Small Developers Need Them

The concept of a Minimum Viable Product (MVP) is very popular in small start ups and software development. It helps us determine at a minimum what we need to accomplish, while also determining what our customers really want. There is no science to this, it is based on judgement and knowledge of your customers and product. The MVP can be confusing, and it may take some time to make sense of it all.


So what is a Minimum Viable Product anyways?

To state it basically, your MVP is your product with only the features that are required to complete the job it was designed for, and only the features that will get people interested and talking about your product. For the most part, your MVP depends on the product you are trying to sell. If it is a service, your MVP could be as simple as a Google Ad or a webpage, if you are creating a game or a sitcom, you may want to create a basic prototype first. The goal of the MVP is to make sure people are actually interested in what you are producing, and to catch it early if they aren't. The worst thing you could do is spend 6 -12 months of time and money developing a service, only to find out that absolutely no one is interested in your product.

Keep in mind that your MVP is just the core functionality or core idea behind the service or product you are trying to ship. The last thing you want to do is ship something broken and say that you will patch it later. You are trying to get people to talk about what you are offering, so leaving them with a broken and buggy service is going to lead people in the other direction.

You also want to remember that you're MVP is out there for you to get constructive feedback on your product. Only feedback. The MVP is not an open source methodology, you aren't asking for people to contribute to the project, and you aren't asking for people to change the story or core functionality of your product. The vision of the product stays the same, but as you receive feedback from your early adopters, you iterate, improve, and develop the service or product that people are looking for. If you get a dozen iterations in and your customers are still not happy or people still aren't interested, that's when you decide that your idea may not be a viable product at all, and its time to move on.

Hopefully by now you can understand why this is important to developers, big or small. There has been quite a few times that I've seen people say that they are going to go out and create a game that will revolutionize the gaming industry and change everything. The problem with these people is that their idea appeals only to them, and they haven't checked to see if it really is what people want in a game or product. Two years later they are still working on the same project, they are nowhere close to finishing, and they still don't know if the world is ready for their Massively-Multiplayer-Online-Real -Time-Strategy-First-Person-Shooter-Role-Playing-Card-Game (MMORTSFPSRPCG).

You need to remember that creating games takes a lot of time, and a lot of resources, especially if you have big ideas. Your best approach is to fill out a Game Design Document (GDD), which I will cover later, and figure out the minimum amount of features, and minimum amount of story you can get a way with without losing what your product is really about. This way you can prototype, iterate, see if this is the game that your audience really wants. You don't want to spend years of your life creating something for yourself, assuming that everyone else is going to love it.