Experiment 02 Interaction Objects

Similar documents
Space Invadersesque 2D shooter

VACUUM MARAUDERS V1.0

Instructions for using Object Collection and Trigger mechanics in Unity

Learn Unity by Creating a 3D Multi-Level Platformer Game

Workshop 4: Digital Media By Daniel Crippa

Unity 3.x. Game Development Essentials. Game development with C# and Javascript PUBLISHING

Kings! Card Swiping Decision Game Asset

Adding in 3D Models and Animations

Unity Game Development Essentials

Star Defender. Section 1

PoolKit - For Unity.

Shoot It Game Template - 1. Tornado Bandits Studio Shoot It Game Template - Documentation.

Save System for Realistic FPS Prefab. Copyright Pixel Crushers. All rights reserved. Realistic FPS Prefab Azuline Studios.

CONCEPTS EXPLAINED CONCEPTS (IN ORDER)

GameSalad Basics. by J. Matthew Griffis

Overview. The Game Idea

COMPASS NAVIGATOR PRO QUICK START GUIDE

"!" - Game Modding and Development Kit (A Work Nearly Done) '08-'10. Asset Browser

Official Documentation

GAME:IT Junior Bouncing Ball

Introduction. Modding Kit Feature List

SteamVR Unity Plugin Quickstart Guide

The purpose of this document is to outline the structure and tools that come with FPS Control.

Creating Bullets in Unity3D (vers. 4.2)

Installation Instructions

EVAC-CITY. Index. A starters guide to making a game like EVAC-CITY

Scratch for Beginners Workbook

For more information on how you can download and purchase Clickteam Fusion 2.5, check out the website

TATAKAI TACTICAL BATTLE FX FOR UNITY & UNITY PRO OFFICIAL DOCUMENTATION. latest update: 4/12/2013

Unity Certified Programmer

First Steps in Unity3D

3D Top Down Shooter By Jonay Rosales González AKA Don Barks Gheist

Your First Game: Devilishly Easy

G54GAM Lab Session 1

1 Shooting Gallery Guide 2 SETUP. Unzip the ShootingGalleryFiles.zip file to a convenient location.

CMSC 425: Lecture 3 Introduction to Unity

Foreword Thank you for purchasing the Motion Controller!

Procedural Level Generation for a 2D Platformer

Shooting in Unity3D (continued)

15 TUBE CLEANER: A SIMPLE SHOOTING GAME

COMPUTING CURRICULUM TOOLKIT

Beginning 3D Game Development with Unity:

Tutorial: A scrolling shooter

2D Platform. Table of Contents

Easy Input Helper Documentation

By Chris Burton. User Manual v1.60.5

In this project, you will create a memory game where you have to memorise and repeat a sequence of random colours!

Speechbubble Manager Introduction Instructions Adding Speechbubble Manager to your game Settings...

No Evidence. What am I Testing? Expected Outcomes Testing Method Actual Outcome Action Required

AIM OF THE GAME GLACIER RACE. Glacier Race. Ben Gems: 20. Laura Gems: 13

INTRODUCTION TO GAME AI

Meteor Game for Multimedia Fusion 1.5

BE SURE TO COMPLETE HYPOTHESIS STATEMENTS FOR EACH STAGE. ( ) DO NOT USE THE TEST BUTTON IN THIS ACTIVITY UNTIL THE END!

Making Your World with the Aurora Toolset

Sword & Shield Motion Pack 11/28/2017

Gaia is a system that enables rapid and precise creation of gorgeous looking Unity terrains. Version March 2016 GAIA. By Procedural Worlds

Once this function is called, it repeatedly does several things over and over, several times per second:

The Beauty and Joy of Computing Lab Exercise 10: Shall we play a game? Objectives. Background (Pre-Lab Reading)

Memory. Introduction. Scratch. In this project, you will create a memory game where you have to memorise and repeat a sequence of random colours!

The Games Factory 2 Step-by-step Tutorial

Section 39: BobmerMan How-To

