Level editor – adding/removing walls at runtime

Now that our level editor will be able to load in this data, we now want to have a way to actually modify what we see onscreen. To do this, we'll need to create a GUI interface and functionality for our level editor.

  1. The first thing we need to do is add a variable to keep track of what item we want to spawn:
    // The object we are currently looking to spawn
    private Transform toCreate;
  2. Now, we need to initialize this variable inside our Start function:
    toCreate = tiles[0];
  3. Next, we need to update our Update function and then explain how it's working, as follows:
        void Update()
        {
            // Left click - Create object
            if (Input.GetMouseButton(0) && GUIUtility.hotControl == 0)
            {
                Vector3 mousePos = Input.mousePosition;
    
    /*
    Set the position in the z axis to the
    opposite of the camera's so that the position is on the world so ScreenToWorldPoint will give us valid
    values.
    */
                mousePos.z = Camera.main.transform.position.z * -1;
    
                Vector3 pos = Camera.main.ScreenToWorldPoint(mousePos);
    
                // Deal with the mouse being not exactly on a 
                // block
                int posX = Mathf.FloorToInt(pos.x + .5f);
                int posY = Mathf.FloorToInt(pos.y + .5f);
    
                Collider[] hitColliders = Physics.OverlapSphere(pos, 0.45f);
                int i = 0;
                while (i < hitColliders.Length)
                {
                    if (toCreate.name != hitColliders[i].gameObject.name)
                    {
                        DestroyImmediate(hitColliders[i].gameObject);
                    }
                    else
                    {
                        // Already exists, no need to create 
                        // another
                        return;
                    }
                    i++;
                }
    
                CreateBlock(tiles.IndexOf(toCreate) + 1, posX, posY);
                
            }
    
            // Right clicking - Delete object
            if (Input.GetMouseButton(1) && GUIUtility.hotControl == 0)
            {
                Ray ray = 
                Camera.main.ScreenPointToRay(Input.mousePosition);
    
                RaycastHit hit = new RaycastHit();
    
                Physics.Raycast(ray, out hit, 100);
    
                // If we hit something other than the player
                // we want to destroy it!
                if ((hit.collider != null) && (hit.collider.name != "Player"))
                {
                    Destroy(hit.collider.gameObject);
                }
            }
    
        }

    You'll note that we used something named hotControl when we were checking for input. The reason we did this was that whenever a player holds down a mouse button, it becomes "hot." No other controls are allowed to respond to mouse events while some control is "hot."

    Once the user releases their mouse, hotControl gets set to 0 to indicate that other controls can respond to user input, which will be useful when we implement our GUI system, as we don't want to draw something when we're clicking on our mouse button.

    Note

    For more information on GUIUtility.hotControl, check out http://docs.unity3d.com/ScriptReference/GUIUtility-hotControl.html.

    A lot of the stuff contained in this code is from reusing a lot of the aspects you learned earlier in the book, back when we did our platformer game. Yet, now we are using the same functions to work with the mouse position in the world and converting it to world space.

    We use the ScreenToWorldPoint function to convert our mouse position from screenspace into world space with the Z position of the point being the units away from the camera we want the position to be. Because our world is at 0, we want the Z to be negative whatever the camera's Z position is.

    Note

    For more information on ScreenToWorldPoint check out http://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html.

    We use this information to get the position we want to place the block at. Once we have this, we can just call Instantiate and create something, but we also need to make sure that we only have one object per tile, so we will use a raycast to determine if that area already has a block, and if it does, we will destroy it:

  4. Now that we have all this set, let's save the file and then exit back to the Unity editor and play the game.
  5. If you select the GameController object, you'll note that the checkbox next to the LevelEditor component is unchecked. This is because we disabled it in the Start function. We will enable it again in code later, but just for demonstration purposes, click on the checkbox to activate it once again. Then, in the Game tab, click on the screen and right-click on areas in the level. Take a look at the following screenshot:
    Level editor – adding/removing walls at runtime

You'll note that now we can draw walls anywhere within our scene and delete anything aside from our player!

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

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