Moongate Games UK

"Changing worlds, one line of code at a time"

Tutorial: Building an In game Level Editor. (Part #3)

Game Engine: Unity 5.1
Language: C#
Subject: In-game Level Editor

 In this part of the tutorial we'll be looking at adding, removing and replacing the objects in the level itself.

 The first thing we'll need to do in this part is create a new C# script called 'LevelManager' under the 'Level Editor' folder in 'Scripts'. As the name says this will be the Level Manager, it will handle all placing and removing of the objects and keep track of what is placed where. You will also need to go into the 'Entities' folder and create a new C# script called 'LevelPart'. This script will be used to store the data of each of the level parts placed in the level.

 So once that scripts has been created we'll need to open 'LevelManager' up and start by adding the following to the top of the script. (Since we'll be using a dictionary in this part.)

using System.Collections.Generic;

 Then we'll need to open up 'LevelPart' and remove the 'void Start()' and 'void Update()' methods from the script and then make it look like this. (EDIT: Removed the MonoDevelop bit. Thanks for the spot Igancio)

using UnityEngine;
using System.Collections;

namespace Entities{
    public class LevelPart {

    }
}

 Once we have done that we'll need to add a few variables to store the LevelPart and it's location.

public GameObject PartObject { get { return _partObject;}}
private GameObject _partObject;

public Vector3 PartLocation { get { return _partLocation;}}
private Vector3 _partLocation;

public string PartTag { get { return _partTag;}}
private string _partTag;

public bool IsSpawnPart { get { return _isSpawnPart;}}
private bool _isSpawnPart;

 This may look a little weird to some of you since it may look like I have duplicates of the variables, but this is what's known as Encapsulation (A quick search in google will give you all you need to know about it.).

 Next we'll need to add a constructor to the script, which is done by the following:

public LevelPart(GameObject part, Vector3 location,string partTag, bool isSpawnPart){
    _partObject = part;
    _partLocation = location;
    _partTag = partTag;
    _isSpawnPart = isSpawnPart;
}

 All of that together will basically hold the information on all the level parts within the level. For the moment the only parts we'll need to worry about are the PartObject, PartLocation and PartTag. The IsSpawnPart has been added ready for a future part of the tutorial.

 Next we'll need to go back into the 'LevelManager' script and add another using part.

using Entities;

 We then need to add a new variable to this script which will hold all the LevelPart objects within the level itself.

public List<LevelPart> PartsInLevel;

 Once you have added that you will need to add the following line of code to the 'void Start()' method.

PartsInLevel = new List<LevelPart>();

 Before you add anything else to the 'LevelManager' script you will need to delete the 'void Update()' method since we won't need it for the moment.

 Before we do anything else in the 'LevelManager' script we'll need to create a new script in the 'IO' folder called 'TagHelper' and replace the default code with the following :

using UnityEngine;
using UnityEditor;

public static class TagHelper
{
    public static void AddTag(string tag)
    {
        UnityEngine.Object[] asset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset");
        if ((asset != null) && (asset.Length > 0))
        {
            SerializedObject so = new SerializedObject(asset[0]);
            SerializedProperty tags = so.FindProperty("tags");
            
            for (int i = 0; i < tags.arraySize; ++i)
            {
                if (tags.GetArrayElementAtIndex(i).stringValue == tag)
                {
                    return;     // Tag already present, nothing to do.
                }
            }
            
            tags.InsertArrayElementAtIndex(0);
            tags.GetArrayElementAtIndex(0).stringValue = tag;
            so.ApplyModifiedProperties();
            so.Update();
        }
    }
}

 This code will enable us to add tags during runtime so that we can place and remove the level parts based on what tag they have.

 Next we'll need to add the following code to the 'LevelManager' for it to be able to add, remove and check level objects.

public void AddPart(GameObject part, Vector3 location, bool isSpawnPart){
    RemovePart (location);

    var newPart = PlaceObject (part,location);

    PartsInLevel.Add (newPart);
}

public void RemovePart(Vector3 location){
    var count = 0;
    LevelPart partToRemove = null;
    foreach(var part in PartsInLevel){
        if(part.PartLocation == location){
            RemoveObject (part.PartTag);
            partToRemove = part;
            continue;
        }
        count++;
    }
    
    if(partToRemove != null)
        PartsInLevel.Remove(partToRemove);
}

private LevelPart PlaceObject(GameObject part, Vector3 location){
        var newTag = GenerateGuid ();
        GameObject _levelPartClone = GameObject.Instantiate(part,location,part.transform.rotation) as GameObject;
        _levelPartClone.name = newTag;

        return new LevelPart(_levelPartClone,location,_levelPartClone.name,false);
}

private void RemoveObject(string partTag){
    var partToRemove = GameObject.Find(partTag);
    Destroy(partToRemove);
}

private string GenerateGuid(){
    return System.Guid.NewGuid().ToString();
}

 Once you have added that code to the 'LevelManager' you will need to go into the 'LE_Input' script and add a few little bits to the variables, the 'void Start()' method and the 'void Update()' method.

 Firstly you'll need to add another variable, like so:

private LevelManager _levelManager;

 Then you'll need to add the following line of code to the 'void Start()' method, like so:

_levelManager = GetComponent<LevelManager>();

 Finally you'll need to add the following lines of code to the 'void Update()' method, like so:

if(Input.GetButtonUp ("Jump")){
    _levelManager.AddPart (_partList.SelectedPart,_placementPosition,false);
}

 Once all that is done you'll need to add the 'LevelManager' script to the 'scriptHolder' Game Object and then you should have something that is able to add and replace already placed objects

 The final thing that we'll need to do for this part of the Level Editor tutorial is to code in the ability to remove objects without adding a new one. To do this we only have to add the following lines of code.

if(Input.GetButtonUp ("Fire3")){
    _levelManager.RemovePart (_placementPosition);
}

 There you have it, you can now add, replace and remove objects within the Level Editor itself. You should be able to do something similar to the video below. If you make sure 'Maximize on Play' is turned off you will be able to see that when you add an object the names themselves are guid's.

This is what you should get by the time you have done this part of the In Game Level Editor Tutorial.

<-- Part 2 | Part 4 -->