Level editor – introduction

To create something that can save files, we'll need to cover new territory. We've already discussed working with PlayerPrefs back in Chapter 5, Shooting Gallery – Working with Animations and Tweens, but there can be a time when you want to save things other than just string, int, or float variables. To deal with complex data types, there are more things that we can do. Perform the following steps:

  1. We are going to first open up our 3D Platformer project we created back in Chapter 6, Side-scrolling Platformer. Open your gameplay scene (in the example code saved as Gameplay) from the link described in the project setup.
  2. As it currently stands, the ability to create our levels is inside our GameController script. For this project, however, we're going to extract that functionality and move it over to a new class. In Project Browser, go to the Scripts folder and create a new C# script named LevelEditor. With this finished, open your IDE.
  3. Once there, click on the GameController.cs file and highlight the level variable. Cut it (Ctrl + X) and paste it (Ctrl + V) as a declaration in the LevelEditor class.
  4. After this, remove the BuildLevel function from the file and stop it from being called in our GameController script's Start function. Instead of calling it here, we will be writing a new version for our new LevelEditor script.

    Next, we want access to our goalPS variable inside the LevelEditor class so that we have a reference to the particle system to turn to when we collect all the orbs, but right now, it's private. Now, I could set this variable as being public and be done with it, but instead, we're going to use another aspect of programming in C# named properties.

    Note

    If you decide to make something public but don't want to see it in Inspector, you can write code as the following:

       [HideInInspector]
      public ParticleSystem goalPS;
    
  5. Add the following code after your goalPS variable declaration:
    public ParticleSystem GoalPS
    {
      get
      {
        return goalPS;
      }
    
      set
      {
        goalPS = value;
      }
    }

    This will allow us to access this newly created GoalPS variable to modify goalPS (our original one). The value that you see in the set function is a keyword that will be assigned.

    Now, you may be asking why you should do this instead of making it public. There are two main reasons. First, we are allowed to use get and set just like a normal function. This will allow us to check the value of the variable before we actually assign something, which can be really useful if you want to make sure that a variable is within a certain range. Take a look at the following code:

    private int health;
    public int Health
    {
      get
      {
        return health;
      }
    
      set
      {
        // Value can only be up to 100
        health = value % 100;
        if(health <= 0)
        print ("I'm dead");
      }
    }

    Also, by omitting either set or get, we can say that the variable cannot be changed outside of the class or accessed outside of the class.

    For more information on properties, check out http://unity3d.com/learn/tutorials/modules/intermediate/scripting/properties.

    We will also no longer need the variables for our object references, so go ahead and remove the following lines in our GameController script:

        [Header("Object References")]
        public Transform wall;
        public Transform player;
        public Transform orb;
        public Transform goal;

    Now that our level is no longer being created in the GameController, let's add the functionality back to our LevelEditor. Perform the following steps:

  6. Add the following function:
    void BuildLevel()
    {
      
      //Go through each element inside our level variable
      for (int yPos = 0; yPos < level.Length; yPos++)
      {
        for (int xPos = 0; xPos < (level[yPos]).Length; xPos++)
        {
          CreateBlock(level[yPos][xPos], xPos, level.Length - yPos);
        }
      }
    }
  7. We haven't created the CreateBlock function, so right now, it'll show up as being red, but before we add it in, we need to create some variables:
    int xMin = 0;
    int xMax = 0;
    int yMin = 0;
    int yMax = 0;
    
    public List<Transform> tiles;
    
    GameObject dynamicParent;
  8. At this point, the List type will show up in red. This is because it doesn't know what we're talking about. Add the following line to our using statements up at the top of the file:
    using System.Collections.Generic; // Lists

Lists

We used arrays previously in this book, which are containers for multiple copies of an object. One of the problems with arrays is the fact that you have to know the size (or how many elements) of the array in advance, and you cannot add or subtract elements from the array.

The list type is basically a dynamically sized array, which is to say that we can add and remove elements from it at any point that we want. It also gives us access to some nice helper functions such as IndexOf (which will return to us the index of an element in a list, something that can be really useful when using the index operator []).

  1. Now we need to actually create our CreateBlock function, as follows:
    public void CreateBlock(int value, int xPos, int yPos)
    {
      Transform toCreate = null;
    
      // We need to know the size of our level to save later
      if(xPos < xMin)
      {
        xMin = xPos;
      }
      if(xPos > xMax)
      {
        xMax = xPos;
      }
      
      if(yPos < yMin)
      {
        yMin = yPos;
      }
      if(yPos > yMax)
      {
        yMax = yPos;
      }
    
      //If value is set to 0, we don't want to spawn anything
      if(value != 0)
      {
        toCreate = tiles[value-1];
      }
      
      if(toCreate != null)
      {
        //Create the object we want to create
        Transform newObject = Instantiate(toCreate, new Vector3(xPos, yPos,  0), Quaternion.identity) as Transform;
    
        //Give the new object the same name as ours
        newObject.name = toCreate.name;
    
        if(toCreate.name == "Goal")
        {
          // We want to have a reference to the particle system 
          // for later
          GameController._instance.GoalPS = newObject.gameObject.GetComponent<ParticleSystem>();
          
          // Move the particle system so it'll face up
          newObject.transform.Rotate(-90,0,0);
        }
        
        // Set the object's parent to the DynamicObjects
        // variable so it doesn't clutter our Hierarchy
        newObject.parent = dynamicParent.transform;
      }
    }
  2. Finally, we need to initialize all of these variables in our Start function, as follows:
    public void Start()
    {
      // Get the DynamicObjects object so we can make it our
      // newly created objects' parent
      dynamicParent = GameObject.Find("Dynamic Objects");
      BuildLevel();
      
      enabled = false;
    }

    Note

    As we used previously, the GameObject.Find function looks within our scene to find an object with the name Dynamic Objects. If it does not find the object, it will return null. It's always a good idea to make sure that the value is not null, or you may be wondering why something in your code doesn't work when it's a spelling error or something of that sort. It's important to note that case is important and that DynamicObjects and dynamicObjects are different! If anything is different, it will not work:

    if(dynamicParent == null)
    {
      print("Object not found! Check spelling!");
    }
    

    This function should be used only on seldom occasions, as it can be quite slow. For more information on GameObject.Find, check out http://docs.unity3d.com/ScriptReference/GameObject.Find.html.

    Next, go back to Inspector and attach the LevelEditor script to the GameController object by dragging the script file on top of it. Afterward, open up the Tiles variable and change Size to 4. Then, go to the Prefabs folder and drag Wall, Player, Collectible, and Goal to the Element 0, Element 1, Element 2, and Element 3 variables, respectively.

  3. Finally, save your scene and play the game! Take a look at the following screenshot:
    Lists

You'll note that now, the class creates our level and then turns itself off—a great start for our level editor!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset