Programming Chapter 5

From Unify Community Wiki
Jump to: navigation, search

Contents

Last Stand

Yep, you know the drill. Create "Example-5" scene, "Example-5 Assets" folder and lets get to work. Create a script in the folder and name it "Player" and have it look like this:

using UnityEngine;
using System.Collections;
 
public class Player : MonoBehaviour
{
    void Start()
    {
    }
 
    void Update()
    {
    }
 
    void OnGUI()
    {
    }
}


Get Structured

A structure is a lightweight object... we'll just leave it at that. Do a search on "C# struct" for more detailed information. For the most part they can be created similar to classes. Add the following to our Player class, before the methods:

struct PlayerName
{
	public string First; 
	public string Last;
}
 
public PlayerName name;

Save and... argh! Error, something about PlayerName being less accessible. This is because the struct we created doesn't have an access modifier, and by default structs are internal. So change the struct to:

public struct PlayerName

OK, no errors but a warning saying that Player.name hides inherited member. Apparently UnityEngine.Object already has a member variable called name, that's a little annoying. So we should probably rename our name to something like:

public PlayerName playerName;

OK, warnings are gone. But lets do something that we can see. So type this code in these methods:

void Start()
{
    playerName = new PlayerName();
    playerName.First = "Joe";
    playerName.Last = "Test";
}
 
void OnGUI()
{
    GUILayout.Label(playerName.First + " " + playerName.Last);
}

Pretty simple huh? If not that's alright, the more you use it the more familiar you'll be.

Proper Tea

Properties are a way to encapsulate data, huh? Do a search for object oriented programming and data encapsulation, I'll wait here while you go. Or I'll just show you an example of what can be done with properties. They are sort of like a method, with a get function and a set function, but they appear as a variable. Still confused? OK, lets write some code. Add this property somewhere in our Player class, I'll put mine before the methods:

public string FullName
{
    get
    {
        return playerName.First + " " + playerName.Last;
    }
}

You see it starts much like a function, but there are no parameters. Also the keyword get is used for when you use this property (as opposed to assigning this property a value). We can use it like so (update your OnGUI method as follows):

void OnGUI()
{
    GUILayout.Label(FullName);
}

Notice "FullName" looks similar to a variable, but we know behind the scenes that it concats our first and last name from the PlayerName structure. Go ahead and run it... brilliant!

Now we can also have a set method in our property. We're going to go a little crazy here, buckle up:

public string FullName
{
    get
    {
        // Add an * so we know First and Last are really separate
        return playerName.First + " * " + playerName.Last;
    }
    set
    {
        // String array of names returned by method "Split"
        string[] names = value.Split(new char[] { ' ' });
 
        // If we have at least one name in the array, assign it to first name
        if(names.Length > 0)
        {
            playerName.First = names[0];
        }
 
        // If we have a second name in the array, assign it to last name
        if(names.Length > 1)
        {
            playerName.Last = names[1];
        }
    }
}

Oh my, I've gone mad. It's really quite simple, really! To the get statement we added an "*" just to give a little more visual feedback (we can take it out later). Now we've added a set method and... one step at a time.

string[] names = value.Split(new char[] { ' ' });

First you should recognize that we're creating a string array called names, that's simple. The value is a keyword within the set method. Whatever is being assigned to FullName will get put in the "value" variable, no matter what type it is. So what type is value? It is whatever type your property is declared as. In this case, we declared FullName as a string type, so value is a string.

So, being a resourceful coder, we go look up the documentation on string. Go to Mono Documentation and click on the link to the System namespace. Most basic types will be in the System namespace. Next look for String and click the link to that. This will give you detailed information about the string and even some examples, but we want to see what Methods are available to see what we can do to a string. So at the top where it says "See Also: String Members", click on the String Members link. Now look for the section that says Public Methods... or just look for the Method called "Split".

Split says it takes a char[] of characters that we want to split the string at, and returns a string[] of the resulting strings. So, we pass in a char array, initializing it with 1 item, a blank space. So we're going to split a string on every space, the first item will go in "playerName.First" and the second item returned will go in "playerName.Last". Lets actually set it now it the Start method, change it to:

void Start()
{
    FullName = "Joe Test";
}

Run the code and, amazing, it works! Try putting a third name in, two spaces between names, add a second parameter to Split with the number 2 (doc says second parameter is the max number of elements to return in the array).

Finishing Touch

Lets say we want to center all of our GUI on the screen. To do that we need to use the Screen types width and height. Lets modify our Player.cs file to have this:

void OnGUI()
{
    int x = Screen.width / 2;
    int y = Screen.height / 2;
 
    GUILayout.BeginArea(new Rect(x, y, Screen.width, Screen.height));
    GUILayout.Label(FullName);
    GUILayout.EndArea();
}

If you've got a keen eye (or if something didn't quite make sense in code), yes, we're starting our x position at the middle of the screen as well as our y position, so the code will be slightly off to the right and down, not exactly center. But forget that for now, how are we using Screen.width and Screen.height without initializing them? We had to create a Rect! Well, they must be static variables or properties. Remember, static functions, variables, properties, etc. must be used without an instance.

To Duplicate, Or Not

Well if you look at that OnGUI method, you may notice that you'll have to do the same thing over and over for every interface you use that you want centered. This is where inheritance comes in. Just follow along. Create a new script, call it CenteredInterface and make it look like so:

using UnityEngine;
 
public class CenteredInterface : MonoBehaviour
{
    protected int xCenter;
    protected int yCenter;
 
    protected virtual void OnGUI()
    {
        xCenter = Screen.width/2;
        yCenter = Screen.height/2;
    }
}

The virtual before OnGUI tells the compiler that child classes can override this method and provide their own implementation. Now go back to your Player.cs file and change the class declaration to inherit from CenteredInterface instead of MonoBehaviour, like so:

public class Player : CenteredInterface

And we'll need to change the OnGUI to this:

protected override void OnGUI()
{
    base.OnGUI();
 
    GUILayout.BeginArea(new Rect(xCenter, yCenter, Screen.width, Screen.height));
    GUILayout.Label(FullName);
    GUILayout.EndArea();
}

Notice that we had to change the access modifier to the same as the base class and we had to add override, which is another keyword corresponding with virtual. It is used to tell the compiler that we are overriding the behavior of our base class. Also base is another keyword that is used to access our base class (useful since our overridden values have the same name). By calling the "base.OnGUI()" before our code, the base OnGUI method gets executed first, so xCenter and yCenter get set before we use them.

Don't worry if you don't totally understand all of it, we'll cover more inheritance in the future. For now, be glad you completed another chapter!


Programming Index : Previous Chapter : Next Chapter

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox