The prefab creation

In order to create a prefab, you must first have a collection of GameObjects that you want to keep together as one prefab.

Perform the following steps:

  1. Navigate to the Assets folder. Right-click on it and select Create and then Folder. Name this Prefabs.
  2. Select the Axe GameObject in Hierarchy. This is the one we created in the last chapter. Click on it and drag it onto the Prefabs folder.

This will create an Axe prefab that we can use in the future that holds everything the current Axe GameObject does.

The prefab creation

Anytime in the future, when we want to create an axe, we will have a complete file that holds everything we know as axe.

This is essentially all it takes to create prefabs. These are an incredibly simple and useful aspect of creating games with Unity.

Coin prefabs

Let's create a couple of different varieties of coins, so when we use them in our level, we will have a more efficient system. Perform the following steps:

  1. Start by creating a new empty GameObject in the Hierarchy tab and name it CoinPattern_00.
  2. Set the location of this CoinPattern_00 GameObject to 0X, 0Y, and 0Z in the world.

    Now, move the existing coin in the scene. Name it Pickup_Coin_0 so that it becomes a child of the CoinPattern_00 GameObject. Center this coin to 0X, 0Y, and 0Z. This location is referenced by its parent, so it is a local position and not a world one. The CoinPattern_00 GameObject has the world location and the Coin child is relative to its position.

  3. Select the Coin child and click on Ctrl + D to duplicate it. Do this a few times and lay out the coins in an arch, as shown in the following screenshot:
    Coin prefabs
  4. With the CoinPattern_00 GameObject selected, click on it and drag it onto the Assets/Prefabs folder.

Once the prefab is created for CoinPattern_00, you can drag a prefab onto the scene and see the power of prefabs. As the prefab stores all the references you created, when they are put into the scene, the prefab is exactly the same as the CoinPattern_00 GameObject, which we created earlier.

Follow the same steps to create a couple of different CoinPattern GameObjects and make sure to create prefabs for all of them. I made three CoinPattern GameObjects and turned them into a prefab.

Tip

If you want to alter a prefab, enter it in the scene and make your changes. When you are done with your changes, click on the parent GameObject and then drag it onto the existing prefab you want to edit. There is also an option in the Inspector window that says Apply. If you click on this, the prefab will be updated to the current settings in the Scene window.

Level piece prefabs

The last step of our prefab setup is to create the level pieces. These will be the pieces we put together with some code to create a "random" level. As the level pieces will be moving under the player, simulating the player moving, we will have to move these level prefab pieces around in the world and introduce coin and obstacles around them, so the player has a somewhat different experience as the game is running.

To start with, use our Sprite Tiler tool to create some tiled GameObjects. I suggest adding some slopes by taking the floor sprites, duplicating them and then rotating them. Here is an example:

Level piece prefabs

This is a grid GameObject created with the Sprite Tiler tool with an additional row copied to the top and a couple more single grid objects duplicated and rotated. Use your imagination and create at least three of these. When you create these, make sure to keep the Y grid amount the same for the beginning and ending of all pieces. I will use five for a Y setting, as seen in the preceding image.

When you are done, take each of the root GameObjects that were created and create prefabs for each of them. Remember to make them unique prefabs with single root GameObjects because we will use each grid individually.

In addition, we will need a starting level piece. This will be the level piece that always starts the game. It will give the player a longer amount of time to get situated with the game and will give us a starting point to begin moving and attaching the other level pieces together. Perform the following steps:

  1. Open the Sprite Tiler tool and name the Tile Level Object Name as StartingLevelPiece.
  2. Then, select X as 3.
  3. Now, select Y as 5.
  4. For the Sprite Ground File, use Floor_03.
  5. Then, for the Sprite Dirt File, use Floor_02.
  6. Click on Create Tiled.
  7. Finally, left-click and drag the resulting StartingLevelPiece GameObject onto the Assets/Prefabs folder to create its prefab.

Further setup of the level pieces

At this point, you should have a collection of CoinPattern, LevelPieces, and Axe GameObject(s) prefabs in the Prefabs folder. This is the list I have:

Further setup of the level pieces

The level pieces will need two extra GameObjects so that we know where they all begin and end. This way, we will be able to place them together by putting the beginning of the next piece at the end of the previous one.