Kismet Interface Overview

Programming Project 2

If you have any questions or feedback regarding the game, please do not hesitate to contact us through

More Actions: A Galaxy of Possibilities

Spell Casting Motion Pack 8/23/2017

Chapter 1:Object Interaction with Blueprints. Creating a project and the first level

True bullet 1.03 manual

Tutorial: Creating maze games

Easy Input For Gear VR Documentation. Table of Contents

Game Design Curriculum Multimedia Fusion 2. Created by Rahul Khurana. Copyright, VisionTech Camps & Classes

Crowd-steering behaviors Using the Fame Crowd Simulation API to manage crowds Exploring ANT-Op to create more goal-directed crowds

In this project you ll learn how to create a times table quiz, in which you have to get as many answers correct as you can in 30 seconds.

Annex IV - Stencyl Tutorial

Battlefield Academy Template 1 Guide

How to Blog to the Vanguard Website

Lesson 2 Game Basics

Nighork Adventures: Beyond the Moons of Shadalee

Game Maker Tutorial Creating Maze Games Written by Mark Overmars

Macquarie University Introductory Unity3D Workshop

Table of Contents. Creating Your First Project 4. Enhancing Your Slides 8. Adding Interactivity 12. Recording a Software Simulation 19

A. creating clones. Skills Training 5

In this project we ll make our own version of the highly popular mobile game Flappy Bird. This project requires Scratch 2.0.

Step 1 - Setting Up the Scene

Words Mobile Ready Game Documentation

Beginning ios 3D Unreal

This guide provides information on installing, signing, and sending documents for signature with

How to Make Smog Cloud Madness in GameSalad

TABLE OF CONTENTS. Logging into the Website Homepage and Tab Navigation Setting up Users on the Website Help and Support...

Inspiring Creative Fun Ysbrydoledig Creadigol Hwyl. Kinect2Scratch Workbook

Ghostbusters. Level. Introduction:

How to Make Games in MakeCode Arcade Created by Isaac Wellish. Last updated on :10:15 PM UTC

Part II: Number Guessing Game Part 2. Lab Guessing Game version 2.0

Creating a light studio

Game Design Comp 150GD. Michael Shah 3/6/15

Pro Photo Photography Studio By Abranimations INSTRUCTION MANUAL

GameSalad Creator (Windows Version ) Written by Jack Reed Layout by Anne Austin

How to Build a LimeSurvey: The Basics for Beginners

Z-Town Design Document

Transcription:

Experiment 02 Interaction Objects Table of Contents Introduction...1 Prerequisites...1 Setup...1 Player Stats...2 Enemy Entities...4 Enemy Generators...9 Object Tags...14 Projectile Collision...16 Enemy Collision...18 Pickup Prefabs...20 Pickup Spawning...25 Player Collision...27 HUD Hookups...29 Conclusion...31 Introduction It is time to expand upon the game framework created in the first experiment. The first experiment setup the player object with limited movement, the spawning of a projectile triggered by user input, a HUD with dynamic text and icons, and a scrolling background. A game would not be much of a game without something for the player to interact with. Two basic aspects of game interactions are positive and negative results. These two core facets of game design can be expressed through pickups (positive) and enemies (negative). Prerequisites It is essential to have a strong understanding of Unity s editor interface and the C# scripting language. These prerequisites should be reviewed and followed before completing the remainder of this document. The time to complete this document will be greatly exaggerated if these resources are not properly reviewed. 0.) Experiment - Game Framework 1.) Arrays 2.) Scope and Access Modifiers 3.) GetComponent 4.) Instantiate 5.) SerializeField & Serialization Setup This document requires the continuation of the Unity project from either the first experiment or lab. The remainder of the document is illustrated through and refers to that experiment. If you are using the first lab, please note some of the illustrations may not exactly match your project. This is fine and should be expected. If you have not done so already, please backup your Unity project before continuing. This can be accomplished by simply copying and pasting the entire Unity project folder to another location. Once the previous project has been appropriately backed up, the below sections can be completed. PG2: Experiment 02 Interaction Objects Pg. 1

