Mission One - Find the Facts - Creating E-Learning Games with Unity (2014)

Creating E-Learning Games with Unity (2014)

Chapter 3. Mission One - Find the Facts

Recall that in the first two chapters, we developed the core technology for a camera, player controls, interactive objects, and a mission-tracking system. Now it's time to apply our technology and make our first learning objective. Our e-learning game will educate the user on the 50 American states, the state flags, and some state trivia. In this chapter, we will assemble the systems we have created thus far and develop our first playable game level—the first of three in our final game.

In this chapter, we will cover the following topics:

· Introducing mission one: find the facts

· Designing games to maximize fun

· Implementing the core classes for mission one

· Playing the level

Finding the facts

In this game, the hero (player) plays the park ranger in charge of cleaning up Confederation National Park. In mission one, the park ranger has to find the missing flags for the flag monument and return them to their holders. The user will have to find five of 50 US flags. They will be placed at random locations in the world. The user will have to collect them, read about the associated states' trivia, and then bring the flags back once all the five flags have been found. The game comprises the following components:

· FlagLocators: This GameObject hierarchy contains a set of potential flag locations. From these 10 potential locations, five will be randomly chosen.

· Terrain: We introduce the terrain editor in this chapter and create a terrain mesh to replace the ground plane from Chapter 2, Interactive Objects and MissionMgr. As our design requires us to have a park-like setting for our game, the terrain editor is the best candidate for building this in the editor quickly and easily; the alternative is modelling the park in a 3D modelling program such as Maya and then exporting and importing into Unity. By adding grass, mountains, and trees we create a picturesque park that will serve as the backdrop and scene for our first game environment.

· Monument: This GameObject hierarchy contains a set of five flagmount locations. These are the places where the flags will be attached once the user finds the missing flags and returns them.

· MissionMgrHelper: This helper class allows a GameObject to manipulate the state of an already-existing mission. This is done by associating the script with a Prefab and then instantiating after a user interaction.

· SetupMissionOne: To accomplish the objectives of the level, this class installs two missions in the MissionMgr class that we developed in the previous chapter and also picks the random flags and flag locations for those missions.

· TriviaCardScript: This class displays a full screen texture on screen that represents a trivia card for a state. The script adjusts the size and layout of the texture and displays it centered on screen. These cards will appear when the flags are first picked up and when they are selected in the inventory.

· MonumentMgr: The gameplay objective of this level is to locate flags and return them to a monument with a number of empty mounting points. This class provides an interface for the monument hierarchy to attach an object (a returned flag) to one of the monument's flagmount points.

· SimpleDetachScript: This class detaches the GameObject that it is attached to, from any parent transforms, thereby making its parent the global coordinates. This is necessary for packaging GUITextures in a Prefab for instancing and then previewing.

The first two collections will be referenced by SetupMissionOne, which picks the flag locations, picks five Prefabs, and instances them. A number of Prefabs will need to be created as well to facilitate the flow logic across missions. Finally, some systems from Chapter 1, Introduction to E-Learning and the Three Cs of 3D Games, and Chapter 2, Interactive Objects and MissionMgr, will be updated to improve the gameplay.

Designing games to maximize fun

Prior to designing the first playable level in the game, an understanding of how to model fun in games is required. Have you ever been involved in an activity and lost track of time, such as playing a game or otherwise? Cognitive psychologists call this mental stateflow, and it is thought to be one way of maximizing fun. This is desirable because when the user is most engaged and having fun, learning and retention of information is maximized.

Game designers are interested in how we can design games that maximize the likelihood of the user entering this mental state.

Designing games to maximize fun

It turns out that we have a model for how to entice the user to achieve flow. Consider the previous diagram that illustrates the relationship between the difficulty and the skill required for a given task. This is when the activity is moderately challenging and under moderate pressure. If the activity is too hard or too easy, or if the situation is too boring or too stressful, it reduces the likelihood of maximizing fun via the flow model.

The teaching loop in game design

There are three stages of teaching in games described as follows:

· Presentation: In this stage, factual information is presented to the user. In a gaming situation, the user participates in engaging game mechanics to discover or interact with the objective material to be learned. The game mechanics provide incentives and challenges to encourage the player to enter flow.

· Application: In this stage, the user participates in game mechanics while employing the facts from stage one. The game mechanics reinforce good behavior as well as recall and mastery of the material from stage one. The game also reduces negative behavior—failure to recall and master the material from stage one.

· Synthesis: In this stage, through interactions with novel game scenarios, the user has to apply the mastered knowledge to new situations. By doing this, mastery and consolidation is further heightened, and a higher level understanding and insight is achieved in the subject matter.

Implementing the core classes for mission one

In this chapter, we will start creating mission one, which presents US geography to the player (state name, flag, and trivia). Let's begin by creating the classes and GameObject instances for this level. To begin, create a new scene file and name it TESTBED.

Creating a terrain

Let's create a nice terrain mesh to replace the ground plane from the previous two levels. With this, we can create a nice-looking mesh for the ground that resembles a park with grass, mountains, and trees by performing the following steps:

1. In the Assets menu, navigate to Import Package | Terrain Assets. Click on the Import button on the pop-up window that appears next to bring a library of models and textures into Unity for use with the terrain editor.

2. To create a terrain mesh, let's navigate to CreateOther | Terrain, from the GameObject drop-down list.

3. On the Set Heightmap resolution pop up that appears, configure the parameters to the following values:

· Terrain Width, Terrain Length: The horizontal dimensions of the terrain mesh. Set both to 500 units.

· Terrain Height: The maximum height of the terrain (for mountains and so on). Set this to 500 units.

· The remaining parameters control the resolution of the textures that are painted onto the terrain. Keep these at their defaults.

Creating a terrain

4. Click on the new terrain GameObject in the Hierarchy view, set its position to -250, 0, -250. This will place the terrain in the 3D world at a convenient location that results in the middle of the terrain at the world origin, which is convenient for development.

5. Clicking on the new terrain, observe the seven unique radio buttons on the terrain component in the inspector tab as shown in the following screenshot:

Creating a terrain

6. The first one from left-hand side will raise or lower terrain depending on if Shift or Ctrl are held down while clicking and moving the mouse. Zoom out in the scene view; select one of the many interesting brushes; and try creating some mountains. Note the effect that brush size and opacity has on the deformations to the terrain.

7. The second button allows you to paint to a certain height. This is good for fine control of elevation in a terrain mesh if you want to build very specific configurations of plateaus.

8. The third button is the smooth height button. Use this if you have previously painted some elevations with a brush that has lots of bumps and jagged edges. This brush will average and round out the selected peaks.

9. The fourth button is the paint textures button. If you navigate to Edit Textures | Add Texture, you can select a texture from any of the imported textures in the project thus far. Click on the texture viewer panel (rather than the normal map panel) to see a dialog box of all available options. After selecting and confirming, you will see your selection as an option back in the terrain previewer. Now, with your favorite brush selected, you can paint the texture onto your terrain. Add a variety of textures to paint grass, roads, and mountain details into your terrain.

10. The next button lets you paint tree models into your scene. Select a tree model from the edit trees button, and once you have confirmed a selection, choose a brush and density to paint the models with. A low-density circle can be used to add foliage to the tops of your mountain ranges. If you find that your game suddenly runs slowly after painting trees, it likely means you have too many tree models on screen. The fix for this is to reduce the density of the trees.

11. The second from the right-hand side button lets you paint the details into your scene. The workflow is similar to painting trees, and they behave similarly as well although this is intended for small details such as grass.

12. The right-most button lets you control the parameters of your terrain component. Things such as wind-speed, draw distances, and grass color let you fine-tune the look of your park.

Once you have finished making your park, it should look somewhat like the following screenshot:

Creating a terrain

Creating the FlagLocators GameObject

Let's create the hierarchy for FlagLocators in the scene as follows:

1. Create 10 Cube GameObjects. Place them in a variety of interesting places, well spaced out in the level. Put some of them on the ground, some in the hills, some on the mountains, and so on. Name these FlagLocator1 to FlagLocator10.