Make sure that any of the level pieces in the Hierarchy tab are saved as a prefab and delete them from the Hierarchy tab. When the scene is clear of level pieces, take StartingLevelPiece and put it in the scene with the following steps:

  1. Select StartingLevelPiece and position its location at 0, 0, and 0 in the world with the Inspector window under Transform.
  2. Open the StartingLevelPiece GameObject in Hierarchy by clicking on the small gray arrow on the left-hand side.
  3. Select the children GameObjects and then position them so that the pivot of the LevelPiece parent GameObject is at the bottom-left of the selected children, as shown in the following image:
    Further setup of the level pieces
  4. Right-click on Hierarchy, select Create Empty, and name it EndLocation.
  5. Now, move the EndLocation GameObject in the bottom-right corner of StartingLevelPiece.
  6. Take the EndLocation GameObjects and drag it onto the StartingLevelPiece GameObject so that it becomes its child.
  7. Select the StartingLevelPiece GameObject and then click and drag it onto the existing prefab in the Assets/Prefabs folder. This will overwrite the current version of the prefab with the updated one.
  8. If you click and drag the StartingLevelPiece prefab from the Assets/Prefabs folder and place it on the Scene window, you should see EndLocation as a child of it in Hierarchy and positioned in the bottom-right corner of the sprite children, as shown in the following image:
    Further setup of the level pieces

Tip

When you place the pivot point and EndLocation, it is okay to have a few pixels of the sprites overlap; I even recommend it. If these locations are outside the pixels of the sprites, there will be small gaps when the pieces are put together, which isn't a huge deal, although noticeable.

This will give us a position we know as the root object position, which when we change it in code will move the rest of the children in a way we can rely on. The EndLocation GameObject also gives us a reliable position to connect another LevelPiece to it without needing to have any offsets.

Repeat these steps for the rest of the LevelPiece GameObjects. Make sure that the root GameObject is placed in the bottom-left corner of the GameObject, and the EndLocation is placed in the bottom-right corner of the GameObject.

The level piece code

In order to keep track of all the LevelPieces, we need a small script that stores their initial location. Right-click on the Assets/Scripts folder and select Create. Then, click on C# Script and name it LevelPiece.

Double-click on the LevelPiece file to open it and make sure that it looks similar to the following code:

using UnityEngine;
using System.Collections;

public class LevelPiece : MonoBehaviour 
{
  // The initial location of this level piece
  private Vector3 InitialLocation;

  // Use this for initialization
  void Awake () 
  {
    InitialLocation = transform.position;
  }

  // Get the initial location of this
  // LevelPiece
  public Vector3 GetInitialLocation()
  {
    return InitialLocation;
  }
}

This is a very simple class that is designed to keep track of where the LevelPiece starts. This will be used to reset the LevelPiece after it has been used so that it can be used again.

InitialLocation is a Vector3 struct that gets assigned during the Start function. Awake is called as soon as the class is initialized or as soon as the game starts running because the class will exist on the LevelPieces, which will be in the world when the game starts.

We don't need the Update function, which is why it was removed from the class.

GetInitialLocation is a function that we can use from the next C# class that we will write so that it can manage the LevelPiece GameObject(s) by getting that location and moving the LevelPiece to it after we have used it.

Tip

The difference between Awake and Start is that Awake gets called before the Update or Start function is called. Then, Start gets called following Awake, but still before the first Update call. This means the order of functions getting called when the class is created is Awake->Start->Update. As the next class we will use will immediately start its Update function, we need to make sure that InitialLocation of LevelPiece is assigned before its location gets moved.

The level piece manager code

We now have everything we need to begin piecing the LevelPieces together with code.

Perform the following steps:

  1. Right-click on the Assets/Scripts folder and select Create. Then, select C# Script. Name it LevelPieceManager.
  2. In order to know when we need to attach another level piece, we must first have a Vector3 position to check against. In Hierarchy, right-click and select Create Empty. Name this LevelPieceManager.
  3. Now, select the X location as LevelPieceManager and the Inspector | Transform window as -7.75. This will offset LevelPieceManager so that when the game starts, the character will have a longer flat path to run along before reaching the first attached LevelPiece.
  4. Then, select LevelPieceManager, and in Inspector, click on Add Component. Search for LevelPieceManager and select LevelPieceManager.
  5. Finally, double-click on the LevelPieceManager script file in the Assets/Scripts folder, open it, and add the following code to it:
    using UnityEngine;
    using System.Collections;
    
    public class LevelPieceManager : MonoBehaviour
    {
      // Starting level piece 
      public LevelPiece StartingLevelPiece;
    
      // Level pieces to rotate 
      public LevelPiece[] LevelPieces;
    
      // How quickly the level pieces move
      public float LevelPiecesMoveRate;
    
      // The currently active Level Piece
      private LevelPiece[] ActiveLevelPieces;
    
      // Use this for initialization
      void Start()
      {
      }
    
      // Update is called once per frame
      void Update()
      {
      }
    }