Player Stats Before diving into the creation of enemies and responding to collision events, some player data should be setup. This data will be modified as a result of those interaction events. Locate and open the ship player controller script in MonoDevelop. Declare a Serialized Field variable of type integer. A serialized field exposes a variable to the Unity Inspector window without making it public to all other scripts. Name it MaxLives and assign it a value of three. This variable will contain the maximum number of lives the player will possess. Declare a private variable of type integer. Name it CurLives and assign it the same value as max lives. This variable will contain the current number of lives the player has remaining. Declare two private variables of integer type and name them numshotsfired and numenemyhits. Assign each the value of zero. These variables will be used to track the number of shots the player ship has fired and how many enemy ships have been hit. Remember, keep an eye out for compile warnings. Declare a private variable of type integer and name it Score. Assign it the value of zero. This variable holds the player s current score and will be modified based on game-play activities. PG2: Experiment 02 Interaction Objects Pg. 2

Create a new function with void for return and accepts no parameters. Name it ResetStats and call it from the Start function. This function is used as a singular location to apply default values to the player stat variables. It is called in start to ensure any time a player controller is instantiated, those variables will be assigned the appropriate default values. This function is also a handy utility to be called elsewhere in game (e.g. A pause menu option or game over screen). Inside the reset stats function, assign the value zero to any variable used as an accumulator (counter). Any private variable that needs to be modified outside of this script should have a function created to do just that. The number of enemies hit will be modified outside this script (by the projectile script). Create a new public function named ModEnemyHits which returns void and accepts an integer parameter. The parameter is added to the numenemyhits variable. We don t know the rules of scoring. It seems likely that various locations throughout code could modify it. Create a new public function named ModScore which returns void and accepts an integer parameter. The parameter is added to the Score variable. Although the player s lives remain private, a single point of contact should be implemented. Doing so helps isolate all life handling code to one location. If bugs occur or functionality needs to change, only this single function needs to be located and fixed / changed. Create a new public function named ModLives which returns void and accepts an integer parameter. The parameter is added to the current lives variable. Now that we have some player status setup and managed, other parts of the game can be implemented. PG2: Experiment 02 Interaction Objects Pg. 3

Enemy Entities Waves of enemies will be sent at the player. Instead of creating and placing all the enemy objects in the scene, they will be spawned at runtime. Much like the projectiles shot by the ship, an enemy will be instanced from a prefab. Back in Unity, let's start by creating a Quad. GameObject menu option, select Create Other option, and then select Quad. Select the new game object and rename it to EnemyBasic. Set the material of the Mesh Renderer component in the Inspector window. Expand the Materials tab and select the radio button next to Element 0 PG2: Experiment 02 Interaction Objects Pg. 4

In the dialog box select one of the enemy materials. Remove the Mesh Collider from the Inspector window and replace it with a box collider. Review the collider s attributes and mark the Is Trigger check-box. From the object s Inspector window, create a new Rigid Body. Add Component -> Physics -> Rigid Body PG2: Experiment 02 Interaction Objects Pg. 5

In the new rigid body component, unmark the Use Gravity check-box and mark the Is Kinematic check-box. NOTE: Gravity is obviously used for the effect of physical gravity. Kinematic refers to the ability to manually control is position and orientation. From the object s Inspector window, create a new CSharp script named EnemyControllerBasic. Add Component -> New Script -> Name the script EnemyControllerBasic. Locate the new script in the inspector window and double click it. The MonoDevelop programing IDE should automatically launch. Note: It may throw warnings or errors the first time it is opened. If this happens, close MonoDevelop and repeat the process. PG2: Experiment 02 Interaction Objects Pg. 6