2. Disable all of the mesh renderers to make these objects invisible in the rendered scene. We will leave these components attached for debugging, but we don't want to draw them normally. Should we want to see where these locators are later on, we just need to enable the renderers to show the geometry.

3. Create another empty GameObject, and name it FlagLocators. Drag-and-drop all of the locators from step one underneath this object.

Congratulations! We now have a data collection of potential places for flags to spawn in mission one. We will select five of these in the SetupMissionOne script discussed in the following section.

Creating the FlagMonument GameObject

Let's build the geometric structure that will be the focal point of the first mission—the monument that needs the flags returned by performing the following steps:

1. Create a new Cube GameObject. Scale it so that it is a long and narrow rectangle on the ground in a central place. Name this monument.

2. Create five short Cylinder GameObjects. Name them FlagMount1 to FlagMount5, and parent them to the monument so that they are on top of the monument.

3. This should look very similar to the FlagLocators in the Hierarchy pane seen previously, but we will also create a MonumentMgr class and extend its functionality.

Creating the MonumentMgr Script

This script provides the API for the inventory to attach items to the flag mounts at the conclusion of the level.

The InventoryMgr script that we will write in this chapter, will use the methods provided in the MonumentMgr script to do this work by performing the following steps:

1. Create a new script, and name it MonumentMgr.cs. Attach an instance of it to the monument GameObject.

2. Inside the script, add public List<GameObject> to store the mount points as shown in the following code. Don't forget to add using System.Collections.Generic to the top of the file so that we can declare list properties. Failure to add this line of code will result in compile time errors in your script:

public List<GameObject> mountPoints;

3. Drag-and-drop the individual flag mount points from the monument to this list.

4. We add an attachObjToMountPoint(GameObject obj, int index) public method as shown in the following code. We first create an instance or clone of the object passed in, attach the object to the given mountpoint, and then zero its local translation and rotation. Doing this forces the object to have the same position and angle as mountpoint it is attached to, specifically a zero position and rotation offset relative to mountpoint. But remember, order is the key here!

5. public void attachObjToMountPoint(GameObject go, int index)

6. {

7. GameObject newGo = (GameObject)Instantiate (go,

8. mountPoints[index].transform.position,

9. mountPoints[index].transform.rotation);

10. newGo.SetActive(true);

11. newGo.transform.parent = mountPoints[index].transform;

12. newGo.transform.localPosition = Vector3.zero;

13. newGo.transform.localEulerAngles =

14. Vector3.zero;//mount.transform.eulerAngles;

}

Congratulations! The monument system is now complete. We will interface with this script in a later mission logic.

Creating the InventoryPlaceOnMonument class

This class loops over all the flags in the inventory and places them on the monument. It loops over all the items and then attaches each one to each successive mount point. This can be created by performing the following steps:

1. Create a new InventoryPlaceOnMonument.cs script. This will be attached to a new Prefab for instancing later.

2. This script will cache a copy of the inventory manager by finding the GameObject named Player and then by getting and storing a reference to the inventoryMgr component.

3. This script also caches a copy of monument so that it can interface with the monumentMgr class defined previously.

4. In the update loop, this script will take an object from the inventory of index objectIndex, remove it from the inventory, and set it to active so that it will render again as shown in the following code:

5. GameObject go =

6. inventoryMgr.inventoryObjects[objectIndex].item;

go.SetActive (true);

7. If there is a cached monument object in the scene, it will then call attachObjToMountPoint and attach this inventoryObject to the flag mount using the following code:

8. _monument.GetComponent<MonumentMgr>().attachObjToMountPoint

(go, objectIndex);

Congratulations! You now have written the system that will be used to move the flags from the inventory to the monument at the end of the mission. This script will be attached to a Prefab that we will instance once the second mission is complete.

Creating the MissionMgrHelper script

This script searches through the mission manager and finds a mission by name. Once it finds it, it updates the visible and enabled flags on the mission. This is used to activate the second half of level one's objectives once the first half of the objectives are completed. This script can be created as shown in the following code:

using UnityEngine;

using System.Collections;

public class missionMgrHelper : MonoBehaviour {

public string MissionName;

public bool setActivated;

public bool setVisible;

private MissionMgr _missionMgr;

// Use this for initialization

void Start () {

_missionMgr = GameObject.Find("Game").GetComponent<MissionMgr>();

}

// Update is called once per frame

void Update () {

for ( int i = 0 ; i < _missionMgr.missions.Count; i++)

{

Mission m = _missionMgr.missions[i];

if (m.displayName == MissionName)

{

m.activated = setActivated;

m.visible = setVisible;

}

}

}

}

Creating the TriviaCardScript script

This helper script will be attached to all GUITexture pop ups used in this level, the flaginfo cards, and the user pop ups that happen when the mission's complete. It centers a texture on screen and scales it to the given dimensions.

1. To draw the texture centered on the screen, we start by calculating the center of the screen, and then we offset by half the size of the texture. The reason we do that is because we draw the texture relative to the upper-left corner.

2. The middle of the screen is assigned using the following code:

(ScreenWidth/2.0f, ScreenHeight/2.0f)

3. The upper-left corner of the texture, relative to the center of the screen, is assigned using the following code:

4. (((ScreenWidth/2.0f) – (textureWidth/2)),

((ScreenHeight/2.0f) – (textureHeight/2.0f)))

Creating the TriviaCardScript script

Creating the SetupMissionOne script

This class is used on level startup to configure the world with a random selection of flags for gameplay. This class picks five flags at random and five locations at random. It instances those five flags at those random locations. It also configures the two missions that this level will use to achieve the first learning objective. It is created by performing the following steps:

1. This script will require six individual lists to accomplish its task. Three of them for picking five flags from 50 potential options and three for picking five locations from a set of 10 options.

2. flagPrefabs holds all 50 flag Prefabs. This is populated once at design time in the editor as shown in the following code:

public List<GameObject> flagPrefabs;

3. flagPrefabsBackup is a copy of the previous list. This occurs once when the game is run. The backup will be used to restore the flagPrefabs list if the mission is restarted as shown in the following code:

private List<GameObject> flagPrefabsBackup;

4. FlagInstances is the list of five unique, selected flagPrefabs. This list is populated from the flagPrefab list by choosing an index at random, removing the GameObject in the list flagPrefabs at that slot, and adding it to the flagInstances list as shown in the following code:

public List<GameObject> flagInstances;

5. spawnPoints is a list that holds the 10 potential spawn locations for flags in this level as shown in the following code:

public List<GameObject> spawnPoints;

6. spawnPointsBackup is a copy of the previous list. This occurs once when the game is run. The backup will be used to restore the spawnPoints list if the mission is restarted as shown in the following code:

public List<GameObject> spawnPointsBackup;

7. activeSpawnPoints is the list of five unique, selected SpawnPoints. This list is populated from the spawnpoints list by choosing an index at random, removing the GameObject in the SpawnPoints list, slow, and adding it to the activeSpawnPoints list as shown in the following code:

public List<GameObject> activeSpawnPoints;

8. Once the lists of selected spawnpoints and flagprefabs are filled, the script initializes two missions.

9. The first one to be acquired is set to visible and active as shown in the following code:

10.Mission m = missionManager.missions[0];

11.m.activated = true;

12.m.visible = true;

m.status = mission.missionStatus.MS_Acquired;

13. It is also given a displayName and description as shown in the following code:

14.m.displayName = "MissionOne";

m.description = "collect the 5 randomly placed flags";

15. For this mission, we instance the five selected flags, place them at the selected spawnpoint, and add them to the MissionMgr. Then we add the five MissionToken script instances (one from each flag Prefab instance) to the mission. This associates picking up each flag instance with the objectives of the first mission as shown in the following code:

16.Vector3 flagPos = activeSpawnPoints[k].transform.position;

17.GameObject flagInstance = (GameObject)Instantiate

18. (flagPrefab, flagPos, new Quaternion(0.0f, 0.0f, 0.0f,

19. 1.0f));