LevelPieceManager is a class that will connect all the LevelPieces together and move them across the screen, simulating that the player is running forward. This is a design decision on my end. Although Unity does have what you can call a "scene size limit", my decision here is to try to keep the organization of the scene to a smaller area, hopefully giving you a more relaxed scene to work in.

The current code is explained here:

  • StartingLevelPiece: This is the initial LevelPiece GameObject. It is a flat portion to get the game started without having to worry about placing anything as soon as the game starts.
  • LevelPieces: This is an array that will hold the other LevelPiece prefabs we created. It is the list that will be used to assign a new piece to the actively moving pieces when another piece has reached a point where it is no longer needed, that is, when it is out of view of the player.
  • LevelPiecesMoveRate: This is the speed at which the LevelPiece GameObjects will be moving across the screen.
  • ActiveLevelPieces: This is a list of LevelPiece GameObjects that will move across the screen. It is set to private to prevent any other class from accessing and/or changing it.

Next, we want to add the code for the Start function. Add the following code to the LevelPieceManager class:

  // Use this for initialization
  void Start( ) 
  {
    ActiveLevelPieces = new LevelPiece[2];
    ActiveLevelPieces[0] = StartingLevelPiece;
    ActiveLevelPieces[1] = GetRandomLevelPiece();

    ActiveLevelPieces[1].transform.position = StartingLevelPiece.gameObject.transform.FindChild("EndLocation").position;
  }

The Start function is called as soon as this class is active in the scene, just after Awake and just before Update, giving us room to assign some values before anything else happens in this class.

To begin with, we will create an array of two LevelPiece classes and assign it to ActiveLevelPieces.

Then, we will give the first element in the ActiveLevelPiece array the value of StartingLevelPiece because it is the first LevelPiece we want to use.

We will then get a "random" LevelPiece from the GetRandomLevelPiece function, which we will write soon; it is going to cycle through the array of LevelPieces from the scene. Make sure that the one we want to use isn't currently active.

After we have the random LevelPiece, we have to assign its location to the EndLocation of the StartingLevelPiece. This is done by using the transform.FindChild function. This function will look for the name of the Transform child, which in our case is EndLocation. When we have this, we can use the transform position of EndLocation and assign the random LevelPiece position to it.

Earlier, I mentioned why the LevelPiece class uses Awake instead of Start. In the case of LevelPieceManager, we want to make sure that the LevelPiece class is done with all its assignments before LevelPieceManager begins to do anything, which will happen because the Awake function of LevelPiece will be called before the Start function of LevelPieceManager, giving us the order of LevelPiece Awake, LevelPieceManager Start, LevelPieceManager Update.

Next, we want to write the Update function for LevelPieceManager. Add the following code:

  // Update is called once per frame
  void Update ( )
  {
    for (int i = 0; i < ActiveLevelPieces.Length; i++)
    {
      Vector3 newLocation = ActiveLevelPieces[ i ].transform.position;
      newLocation.x -= LevelPiecesMoveRate * Time.deltaTime;

      ActiveLevelPieces[ i ].transform.position = newLocation;

      if (ActiveLevelPieces[ i ].transform.position.x < transform.position.x)
      {
        if (ActiveLevelPieces[ i ] == StartingLevelPiece)
        {
          ActiveLevelPieces[ i ].gameObject.SetActive( false );
        }

        ActiveLevelPieces[ i ].transform.position = ActiveLevelPieces[ i ].GetInitialLocation( );
        ActiveLevelPieces[ i ] = GetRandomLevelPiece( );
        ActiveLevelPieces[ i ].transform.position = FindOtherLevelPiece( ActiveLevelPieces[ i ] ).gameObject.transform.FindChild( "EndLocation" ).position;
      }
    }
  }

As mentioned before, the Update function is called for every frame that is rendered. This means that if your game is running at thirty frames per second, the Update function gets called thirty times a second as well.