Alternatively, you can open MonoDevelop then browse to and open the project file. Unless the script has been previously modified, you should see something similar to the below image. Add a Serialized Field variable MoveSpeed of type float. This is used to control how fast the enemy moves. The game object s position will be modified in this script s Update function. Since the game s frame rate may fluctuate, the amount of time elapsed since the last frame should be considered. We also want to control the movement speed in the editor. Hence, the MoveSpeed variable is a serialized variable. Its value is multiplied against the Time s delta time. Directly add the result to the game object s transform s position. NOTE: We can use the Transform object directly without having to access it through the GameObject. The enemy will live forever and keep moving far beyond the screen bounds. This wastes performance and memory. Since testing the screen bounds is rather expensive, another means is employed to remove our game object. In the Start function, call the function Destroy. Pass it two parameters, the game object it should destroy and how much time should transpire before the destruction occurs. PG2: Experiment 02 Interaction Objects Pg. 7

We need to verify the functionality before we make it a prefab. Simply press the play button and the enemy game object should move up. This may seem odd, but we'll get to the enemy orientation and correct that shortly. Select the enemy game object in the Hierarchy window and drag it to the PreFabs folder in the Project window. PG2: Experiment 02 Interaction Objects Pg. 8

Delete the enemy object from the Hierarchy window by right-clicking EnemyBasic and selecting Delete. This is because the enemy will be added to the game (the hierarchy window) at runtime during game-play similar to the bullets. Enemy Generators Now that we have an enemy to spawn, we need something in game to spawn them. A new game object will be created which will act as the enemy generator. This generator does not interact with other objects nor is it going to be rendered. It is simple used as a location for spawning enemies. As such, create a new empty game object and name EnemyGenerator. By default, the new game object will be placed in the center of the screen. The player should not see the enemies spawn. They should spawn off screen and move on screen. Select the game object and, in the scene view, translate (move) it to a location just above the top of the screen. The enemies also use this transform for orientation as well as position. Rotate it by 180 on the Z axis so the enemies spawn facing the player. PG2: Experiment 02 Interaction Objects Pg. 9

HINT: You can see a preview of the camera s perspective area Now that we have the generator created and placed in the scene, it s time to have the generator actually generate some enemies. This will be accomplished by creating a new CSharp script named EnemyGenerator. NOTE: The name of the script and name of the game object do not need to be the same. Open this new script in MonoDevelop and add an array of Serialized Field game objects. This array will contain the list of enemy TYPES which can be spawned. We currently have one type but this allows our setup to be flexible and accept any number of new ones created later. PG2: Experiment 02 Interaction Objects Pg. 10

In the editor, set the size of this game object array to three then hit enter. Drag & drop the prefab of the enemy onto each of the three elements. Before we can start spawning enemies, we need to control their spawn frequency (how often they spawn in units of time). For game-play reasons, let s not spawn the enemies at a consistent, predictable, interval. Switch back to the script file and create a new set of variables. The first two will be serialized field floats named TimeMin and TimeMax. These two variables will contain the minimum and maximum times, known as bounds, for selecting the time delay. The other sets of time variables will be used for internal tracking of when the delay duration has been satisfied. Declare two private float variables and name them TimeLimit and Timer. The time limit will be repopulated (assigned a value) each time an enemy is spawned. The timer will reset to zero each time an enemy is spawned and count up to the time limit before allowing another enemy to spawn. PG2: Experiment 02 Interaction Objects Pg. 11

Create a new function named updatetimer which returns void and accepts no parameters. This function will be used to manage the timers and should be called each game update. In the update timer function, accumulate the time elapsed by adding the Time object s delta time variable to the timer variable. Now compare the timer s current value against the time limit. If it s greater than or equal to the limit, it is time to spawn an enemy. Before spawning the enemy, the timer variables should be reset. The time accumulating variable can simply be reset to zero. The time limit is a little more involved as it needs to be populated by a value between the minimum and maximum times. Use the Random utility object for picking a number between the time bounds. The function requires two parameters be passed to it. As you probably have already guessed, the two parameters denote the minimum and maximum numbers to select between. Assign the result of this function to the time limit variable. Since we don t have anything to spawn yet, add a debug log to verify its working when playing through the Editor. PG2: Experiment 02 Interaction Objects Pg. 12