m.tokens.Add (flagInstance.GetComponent<missionToken>());

20. The second mission is set acquired, visible, and active as shown in the following code:

21.m.activated = false;

22.m.visible = false;

m.status = mission.missionStatus.MS_Acquired;

23. It is also given a displayName and description as shown in the following code:

24.m.displayName = "MissionTwo";

m.description = "return the flags to the flagstand";

25. All of the MissionTokens from mission one are added to mission two as well. Since mission two starts with one MissionToken (id=10) in the inspector, the total number of tokens for mission two is equal to six. This last token corresponds to the user taking the five flags back to the monument (the monument gives the user this final flag to complete the mission) as shown in the following code:

m.tokens.AddRange (missionManager.missions[0].tokens);

Creating the flag Prefabs

As this mission revolves around finding state flags, let's build a generic Prefab that we can texture with different flag imagery, creating a database of objects to choose from.

1. To get started, let's create a cylinder and set it's scale to (0.5, 3.2, 0.5). Create a dark-grey material, and apply it to the cylinder and name it Pole.

2. Create a sphere, scale it to (1.5, 0.2, 1.5). Place it on top of the pole and parent it to the cylinder object. Create a yellow material and apply it to the texture as seen in the following screenshot:

Creating the flag Prefabs

3. Create an interactive cloth object, and orient it by 270 degrees on the x axis. Scale it to (1, 0.3, 0.08). Parent it to the pole, and set its local position to (5.8, 0.4, 0). This is a GameObject with script attached that simulates the natural motion of cloth under the influence of external forces. We will use this to build nice-looking flags for the states that respond to gravity, wind, and the player's interactions.

4. Create two more spheres, scaled down to (0.4, 0.07, 0.4). Position these on the pole to act as mount points for the interactive cloth. The cloth will attach at these points to the pole. Disable their mesh renderer so that you cannot see them once they are placed correctly (overlapping the interactive cloth). Make sure that these two spheres have a rigid body component so that they can anchor the interactive cloth properly.

Creating the flag Prefabs

5. Create a new, empty GameObject, and name it MissionMgr. Attach the MissionMgr script to this object. We purposely detach this script from the player because the lifespan of MissionMgr may differ from the player object.

Now that we have added our flag geometry, let's create some interactive objects to collect and interact with. As there are 50 states, let's start with Alabama and repeat the following steps for every other state, modifying the textures and state names as appropriate:

1. Create a sphere and place it on the ground plane. Name it Flagpole_Alabama, and disable the mesh renderer component. On the sphere collider, check the IsTrigger checkbox so that we can detect when the player enters the object.

2. Add a CustomGameObject script to this object. Set the display name to Alabama and the object type to flag.

3. Add a mission token script to this object. Set id=501, title to token, and the description to mission 1 token.

4. Add an InteractiveObj script to this object. Set the rotAxis to (0,1,0) to make the object rotate horizontally about the y axis. Set the rot Speed to 40 for a gentle rotation.

5. Add an object interaction script to this object. Set the interaction to putInInventory. Set the interaction type to Unique. Point the text to the Alabama state flag texture.

6. Drag-and-drop this GameObject into the OnCloseEnough variable of the InteractiveObject component. This will connect this reference to the ObjectInteraction component on the GameObject itself.

7. Add an external force of (1.7, 0, 0) and a random force of (2, 2, 2) to the interactive cloth to make the flag flap in the breeze. Consider experimenting with the external force and random force properties of the InteractiveCloth script to explore the various different flag behaviors that can be achieved.

We now have a Prefab that we can customize for each state flag. Note the nice animation on the flag when the player walks by it. Let's create 50 Prefabs by applying the correct texture to the interactive cloth component and then dragging the hierarchy into the project tab. Let's also add the following script instances to each Prefab.

1. CustomGameObject: Set the object type to flag, name it according to the state, and add a reference to the info card for this flag; the info card will show up when the inventory is clicked on, telling the user about the flag, the state name, and some trivia.