As we will always have two ActiveLevelPieces and want them to move together, we will use a for loop that will loop through these ActiveLevelPieces, which if you recall is two.

For each one of these ActiveLevelPieces, we first want to get their location, which we named newLocation.

We then want to change the location.x value of this newLocation by LevelPieceMoveRate multiplied by the Time.deltaTime value, which is the time it took to render the last frame to this frame.

When we have newLocation assigned, we then want to update the location of the current ActiveLevelPiece element to the newLocation Vector3 value, which will move the ActiveLevelPiece element.

We then want to check whether the ActiveLevelPiece element has passed the bounds of the LevelPieceManager GameObject position.x value. If it has, we check whether the ActiveLevelPiece element is StartingLevelPiece. If it is, we know that we don't want to use it again, so we will use the SetActive function to hide it by saying that it is not active anymore.

As the ActiveLevelPiece element has reached the point where it no longer needs to be used, we will reset its location to its InitialLocation with the GetInitialLocation function written in the LevelPiece class.

After it has been reset, we will use the GetRandomLevelPiece function so that we can begin to use an available LevelPiece. As mentioned before, this function returns a LevelPiece that is currently not being used.

After we have our next LevelPiece, we then want to set its location to the EndLocation of the other ActiveLevelPiece, which is done with a function named FindOtherLevelPiece, in which we pass the current ActiveLevelPiece to compare against the rest of them, making sure that we don't accidentally return the ActiveLevelPiece that needs replacement.

Let's simplify what is going on here. We are taking a location of GameObject and offsetting it a small amount and then assigning the GameObject position to the new offset location. If this offset location is outside the bounds of what we have set, we can replace it with a new GameObject that begins the cycle all over again.

Next, we need the FindOtherLevelPiece function. Add the following function under Update:

    // Get the other LevelPiece
    // from the LevelPieces
    // Array
    private LevelPiece FindOtherLevelPiece(LevelPiece CurrentLevelPiece)
    {
      for (int i = 0; i < ActiveLevelPieces.Length; i++)
      {
        if (ActiveLevelPieces[ i ] != CurrentLevelPiece)
        {
          return ActiveLevelPieces[ i ];
        }
      }
      return null;
    }

This function is simple. We check the value of CurrentLevelPiece against the array elements of ActiveLevelPieces. As soon as we find that the ActiveLevelPieces array element is not equal to CurrentLevelPiece, we will return it. This means that we found the other ActiveLevelPieces array element (as there are only two). Also, it doesn't match the CurrentLevelPiece argument.

Next, we need to write the GetRandomLevelPiece function. Add the following function under FindOtherLevelPiece:

    // Get random level piece
    // from LevelPieces Array
    private LevelPiece GetRandomLevelPiece()
    {
      LevelPiece returnPiece = null;
      while (returnPiece == null)
      {
        for (int i = 0; i < LevelPieces.Length; i++)
        {
          if ( !isActivePiece( LevelPieces[ i ] ) )
          {
            returnPiece = LevelPieces[ i ];
          }
        }
      }
      return returnPiece;
    }

As mentioned before, the while loop will continue to loop until the condition is no longer true. In our case, we want to make sure that the loop stops when returnPiece has a value or is not equal to null.

For this, let's first create a for loop that loops through LevelPieces. These are the LevelPiece prefab GameObjects in our scene. We then check whether the LevelPieces array element is not active by passing it to a function called isActivePiece and then checking whether this function returns false.

When we have the LevelPieces array element that is not being used, we can assign its returnPiece to that LevelPieces array element. Once this is done, the while loop condition will become false and then the next line after the while loop returns the returnPiece found.

Simply put, we will look at all the LevelPieces and return the first one that is not being used.

The last function we need to write is the isAlreadyActive function. This will return true if the piece is active and false if it is not active. Under the GetRandomLevelPiece function, add the isActivePiece function:

    // Check if LevelPiece
    // is already used.
    private bool isActivePiece(LevelPiece Piece)
    {
      for (int i = 0; i < ActiveLevelPieces.Length; i++)
      {
        if (Piece == ActiveLevelPieces[ i ])
        {
          return true;
        }
      }
      return false;
    }

Similar to the FindOtherLevelPiece function, we loop through the ActiveLevelPieces array and check whether the Piece argument is passed. If any of the ActiveLevelPieces array elements match the Piece argument being passed, the function will return true because the condition is true. If the function loops through the entire ActiveLevelPieces array and the Piece argument doesn't match any of them, the function will return false because the condition in the for loop was never true.