TIP: Don t forget to switch to the Console window to view debug prints. Now that we have functionality for time controlled spawning, let s create a function which handles the actual spawning. Declare a function named dospawn which returns void and accepts no parameters. Replace the previous debug log in the update timer function with a call to this new function. Use the Range function found in the Random utility object. All arrays start at index value zero and have some length. Use zero as the random range s minimum parameter and the array s length as its maximum. Capture the resulting value in a local integer variable named randindex. The randindex variable is used to index into the enemy types array. That array element is supplied as the object type to be instanced. The generator s transform is used as the position and rotation. Multiple enemies should now spawn based on the random time range. PG2: Experiment 02 Interaction Objects Pg. 13

NOTE: This screenshot has a lot more enemies on screen than the script should allow at this point. The variables you need to change to spawn enemies faster are serialized fields. Try to find them in Unity and make your enemies spawn this fast! Object Tags Collision detections are fairly easy to accomplish in Unity. Each object can implement the OnTriggerEnter function which supplies the other game object colliding with us. This other object is just a generic Collider, not the game specific type. Although there are many methods for identifying which specific type the other objects is, the distinction between game objects can be accomplished most efficiently by using the Tag attribute. Each game object created so far, with collision capabilities, should be revisited and assigned a Tag value associated with its type category. Meaning, all enemy types should be tagged with the same enemy Tag value. NOTE: Individual sub- types can be further distinguished by assigning them unique Collider names. See the pickup section for an example. Located and select any game object then review the top component in the inspector window. Expand the list box next to the Tag option then select Add tag option. PG2: Experiment 02 Interaction Objects Pg. 14

In the new inspector window, select the last (or first empty) Element under the Tags section and add a value for each game object type. Add PlayerProjectile, PlayerShip, EnemyShip, and Pickup as new element text values. Locate and select the bullet prefab then review the Inspector window. In the Tag list box, select the new player projectile tag name. Locate and select the enemy prefab then review the Inspector window. In the Tag list box, select the new enemy ship tag name. PG2: Experiment 02 Interaction Objects Pg. 15

Locate and select the player game object then review the Inspector window. In the Tag list box, select the new player ship tag name. Every interact-able game object now has a text value identifying its type. The pickup type is missing from this list. The pickup tag will be set when the prefab is created. From here on out, any game object created with collision will have its Tag value assigned. Projectile Collision A projectile may look visually stunning, depending on the assets used; however, it is not very useful without the ability to collide with other game objects. Start by locating and opening the Projectile script in MonoDevelop. Create a new function named OnTriggerEnter which returns void and accepts a Collider object as its sole parameter. This function has been declared in our parent class. Since the projectile class overrides and implements this function, the function declaration must match exactly with the parent s version. The engine is setup such that this specific function is invoked when a collision between two objects occur. NOTE: This relates to the Mesh Collider s Is Trigger check box in the Inspector window. More than one game object has collision and will cause this function to be executed regardless of its type. Namely, the projectile will collide with the ship that has spawned it. Obviously it should not react to its parent ship, so we limit it to a specific type via the Tag we've assigned it. The other collider has a member variable tag which contains that value. PG2: Experiment 02 Interaction Objects Pg. 16

Add an if-statement verifying its value then place a simple debug log inside it. Run the game and you should see the debug message when it collides with an enemy ship. After a successful test of the debug message, replace it with a call to Destroy and pass it the projectile s game object. The projectile should now disappear when hitting an enemy. We could stop there, but, this is a game and we want to reward the player for hitting an enemy. The player ship controller class contains the player stats. To modify those stats, the projectile class needs a reference to that class. Add a new private variable of type ShipPlayerController named ParentShip which is used to hold that reference. Next, the instance of the player s ship controller script needs to be located and used to populate the parent ship variable. When the projectile is spawned, its Start function is called. We can use this location in conjunction with the game object s find function to perform our assignment. The find function accepts a string name and should be sent the exact name of the player ship game object. The result of this function can be captured in the basic game object type. Once that's done, we can use the result to access a component from that object via its GetComponent function. This function is a little strange in that the component name is NOT sent as a parameter; rather, as a type specifier. Take note that the < and > characters are used before the parameter ( ) characters. PG2: Experiment 02 Interaction Objects Pg. 17