2. Add an InteractiveObj script, leaving everything as zero except for the reference to ObjectInteraction (also an instance on the flag Prefab).

3. Add an ObjectInteraction script to this object, and connect the reference to the InteractiveObj script. Set its parameters to PutInInventory and Unique, and set the texture to the state flag texture; the text will be the icon that shows up in the inventory when this item is collected.

4. Add a MissionToken script. Name the token the same as the state, and give each flag a unique ID ranging from 0 to 50.

Congratulations! Once you have done this 50 times (it may take a while), you will have 50 state flag Prefabs. These should then be added to the flagPrefabs list in the SetupMissionOne script.

Creating the pop-up card Prefabs

This game level communicates the learning objectives to the player through the information cards. This information will be baked onto a single texture in your favorite external pixel art program. When the player picks up a flag, or presses on the flag button in the inventory, a pop-up card for the relevant state is displayed as shown in the following screenshot:

Creating the pop-up card Prefabs

The pop-up card Prefabs can be created by performing the following steps:

1. Create a new GUITexture object, and name it popup_<statename>.

2. Drag-and-drop an instance of the TriviaCardScript to the GameObject. Set the card width and height to 320,320.

3. Drag-and-drop an instance of SimpleLifespanScript to the GameObject. Set the seconds parameter to 4. This will make sure that if the information card disappears, it does not matter if you toggle it off from the inventory or if the user just lets it time out naturally.

4. Repeat steps 1 to 3 for each of the 50 states.

5. Drag-and-drop a reference to each of these Prefabs to the appropriate flagObject Prefab. Note that the reference for the game information pop up is in the CustomGameInfo component of the flag object.

Congratulations! You have now created the learning content for the first level of the game. If you need to update these, simply edit the textures in your pixel art program, and Unity3D will naturally update the code and Prefabs.

Creating the pop-up card Prefabs

Creating the mission pop-up Prefab

These game missions communicate their state to the user through pop ups. We need to create two more special purposes dialog boxes that the game will use to reward the user and to inform the user of what the next objective is in the game. The first one, namedreturnFlagsToMonument, communicates to the user that they have all five flags and should walk back to the monument to finish. The second one, named Level1Done, communicates that the level is done and that the next level will load.

We can create a mission pop-up Prefab by performing the following steps:

1. Create a new GUITexture object, and name it returnFlagsToMonument.

2. Drag-and-drop an instance of the TriviaCardScript to the GameObject. Set the card width and height to 320,320.

3. Drag-and-drop an instance of the TriviaCardScript to the GameObject. Set the card width and height to 320,320.

4. Drag-and-drop an instance of SimpleLifespanScript to the GameObject. Set the seconds parameter to 4. This will make sure the pop up disappears after it times out.

5. Repeat steps 1 to 3 for another texture named Level1Done.

Creating the mission pop-up Prefab

Congratulations! These two Prefabs will be used to communicate the user's progress through the learning objectives in level one. Create Prefabs by dragging-and-dropping these GameObjects to the project tab. We will place these Prefabs into the missionMgr script to finish configuring the level.

Creating the mission reward Prefabs

By exploiting the fact that a GameObject Prefab can contain any number of sub-objects in the hierarchy, we can create Prefabs with any number of results to be achieved in the world when a mission is complete. We will use this fact to aggregate and pack together all of the results we want to achieve when the user accomplishes their goals. We will use this fact to construct a reward for when the flags are all found and a separate reward for when the flags are returned to the monument.

Creating the FoundAllTheFlags Prefab

The FoundAllTheFlags Prefab can be created by performing the following steps:

1. Create a new GUITexture object, and name it returnFlagsToMonument.

2. Drag-and-drop an instance of the returnFlagsToMonument Prefab to this object.

3. Create a new Cube GameObject, and name it FlagReturnTriggerObj. This object will be an invisible InteractiveObj class that will (on being picked up by the user), add the final token to the inventory, which will satisfy the second mission in the level.

4. Scale and position it so that it rests on top of the monument. Give it a large height, and make it about 15 percent wider and deeper than the monument itself. Add this object to the FoundAllTheFlags object.