This is the LevelPieceManager class. If you save and open/tab back over to Unity and then compile, you can set up the LevelPieceManager settings.

Setting up the LevelPieceManager GameObject

If not already created, right-click on the Hierarchy tab and select Create Empty. Rename this GameObject as LevelPieceManager.

With the LevelPieceManager GameObject selected, click on Add Component in the Inspector window.

Search for LevelPieceManager and select LevelPieceManager to add the component.

With the LevelPieceManager GameObject still selected, change its X position to -7.75 using the Inspector | Transform window. The Y and Z locations don't matter, although you can set them both to zero if you want to keep things organized.

Perform the following steps:

  1. Take each of the LevelPiece prefabs and drag them onto the scene outside the view of the camera, except for StartingLevelPiece. Move the StartingLevelPiece position to 0X, 0Y, and 0Z by selecting it from Hierarchy and using the Inspector | Transform settings.
  2. Select the LevelPieceManager GameObject from Hierarchy.
  3. Then, left-click and drag StartingLevelPiece from Hierarchy onto the Starting Level Piece slot in the LevelPieceManager GameObject.
  4. Now, change the Level Pieces array amount from zero to three.
  5. Then, take each of the LevelPiece prefab GameObjects, not including StartingLevelPiece, and put each of them in a slot of the LevelPieces of the LevelPieceManager GameObject.
  6. Finally, change Level Piece Move Rate from 0 to 1.35:
    Setting up the LevelPieceManager GameObject

If you play the game now, you should see LevelPieces moving and connecting to each other, simulating that the player character is moving. You will also see that at times, the player character is getting pushed backwards by the slope of LevelPieces. To fix this, open the Character script from the Assets/Scripts folder.