Now that we have a reference to the parent ship, let s use it to reward those points! In the OnTriggerEnter function, where the projectile is destroyed, access the ModScore function from the player ship. Pass it a positive value of your choosing. The other player stat we can handle here is the number of enemies hit. NOTE: Alternatively, this same process, to access and modify the stats, could be applied to the enemy script. Since we've already done it in the ShipPlayerController, it's far more efficient to use those functions. That way if a change needs to be made to the way points or hits are counted, the change only need happen in one place. Enemy Collision An enemy is not much of an enemy if it does not collide with other game objects. In this case, we want the enemy to react to the player s projectile and ship. Start by locating and opening the basic enemy controller script in MonoDevelop. Create a new function named OnTriggerEnter which returns void and accepts a Collider object as its sole parameter. The engine is setup such that this specific function is invoked when a collision between two objects occur. As such, the function declaration must match exactly with what is shown in the document. NOTE: This relates to the Mesh Collider s Is Trigger check box in the Inspector window. More than one game object has collision and will cause this function to be executed regardless of its type. Namely, the enemy will collide with other enemies or pickups. Depending on the design of the game, this may or may not be desirable. This experiment does not want this to occur so we limit it to a specific type via its Tag, similar to how we accomplished this with the projectile. The other collider has a member variable tag which contains the tag we've assigned it. Add an if-statement verifying its value then place a simple debug log inside it. Run the game and you should see the debug message when it collides with a projectile or player ship. PG2: Experiment 02 Interaction Objects Pg. 18

We could stop there, but, this is a game and we want to punish the player for wrecking into an enemy. The player ship controller class contains the player stats. To modify those stats, the enemy script needs a reference to that class. Add a new private variable of type ShipPlayerController named PlayerShipCtrl which is used to hold that reference. Next, the instance of the player s ship controller script needs to be located and used to populate the player ship variable. When the enemy is spawned, its Start function is invoked. Just like in our previous example, we use this location in conjunction with the game object s find function to perform our assignment. The find function accepts a string name and should be sent the exact name of the player ship game object. The result of this function can be captured in the basic game object type. Once that's done, we can use the result to access a component from that object via its GetComponent function. This function is a little strange in that the component name is NOT sent as a parameter; rather, as a type specifier. Take note that the < and > characters are used before the parameter ( ) characters. Now that we have a reference to the parent ship, let s use it to punish the player. In the OnTriggerEnter function, where the enemy is destroyed when colliding with the player, access the ModScore function from the player ship. Pass it a negative value of your choosing. PG2: Experiment 02 Interaction Objects Pg. 19

Pickup Prefabs An easy way to spice up a game is to add some positive rewards for the player. These rewards can be expressed through many different means; however, the concept of a Pickup is universally known and expected. Start by creating a new Quad. GameObject -> Create Other -> Quad. Select the new game object and rename it to Pickup. Review the top component in the inspector window. Expand the list box next to the Tag option then select the Pickup option. PG2: Experiment 02 Interaction Objects Pg. 20

Set the material of the Mesh Renderer component in the Inspector window: Expand the Materials tab and select the radio button next to Element 0 In the dialog box select the pupscore materials. Remove the Mesh Collider from the Inspector window and replace it with a box collider. Review the collider s attributes and mark the Is Trigger check-box. PG2: Experiment 02 Interaction Objects Pg. 21

Next, from the object s Inspector window, add a Rigidbody. Add Component -> Physics -> Rigid Body In the new rigid body component, unmark the Use Gravity check-box and mark the Is Kinematic check-box. NOTE: Gravity is obviously used for the effect of physical gravity. Kinematic refers to the ability to manually control is position and orientation. From the object s Inspector window, create a new CSharp script named Pickup. Add Component -> New Script -> Name the script Pickup. PG2: Experiment 02 Interaction Objects Pg. 22