5. Disable the mesh renderer on this object so that we no longer see it.

6. Add MissionToken to this object, give it an ID of 10. Give it a title ReturnToBase and an appropriate description, such as Returns Flags To Base.

7. Add an object interaction script. Set the interaction to AddMissionToken, and set the interactionType to Unique.

8. Add an InteractiveObj class, and set the OnCloseEnough script reference to the ObjectInteractionScipt from this object!

9. Drag this object to the project tab to create a Prefab from it.

Congratulations! Now, when this parent object (FoundAllTheFlags Prefab) is instantiated, the following will occur:

· The returnFlagsToMonument Prefab will be instantiated. This object will detach itself from the parent and display the pop-up GUITexture for a few seconds before destroying itself.

· The FlagReturnTriggerObj Prefab will be instantiated. This invisible object will sit at the top of the monument. When the user walks back to the monument, this will result in a new mission token being collected, which will activate the second mission and complete the level!

Creating the ReturnedTheFlagsResult Prefab

One other Prefab is needed to finish the logic for level one. This Prefab will be instantiated once the user has gotten all the five objects and returned them to the monument.

1. Create a new, empty GameOobject, place it at (0,0,0), and name it ReturnedTheFlagsResult.

2. Add an instance of the Level1Done Prefab (that displays the pop-up dialog box for level completed) as a child of ReturnedTheFlagsResult.

3. Create a new, empty GameObject, name it InventoryPlaceAllFlags, and add it as a child of ReturnedTheFlagsResult.

4. Add five instances of the InventoryPlaceOnMonument script to this object. Set each one to a unique ObjectIndex from 0 to 4. This will remove a single object from the inventory and attach it to the monument at the flag mount of the same index.

5. Drag this Prefab back into the project tab to make a Prefab from this compound object.

Congratulations! Now when this parent object (ReturnedTheFlagsResult) is instantiated, the following will occur:

· The pop-up Prefab will be instantiated. This object will detach itself from the parent, and display the pop-up GUITexture for a few seconds before destroying itself.

· The FlagReturnTriggerObj Prefab will be instantiated. This invisible object will sit at the top of the monument. When the user walks back to the monument, it will result in a new mission token being collected, which will activate the second mission and complete the level!

Configuring the mission manager

Before we can test our game level, we need to configure the MissionMgr class. This class acts as the dispatcher and gate for the dynamic behavior of the game logic. It can be configured by performing the following steps:

1. Ensure that there are two missions in MissionMgr; the size of the missions list in the mission manager is equal to 2.

2. Generally, the default values inside a mission don't really matter (since we set them up in custom scripts such as SetupMissionOne.cs; however, some values need to be preconfigured).

3. In the second mission (mission one), make sure that the token array is of size 1, and has a reference to the FlagReturnTriggerObj mission token on the InteractiveObject class that is sitting on top of the MissionMgr script.

4. In the first mission, set the reward reference variable to the foundtheflagresult Prefab in the project tab.

5. In the second mission, set the reward reference variable to the returnedtheflagsresult Prefab in the project tab.

And that's it! Now when these two missions are finished, those Prefabs will be instanced, causing pop ups to appear and time out, and causing other interactions with the inventory and missions systems as discussed previously.

Playing the level!

We can test our work now by playing the level! Drive the player around the level to find the five missing flags. Once found, press their icon in the inventory to read the information about each state. Once all five flags are found, the system will tell you to return them to the monument, at which time the flags will return and the mission will be done.

Playing the level!

Summary

We have shown how to apply the Player, InteractiveObj, ObjectInteraction, InventoryMgr, and MissionMgr classes that we developed in the first two chapters to create a fun "collect-and-interact" mechanic system for our e-learning game. We also reviewed a model of fun and "gamification" and how this model can be used in e-learning games to design content that will present and encourage consolidation of learning objectives in the user.

Going forward, we will review our code thus far, and make some maintenance changes to future proof the code, ensuring we can extend it and that it will remain suitable for subsequent e-learning games with a different content.