In the Update function, before the condition that checks isFadeOut, add the following code:

    // Update is called once per frame
    void Update () 
    {
      Vector3 lockXPosition = transform.position;
      lockXPosition.x = 2.25f;
      transform.position = lockXPosition;

      if (isFadeOut)
      {

If you play the game now, you will see that the character is locked in the X position of 2.5, meaning that the slopes won't affect it anymore.

Adding coins and obstacles to LevelPieces

The next step is to add coins and obstacles to our LevelPiece prefabs. As our LevelPieceManager can handle more than three LevelPiece prefabs, you can create duplicates to have different coin and obstacle layouts. Alternatively, you can keep it simple and only use the current three LevelPiece prefabs.

Drag and drop the Coin and Obstacle prefabs onto the scene and position them around the LevelPiece prefabs. For each of the LevelPiece prefabs, create as many obstacles or coins as you want, and after they are placed, make sure to drag them onto the LevelPiece GameObject, making the obstacles and coins children of LevelPiece. When you are done, you should have something similar to the following screenshot:

Adding coins and obstacles to LevelPieces

If your Axe obstacle is rendering behind LevelPiece, left-click on the 2D button at the top of the Scene window.

You can use the following controls to navigate the scene:

  • Alt + left click: This control can be used to rotate around the center of the scene
  • Alt + middle mouse down: This control can be used to move the camera around
  • Middle mouse wheel forward: This control can be used to zoom in the camera
  • Middle mouse wheel backward: This control can be used to zoom out the camera
  • F: With the selected GameObject, the camera positions itself in front of the selected GameObject

Select the Axe GameObject that needs to be moved and use the move gizmo to move it in front of LevelPiece, as shown in the following screenshot:

Adding coins and obstacles to LevelPieces

Tip

The Z position of GameObjects does not affect the game. You can position them in any order to make them render correctly in the scene. You can move anything forward or backward to make the sprites look correct.

Managing coins and obstacles with the LevelPiece code

In the Assets/Scripts folder, double-click on the LevelPiece.cs file to open it. Add the following code at the top of the class:

    // Coin children
    public Coin[] Coins;

Save the LevelPiece.cs file and tab back or open Unity to let the code compile. Start by selecting one of the LevelPiece GameObjects in Hierarchy, and in the top-right corner of the Inspector window, click on the small lock; it should change from an open lock to a closed lock. Once it has, you can select all the coins from Hierarchy for the specific LevelPiece GameObject and drag them onto the LevelPiece component in the Inspector window; it will automatically fill and assign the Coins array, as shown in the following screenshot:

Managing coins and obstacles with the LevelPiece code

Do this for all the coins in all the LevelPiece GameObjects. Also, make sure to match them to the correct Coins array. Remember that the lock will keep the LevelPiece GameObject selected until you unlock it by clicking on the lock again. You will have to do this for each LevelPiece.

Resetting coins

In the Assets/Scripts folder, open the Coin.cs class. We will change how the coin is being used here. Earlier, we were destroying it after the player collided with it. We do not want this now because this was only useful for testing purposes. We now want the coin to be in the scene always and managed in a way where it can be reactivated when LevelPiece becomes active.

In the OnTriggerEnter2D function, remove the following line:

Destroy( gameObject );

Then, replace it with the following code:

ActivateCoin( false );

Now, we need to write the ActivateCoin function. Add the following code under OntriggerEnter2D:

    // Activates or deactivates
    // coin
    public void ActivateCoin(bool bActivate)
    {
      SpriteRenderer renderer;
      BoxCollider2D collider;

      renderer = gameObject.GetComponent<SpriteRenderer>( );
      collider = gameObject.GetComponent<BoxCollider2D>( );

      collider.enabled = bActivate;
      renderer.enabled = bActivate;
    }

We first have the SpriteRenderer and Box Collider 2D components for the coin and then set them to the value of bActivate. This means that if the character collects the coin, the bActivate value will be false. This is because we don't want it activated after being collected, which will set enabled to false for both the collider and the renderer. Whereas, if we reset the game, we can call this same function but set bActivate to true. This will turn enabled to true for both the collider and renderer, making it so that the character can collect it again.

Furthermore, this function allows you to control the coin after it has been used so that it can be used again by setting the Box Collider 2D and SpriteRenderer components to enabled or not enabled. By setting these two components to not enabled, they won't react to the player character anymore, but if we set them to enabled, the player can again interact with them. This is good for us because we need to enable them every time LevelPiece gets used, although it has been used before.

Save this Coin.cs file.

Resetting the coin in LevelPiece

In the Assets/Scripts folder, open the LevelPiece class. At the bottom of the class, add the following function:

    // Resets all children
    // coins
    public void ResetAllChildrenCoins()
    {
      for (int i = 0; i < Coins.Length; i++)
      {
        Coins[ i ].ActivateCoin( true );
      }
    }

This does exactly as the function describes. It loops through all the coins that we added from the Hierarchy tab to the LevelPiece script component and calls the ActivateCoin function we wrote early, setting the enabled bool value to true. This is what we will pass in ActivateCoin.

Then, we need to call the ResetAllChildrenCoins function from LevelPieceManager, when it decides that it needs a new LevelPiece. In the Assets/Scripts folder, open the LevelPieceManager code file.

Change the Update function as follows:

  // Update is called once per frame
  void Update ( )
  {
    for (int i = 0; i < ActiveLevelPieces.Length; i++)
    {
      Vector3 newLocation = ActiveLevelPieces[ i ].transform.position;
      newLocation.x -= LevelPiecesMoveRate * Time.deltaTime;

      ActiveLevelPieces[ i ].transform.position = newLocation;

      if (ActiveLevelPieces[ i ].transform.position.x < transform.position.x)
      {
        if (ActiveLevelPieces[ i ] == StartingLevelPiece)
        {
          ActiveLevelPieces[ i ].gameObject.SetActive( false );
        }

        ActiveLevelPieces[ i ].transform.position = ActiveLevelPieces[ i ].GetInitialLocation( );
        ActiveLevelPieces[ i ] = GetRandomLevelPiece( );
        ActiveLevelPieces[ i ].transform.position = FindOtherLevelPiece( ActiveLevelPieces[ i ] ).gameObject.transform.FindChild( "EndLocation" ).position;
        ActiveLevelPieces[ i ].ResetAllChildrenCoins( );
      }
    }
  }

The only change here is the last line. When we have a new ActiveLevelPiece and when we update its location, we call ResetAllChildrenCoins for the ActiveLevelPiece so that the ActiveLevelPiece is fully playable again as all the coins are back to being able to be collected.

Save the LevelPieceManager.cs file and go back to Unity. After the code has compiled, you should see your entire gameplay going, including all the LevelPieces moving, connecting, and resetting.

Tip

Make sure to save all of your Unity files and the scene.

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

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