Locate and open this new script in MonoDevelop. Add a serialized field variable MoveSpeed of type float. This will be used to control how fast the pickup moves. In this script s Update function, we'll be modifying the Pickup's location. As we've done previously, we'll use the Time object's deltatime to keep track of the time elapsed between frames. The deltatime variable handles this by being multiplied against the game object s transform s up component. The MoveSpeed variable is multiplied against the Time s delta time, and since we want to control the movement speed in the editor, it's made as a serialized field. Directly subtract the result to the game object s transform s position. NOTE: We can use the Transform object directly without having to access it through the GameObject. As before, we don't want the pickup to live forever, wasting performance and memory, and we don't want to worsen performance by constantly testing screen boundaries either. The easier way to do this is to simply remove the game object. In the Start function, call the function Destroy. Pass it two parameters, the game object it should destroy and how much time should transpire before the destruction occurs. This pickup script can be reused for every other type of pickup. Each pickup type uses the same tag identifier. We need a means to distinguish between the unique types. Declare a serialized field string variable named subtypename and assign it the value UnknownPickup. This variable will be used to contain our custom name used to denote its pickup type. The Collider object type is passed into the collision trigger function. The name variable of the pickup s collider is assigned this value so it can be checked in that trigger function. The best place to perform this assignment is when the pickup is first started. PG2: Experiment 02 Interaction Objects Pg. 23

In the editor, select the pickup and, from the inspector window, assign the sub type name a particular value. Let s use the Score value to denote it as a pickup which will affect the player s score. We need to verify the functionality before we make it a prefab. Simply press the play button and the pickup game object should move up. Don't worry about it going up, we'll correct that shortly. Select the pickup game object in the Hierarchy window and drag it to the PreFabs folder in the Project window. PG2: Experiment 02 Interaction Objects Pg. 24

Delete the pickup object from the Hierarchy window. From here on out that object will be added to the game dynamically during gameplay, so it doesn't need to remain in the hierarchy. Pickup Spawning Now that a pickup prefab has been created, we need to spawn them into the game scene. Depending on the design, there are many locations or means by which they could be spawned. For this experiment, they will be spawned when an enemy has been destroyed. Open the enemy controller script in MonoDevelop and add an array of game objects. This array will contain the list of pickup TYPES which can be spawned. We currently have one type but this allows our setup to be flexible and accept any number of new ones created later. In the editor, select the enemy prefab and set the size of this game object array to three then hit enter. Drag & drop the prefab of the pickup onto each of the three elements. PG2: Experiment 02 Interaction Objects Pg. 25

Create a new function called SpawnPickup which returns void and accepts no parameters. Locate the OnTriggerEnter function. Call this new function inside the if-statement handling the player projectile tag. Use the Range function found in the Random utility object. All arrays start at index value zero and have some length. Use zero as the random range s minimum parameter and the array s length as its maximum. Capture the resulting value in a local integer variable named randindex. The randindex variable is used to index into the pickup types array. That array element is supplied as the object type to be instanced. The enemy s transform is used as the position and rotation. A pickup should now appear when the enemy is destroyed due to a player projectile collision. PG2: Experiment 02 Interaction Objects Pg. 26

Player Collision Now that we have pickups, functionality can be added to the player ship for interacting with them. More importantly, the player can be rewarded for capturing those pickups. Start by locating and opening the player ship controller script in MonoDevelop. Create a new function named OnTriggerEnter which returns void and accepts a Collider object as its sole parameter. The engine is setup such that this specific function is invoked when a collision between two objects occur. As such, the function declaration must match exactly with what is shown in the document. NOTE: This relates to the Mesh Collider s Is Trigger check box in the Inspector window. More than one game object has collision and will cause this function to be executed regardless of its type. Namely, the ship will collide with the projectile that it shoots. Obviously it should not react to its own projectile. We limit it to a specific type via its Tag. The other collider has a member variable tag which contains the tag we've assigned it. Add an if-statement verifying its value then place a simple debug log inside it. Run the game and you should see the debug message when it collides with a pickup. There could be more than one sub-type of pickup. The pickup s collider was named Score. Add a second ifstatement to check the collider s name for that value. Run the game and you should see the debug message when it collides with a score sub-type pickup. PG2: Experiment 02 Interaction Objects Pg. 27

A debug print is fine for testing functionality; however, we want the score pickup to actually affect the player s score value. The score variable could be accessed directly but that is not the best approach. The ModScore function should be used instead. This maintains a singular location (point of contact) for adjusting that variable. If any bugs occurred regarding the score, a single break-point would be added to that function. If it was not used, every location in code which touched that variable would need a log or break-point. Furthermore, code could be added to the ModScore function to prevent its value from falling below or exceeding certain values. The pickup the player has collided with needs to be handled as well. By simply removing the other game object from the game scene, the collection process is simulated. Add a call to the destroy function. Since the other is of Collider type and that function only accepts game objects, the other s game object should be passed. NOTE: Alternatively, the pickup script could have an OnTriggerEnter function added to it. When it detects a collision, it would destroy itself. Although the enemy has collision handling for wrecking into the player, the player should also provide a response to that wreck. Add an else-if statement, below the pickup if-statement, in the OnTriggerEnter function. Compare the other s tag value to the name of the enemy ship tag. Inside the body of that else-if, modify the number of player s lives by negative one. PG2: Experiment 02 Interaction Objects Pg. 28

HUD Hookups The HUD is currently drawing text and images; however, all the information is static (unchanging). A practical HUD would dynamically update the information based on game-play activities. We have added some functionality to modify the score based on collisions. The player has no way to know that the score is being adjusted. Let s connect the HUD s drawn score to the player s score stat. Start by locating and opening the player ship controller script in MonoDevelop. Add a serialized field variable of HUD type and name it PlayerHUD. This variable holds the reference to the HUD game object. Specifically, the HUD script component. TIP: Don t forget to drag and drop the HUD game object, from the Hierarchy window, to this new variable, in the player ship s Inspector window. Locate the ModScore function in the player s ship controller script. Use the HUD s updatescore function to update it to the newly modified value. Calling the HUD from this location allows for a singular point of contact. Any other areas of code, which modify the score, do not know or care about the HUD. The HUD will automatically reflect the new score value. HINT: Don t forget to remove the testing code in the HUD s start function. PG2: Experiment 02 Interaction Objects Pg. 29

The HUD should now show the score change in real-time. The number of HUD life icons are currently hardcoded. Similar to how we handled the score, functionality can be added to make those icons dynamically updated. Start by locating the ResetStats function in the player s ship controller script. Just below the assignment of the max lives to the current lives value, call the CreateLifeIcons from the PlayerHUD variable. Pass it the MaxLives lives variable as the parameter. This will ensure the HUD creates enough icons to represent the maximum number of lives. NOTE: This create function only instances the icons once. It ignores the call if already created. Before testing this new functionality, the HUD s internal test of the create function needs to be removed. Open the HUD script and locate the Start function. Remove the call to CreateLifeIcons. PG2: Experiment 02 Interaction Objects Pg. 30

Since this reset stats function could be called at any time during or after game-play, depending on the design, the HUD needs to reflect the current number of lives. NOTE: The current lives variable is assigned the maximum number of lives. The max number of lives could be passed to the HUD instead. However, the point of the HUD s update function is to reflect the current life count. The life count is also changed in the ModLives function. Add the same call to updatelives in that function. Now any time the life count is modified, the HUD will automatically reflect the new value. The life icons on the HUD should now disappear when an enemy collides with the player. Conclusion That s it for this experiment! It would be highly beneficial to continue testing out and experimenting with different materials, values, and additional types of game objects. The results might ignite your imagination! PG2: Experiment 02 Interaction Objects Pg. 31