Fall-In Production Project – Session 2

 

“DIY Alien invasion” by Scott Beale is licensed under CC BY-NC-ND 2.0

SUMMARY

Role: Producer

Intention (SMART Goal)

To better learn and understand the role of Producer to become better at its clashing role; Director.

PRE-PRODUCTION – INQUIRY

Leader(s) in the Field / Exemplary Work(s)

Jeffrey Hunt is the main programmer at Hoppo Games, his most notable work being Risk Of Rain 2. Jeff was self-taught as a modder, and has made mods for games such as Starcraft and DOOM from the age of 11.

Training Source(s)

Micah

Jacob

General tinkering in Construct

Project Timeline

  1. Create Project and share with team members
  2. Create Player Sprite with basic movement
  3. Create gun
  4. Create bullet
  5. Make player sprite shoot bullets from the gun
  6. Ensure the gun is attached to the player
  7. Ensure the player is bound to layout
  8. Ensure the camera is following the player
  9. Create Enemies
  10. Import Enemies into Construct
  11. Add Pathfinding behavior to Enemies
  12. Code Pathfinding for Enemies
  13. Enable enemies to be damaged by bullets
  14. Enable enemies to die after enough damage has been taken
  15. Enable enemies to attack player
  16. Enable player to die after enough damage has been taken
  17. Create health bar
  18. Restart game after the player dies

Proposed Budget

PRODUCTION – ACTION

The (FILM, SOUND, or GAME Creation)

https://hockeypuck.itch.io/fall-in

Skills Commentary

The player can move freely about the map at all times.

The game restarts when the player dies.

The player can fire bullets.

The bullets damage the enemies.

The enemies die once damaged enough.

The player can be damaged by enemies.

The player dies once damaged enough.

A new enemy spawns once every ten seconds.

POST-PRODUCTION – REFLECTION

21st Century Skills

Ways of Thinking (Creativity, Innovation, Critical Thinking, Problem Solving)

I, with the help of Micah and Jacob, determined that to stop the enemies from spawning on top of each other, that they should spawn every ten seconds rather than every tick.

Ways of Working (Communication & Collaboration)

I consulted Micah each time I tested the project.

Tools for Working (Info & Media Literacy)

As I was developing the game in Construct, I occasionally ran into parts of Construct I was unfamiliar with, and consulted Micah whenever I did.

Ways of Living in the World (Life & Career)

I decided to take on the role of Producer in order to help me become better at its clashing role, Director, which is what I wish to pursue in the real world.

Reactions to the Final Version

In terms of movement, the player is more limited than the enemy.

Self-Evaluation of Final Version

Due to the (mostly) excellent communication between our team, the final version of the project turned out better than I originally expected . My only complaint is that we never began working on a shooting animation due to time constraints.

What I Learned and Problems I Solved

Through the development of our game, I learned how to code more mechanics in Construct than what I previously knew, with a focus on a deeper understanding of pathfinding and basic enemy spawning. I also gained a better understanding of global variables by using a global variable to fix a bug where the game would not restart upon the player dying.

Grammar and Spelling

Built-In Grammar and Spell Check.

Editor

Micah B.

Instantiate Tip

Recently, I found a simple yet amazing to use the Instantiate function that’ll solve problems such as adding to the player’s score when they kill an instantiated enemy. What I needed it for was to untick a boolean whenever a player shoots an enemy.

Here’s how one would go about writing this code:

First, declare the variable:

public GameObject clone;

Ensure the variable is of type GameObject and don’t use an array. The public keyword isn’t required unless you’re going to call this variable in other scripts, for example, if you were using this to add to the player’s score every time they killed an enemy, you’d probably want to use the variable in your score manager script.

Now, you could call Instantiate() when you first declare the variable, although in most cases you’ll want to call Instantiate() in the Update() method, or a function of your own. In either case, you’ll be assigning the variable in one of those methods or functions rather than at the start of the class when you declare the variable. Here’s what I’m talking about:

clone = Instantiate(prefab, transform.position, transform.rotation);

When I first saw this, I doubted the versatility of this, but since you’re effectively assigning the instantiated clones to this variable, you can do anything with this that you would with a GameObject variable.

Refresh Feedback

 

 

Summary

  • You find yourself trapped in a void prison, where only the Milky Way’s worst threats are detained, although you are not without hope; the warden of the prison has created a gauntlet that leads to the light at the end of this seemingly endless tunnel.
  • Wrongly detained in a void prison, your only hope is The Warden’s Gauntlet, but if you expected an easy escape, the warden detained you in the wrong cell.

Questions

  • How difficult is the game? If you feel it’s too easy, please explain how it could be more difficult. If you feel it’s unbearably hard, please explain how it could be easier.
  • When you die in the game, does it feel like you died because you legitimately made a mistake or because of a technical flaw in the game? If you feel like you died because of a technical flaw, please explain.

Peer Feedback

  • Brev – The game is great with lots of replay value but the first guys go too fast for you to see and you have to have the reflexes of a god to dodge the bosses’ first attack.

Random Dungeon Generation

I will be taking notes on a three-part series on random dungeon generation.

Episode 1

Notes:

0:55 What you’ll be making

1:47 Our dungeon must have a start point and an exit point.

1:56 We need a clear path between the start and exit.

2:11 Our dungeon must be closed.

2:33 Create Rooms.

2:47 In Edit<Snap Settings change the X and Y move values to 1 to move the walls in a clean and precise way.

3:01 Entry room has four openings.

3:56 Rooms are named with one or two letters abbreviating where the openings are.

3:53 Room spawn points are ten units back of each opening.

4:04 Create an empty game object.

4:07 Parent it to the room.

4:10 This will be our room spawn point.

4:23 Make a script for spawning rooms and drag and drop it on the spawn point object.

4:31 Create a spawn point tag and ensure the spawn point has it.

4:35 Add a 2D Box Collider set to trigger.

4:39 Add a 2D Rigidbody with a Kinematic body type.

4:51 Give the spawn point a gizmo.

5:02 Increment the Y position of our spawn point by 10 so it’s 10 units away from the top door.

5:13 Duplicate the spawn point and ensure the duplicate is 10 units away from the right door.

5:32 Prefab all the rooms and delete them from the scene except for the entry room.

5:45 In the room spawner script, create a public variable of type int for the opening direction.

5:59 If the opening direction variable equals 1, a bottom door must be spawned.

6:05 If the opening direction variable equals 2 a top door must be spawned. If the opening door variable equals 3 a left door must be spawned and if it equals 4 a right door must be spawned.

6:13 In the inspector, type 1 into the opening direction variable for the spawn point 10 units away from the top opening to spawn in a connecting top door.

6:21 For the spawn point to the right, type in 3 for the opening direction value to spawn a connecting left door.

6:28 For the bottom spawn point, type in 2 to spawn a connecting top door.

6:34 Type in 4 for the left spawn point to spawn a connecting right door.

6:58 In the Update function of our room spawner script, check if our opening direction variable is equal to 1. If so we need to spawn a bottom door.

7:02 In an else if clause, check if the opening direction variable is equal to 2. If so we need to spawn a top door.

7:10 Create two more else if clauses checking if the opening direction variable is equal to 3 or if it’s equal to 4. If so we need to spawn a left or right door respectively.

 

 

 

 

Episode 2

This video leaves off where Episode 1 started. The focus of this episode is making the code to spawn the rooms.

Notes:

0:47 Create an empty game object called Room Templates.

0:52 Create a new script to place on the Room Templates object.

1:01 Open up the script in your scripting editor. Delete the Start and Update functions.

1:05 Create 4 public Game Object arrays.

1:12 These 4 arrays are for bottom rooms, top rooms, left rooms, and right rooms.

1:19 Drag and drop the rooms into the corresponding arrays based on their letter names. B for the bottom, T for top, L for left, and R for right. If a room has multiple letters, it goes in multiple arrays.

1:49 Create a “Rooms” tag and ensure it is on the Room Templates object.

2:21 Create a variable referencing the Room Templates game object.

2:34 Set the templates variable equal to the Room Templates script that’s on the game object tagged “Rooms”.

3:07 In the first if statement, instantiate a bottom door from the template’s script.

3:18 Create a private variable of type int called rand.

3:32 Inside the if statement, set rand equal to a random number between 0 and the number of rooms in the array.

3:36 State an index of rand in the array in the first argument for the instantiate function.

3:59 Copy and paste the instantiate function into each else if clause, only changing the bottom rooms to top rooms, left rooms, and right rooms.

4:22 Change the Update function to a Spawn function and Invoke the function in the Start function.

4:42 Type the name of the function as an argument for Invoke. Here, it is typed in between quotation marks, but I’ve learned that Invoke is much more accurate if you call the function like so: Invoke(nameof(Spawn), 0.1f)

5:03 Create a private variable of type bool to determine if a room has been spawned.

5:12 Make an if statement in our spawn function at the top checking if the spawned bool we made equals false.

5:16 Cut the block of code we just made and paste it into the scope of the if statement checking if our spawned bool equals false. If this statement returns true, the code we wrote will be run.

5:26 Set the spawned bool to true as soon as the code runs.

6:08 Create an OnTriggerEnter2D function under the Spawn function. Ensure it has a parameter of type Collider2D and name it other.

6:53 In this function, check if the object “other” has collided with has the tag “SpawnPoint”.

6:45 Destroy the spawn point.

6:53 Double check that the spawn points have spawn point tags Colliders all set to triggers, and Rigidbodies.

Episode 3

In this episode, we will close the remaining openings, define an exit room, and explain how one could expand on this system.

Notes:

1:20 In the last if statement we made, check if “other” has a spawned boolean that equals false and if the current spawn point hasn’t spawned anything.

1:31 If all conditions above are met, spawn walls blocking off all exits.

1:41 In the room templates script, add a public variable of type game object that will store these walls.

1:45 The game object will be a wall the size of a room, guaranteeing the player cannot escape.

1:53 Instiatiate the closed room at the spawn point’s position and no rotation.

1:55 Ensure the spawn points are destroyed AFTER all the code above runs.

1:59 Set spawned to true after the spawn points are destroyed.

2:36 Add a spawn point in the center of the room.

2:46 Remove the room spawner script from this spawn point and instead add a new script called destroyer to this point.

2:52 In the destroyer script, create an OnTriggerEnter2D and destroy whatever collides with it.

3:11 If you want a higher chance of a certain room spawning in your dungeon, drag and drop it multiple times into it’s given array.

3:47 Create a public list of game objects called “rooms”.

3:51 Create a new script for adding rooms to this list.

3:54 Drag and drop it onto every room (except the closed room).

4:14 Create a private variable that references our room templates script.

4:23 In the Start function set the templates variable equal to the room templates script located on a game object with the tag “Rooms”.

4:32 Under that line, add a room from templates to the list.

4:35 Add this.gameObject in the parentheses saying you wish to add the object that this script is on, which is every room in our case.

5:06 Create a public float variable for the time time to wait for spawning a boss.

5:09 Create a private variable of type bool checking if the boss has spawned.

5:13 Create a public game object for the boss.

5:21 In the update function, check if the wait time is less than or equal to 0.

5:28 Before spawning the boss, write an else clause saying if the statement returns false, slowly decrease the wait time.

5:40 Create a for loop.

5:49 Replace max with rooms.Count to ensure the loop runs as long as the number of items in the list greater than 0.

6:01 In this loop, check if i is equal to the number of rooms in the list subtracted by one because lists start counting at 0 instead of 1.

6:22 Spawn the boss at the last spawned room with no rotation if the above statement returns true.

6:28 Set the spawned boss boolean equal to true after the boss is spawned.

6:33 Add a second condition to the if statement saying that spawned boss must equal false.

6:43 Type in a wait time in the inspector window.

6:49 Drag and drop the boss game object to the game object slot in the inspector.

7:10 In the room spawner script, create a public float variable that dictates how long to wait to spawn in a room.

7:15 In the Start function, destroy the game object with this script attached to it after the amount of time dictated by the wait time variable to save memory.

7:41 How one could go about expanding on this system.

Boss Battle in Unity

Notes:

  • 1:41 What is a finite state machine?
  • 1:49 Example FSM diagram.
  • 2:12 Examples of boss states.
  • 2:34 Unity’s built-in state machine.
  • 2:45 What you’ll be making.
  • 5:15 Open the animator window.
  • 5:34 Select and insert the attack, run, and intro animations into the animator.
  • 5:48 Set the intro as the default state.
  • 5:55 Delete the idle animation.
  • 6:09 Make a transition from the intro state to the run state
  • 6:13 Click on the transition to choose when and how we transition to this state.
  • 6:31 Set exit time (how much of the animation do you want to play, 90% in this example).
  • 6:40 Uncheck “fixed duration” so the transition duration can be a percentage (10% in this example).
  • 7:07 Make a transition from the run state to the attack state.
  • 7:18 Add a trigger parameter for an attack.
  • 7:25 In our transition from run to attack, add the attack trigger as a condition.
  • 7:32 On the transition from the run state to the attack state, turn exit time off.
  • 7:39 Set the transition duration. Make sure that “fixed duration” is on. (one second is the transition duration in this example).
  • 7:49 Make a transition from attack to run
  • 8:00 Set up this transition in the exact same way as the intro transition to run.
  • 8:20 Add a behavior script to the run state.
  • 8:39 In your scripting editor, remove the two bottom functions.
  • 9:02 Remove the comments on the functions OnStateEnter, OnStateUpdate, and OnStateExit.(Ctrl+Shift+Alt+/ is a nifty hotkey to help you do this automatically)
  • 9:10 The OnStateEnter method.
  • 9:14 The OnStateUpdate method.
  • 9:18 The OnStateExit method.
  • 9:43 Locate the player in OnStateEnter.
  • 9:47 Ensure the player has the “Player” tag.
  • 10:01 Store the player’s transform information in a variable.
  • 10:51 Find the rigidbody on the boss.
  • 10:58 Store the rigidbody in a variable.
  • 11:06 Create a variable of type Vector2 for the boss’s target destination equal to a new Vector2 with the player’s position on the X-axis and the boss’s position on the Y.
  • 11:21 Under that line, move the boss to the position of the player using Vector2.MoveTowards using a speed determined by us multiplied with Time.fixedDeltaTime.
  • 12:11 Store the line we just wrote in a Vector2.
  • 12:18 Move the rigidbdy to our new position determined by the line we wrote before.
  • 12:42 Make the boss face the direction of the player regardless of which direction the player is on.
  • 13:11 Get the boss script component and call the LookAtPlayer function.
  • 13:17 Create a variable to store the reference to the boss script.
  • 13:22 Set the boss script reference variable equal to the boss script.
  • 13:24 Call the boss script’s LookAtPlayer function.
  • 13:54 Use Vector2.Distance to check our distance from the player.
  • 14:01 Use an if statement to check if the boss is within attack range of the player.
  • 14:15 Create a public variable of type float called attack range.
  • 14:22 In OnStateUpdate set our attack trigger.
  • 14:50 In OnStateExit, reset our attack trigger.
  • 15:52 Find the attack animation.
  • 15:57 Find the point in the animation where we wish to trigger the attack.
  • 16:00 Add an event.
  • 16:03 You can select from any public function.
  • 16:11 Select the attack function.
  • 16:32 Select the Enrage, Enraged attack, and Enraged run animations and drag them into the animator.
  • 16:54 Create a bool parameter to check whether the boss is enraged.
  • 16:57 Make a transition from run to enrage.
  • 17:03 Select the transition, as a condition, ensure the boss is enraged.
  • 17:07 Disable exit time and set the duration to 0.1.
  • 17:30 Create a transition from enraged to enraged run, for the exit time and transition duration, use the same settings as the normal run state.
  • 17:42 Create a transition from enraged run to enraged attack. Set the condition to the attack trigger.
  • 17:44 Change the transition duration to 0.1.
  • 17:46 Make a transition back to enraged run for enraged attack. Use the same settings as the transition from normal attack to normal run.
  • 17:54 Reuse the normal run behavior script on the enraged run state.
  • 18:06 Bump up the speed and extend the attack range on the enraged run.
  • 18:25 Find the enraged attack animation.
  • 18:29 Find the point where we want the player to be damaged.
  • 18:35 AAdd the enraged attack function.
  • 19:08 Open the boss health script.
  • 19:42 Check if the boss’s health is less than or equal to half. If that statement returns true, set the is enraged bool parameter to true.
  • 20:12 Add an enraged behavior script.
  • 20:49 In OnStateEnter, get the boss health script and set the is invulnerable boolean to true.
  • 20:51 In OnStateExit set the is invulnerable boolean back to false.

Advanced AI in Unity- State Machine

Notes:

  • 0:30 What you’ll be making.
  • 1:16 What we’ll be using.
  • 1:37 Open the animator

EXAMPLE STATE 1: FOLLOW

  • 1:55 Create a bool parameter to find out if the enemy is following the player.
  • 2:02 Make a transition between the idle state and the chasing state.
  • 2:12 Trigger this transition only when the enemy is following the player.
  • 2:17 Make a transition from the follow state to the idle state that will trigger if the enemy stops following the player.
  • 2:28 Add a behavior script to the chase state.
  • 2:35 Open the behavior in your scripting editor.
  • 2:41 Remove the comments on the OnStateEnter, Update, and Exit functions.
  • 3:10 Create a private variable of type Transform to store the player’s position.
  • 3:14 In the On State Enter function set the Transform variable equal to the transform information on the object tagged “Player”.
  • 3:27 In the On State Update function, make the AI follow the player.
  • 3:36 In the parentheses of MoveTowards() feed in the animator’s position, the player’s position, and a speed value, you’re probably going to want a speed variable for this.
  • 3:49 Multiply all the parameters with Time.deltaTime.
  • 3:53 Type a value for speed in the inspector.
  • 3:56 Ensure the player has the “Player tag
  • 4:12 Add a behavior to the idle state.
  • 4:25 In On State Update set the is following bool to true if the space key is pressed.
  • 4:42 In the On State Update for the chase state behavior set the is following to false if the space key is pressed.

EXAMPLE STATE 2: PATROL

  • 5:04 Make another bool parameter to check if the AI is patrolling.
  • 5:09 Make a transition from the chase animation to the patrol animation.
  • 5:13 Make this transition trigger if the AI is patrolling.
  • 5:20 Make a transition from the patrol state to the chase state that triggers if the AI is not patrolling.
  • 5:23 Add a behavior script to the patrol state.
  • 5:31 Create a patrol path and have the AI move along it. A video on the patrolling behavior will be linked here.
  • 5:40 If the player presses space, stop the AI from patrolling.
  • 5:53 In the On State Update function in the chase behavior script, add an if statement checking if the player presses P. If they do press P, make the AI start patrolling.

PLAYING SFX WITH STATE MACHINE BEHAVIORS (TIMELAPSED BONUS)

  • 6:49 In the chase behavior script, add a private variable of type AudioSource.
  • 6:49 In On State Enter set the audio source equal to that on the animator.
  • 6:50 Below that line, play the audio source.

SPAWNING PARTICLE EFFECTS WITH STAE MACHINE BEHAVIORS (TIMELAPSED BONUS #2)

  • 7:00 In the idle behavior script, add a public variable of type game object for the particle effect.
  • 7:04 Instantiate the effect at the animator’s position and no rotation for the third argument.
  • 7:05 Drag and drop the particle system game object into the empty “effect” slot in the inspector.

7:07 Final product and final words.

Refresh Production Project

“Game Design Industry Night” by vancouverfilmschool is licensed under CC BY 2.0

SUMMARY

My goal is to improve in the area of gameplay coding, but also learn a little bit about art and sound design, the likes of which I haven’t ended up doing myself on any other game design project.

Role: Lead Designer

Intention (SMART Goal)

By June 16th, 2021, I wish to make a fully functional, gameplay-first game that is enjoyable for all gamers as well as further develop my skills in the areas of gameplay coding, art, animation, and sound design.

PRE-PRODUCTION – INQUIRY

Leader(s) in the Field / Exemplary Work(s)

“《戰神》總監Cory Barlog表示單機遊戲不會死 對競爭類遊戲無感” by steamXO is marked with CC PDM 1.0

Cory Barlog is the creative director of the American game design company SIE Santa Monica Studio, best known for his work on the God of War franchise. He also worked on Backyard Wrestling: Don’t Try This At Home and X-Men: Next Dimension as a lead animator. He’s also worked with Crystal Dynamics on 2013’s Tomb Raider as the cinematics director. He stands out to me for writing film-like stories that immerse the player in the world, similar to the works of Christopher Nolan.

“Dark Souls II” by K-putt is licensed under CC BY-NC 2.0

Hidetaka Miyasaki is a Japanese video game director, designer, writer, and company president of FromSoftware. Miyasaki joined the company in 2004 as a game designer for the Armored Core series but later became known for the Souls series, Demon’s Souls, Dark Souls, Bloodborne, and Sekiro: Shadows Die Twice. He stands out to me for telling the story of the Souls franchise through gameplay rather than look but don’t touch cutscenes that spoon-feed the player the story.

“Alan Wake” by K-putt is licensed under CC BY-NC 2.0

 

Sami Järvi, better known as Sam Lake, is the creative director of Remedy Entertainment and the chief writer of Control, Remedy’s latest game. Lake’s most known and most praised work is on the Max Payne franchise, he has also worked on Alan Wake and Quantum Break as the chief writer. He stands out to me for the astounding world-building in all of his games.

Training Source(s)

2D AI Follow

2D AI Shooting

Project Timeline

  1. Complete GDD
  2. Write Tasks in Backlog
  3. Fibonacci tasks.
  4. Add tasks to MVP board.
  5. Start MVP.
  6. Complete MVP by December 18th.
  7. Fix V1 Encounter as needed.
  8. Prefab V1.
  9. Start V2 encounter.
  10. Fix V2 Encounter as needed.
  11. Prefab V2.
  12. Start V3 Encounter.
  13. Fix V3 Encounter as needed.
  14. Prefab V3.
  15. Create an empty game object to act as an enemy spawner.
  16. Add an array with all of our prefabbed enemies.
  17. Make them spawn in random order.
  18. Make a new enemy spawn when the player reaches a new level.
  19. Make the final level.
  20. Make the Warden.
  21. Add Collider to Warden.
  22. Add Rigidbody to Warden.
  23. Code 1st phase of Warden.
  24. Code 2nd phase of Warden.
  25. End the game if the Warden dies.
  26. Create a “TRIAL COMPLETE” screen.
  27. Code the win screen.
  28. Add side bosses if I have extra time.
  29. Make side bosses drop lore puzzle pieces.
  30. Spawn side bosses ONLY in void cells.
  31. Spawn side bosses in random order.

Refresh HacknPlan

Proposed Budget

Composer/Sound Designer

PRODUCTION – ACTION

The (FILM, SOUND, or GAME Creation)

Skills Commentary

0:02 Updated Main Menu UI

0:05 New option to skip the tutorial

0:15 Collider allows the player to stick to walls

0:16 New dodge mechanic

0:18 Jumping feels floaty

0:27 Slow trial 1 AI

0:58 Reload mechanic

1:03 Win screen on guard death with updated UI

1:14 Known bug where the player can spam the dash ability in mid-air but must wait three seconds in between dashes otherwise

1:39 Boss flies upwards

2:08 Game over screen on player death with updated UI

2:16 Boss health text spawn when the guard spawns

4:03 Mali Matus is faster in phase 2

4:11 Mali Matus slows down when the player enters phase 3

4:15 There are no nearby walls to jump on and avoid the untouchable floor. I am working on this as of this writing.

4:20 Mali Matus was supposed to be invulnerable in phase 3, but it didn’t work in this demo.

4:38 I should create a skybox for situations like this

4:51 The walls turn red in phase 3 to warn the player that the floor is unsafe for them

5:40 Upon death, the boss text disappears, and the walls turn black again

5:46 There is also a portal that spawns near the wall closest to Mali Matus.

5:47 The portal currently takes you to the main menu, but I plan to add three more dimensions, all with their own final bosses

Another known bug that wasn’t shown in this video due to the bug somehow not appearing at all in my six-minute-long playthrough of dimension one, is sometimes the dodge will just not work at all. I have no idea whether this is being caused by the Unity editor, something in my code, or if this is a physics-related issue, but I can personally guarantee that I will delay this game as long as needed to fix this issue.

POST-PRODUCTION – REFLECTION

21st Century Skills

Ways of Thinking (Creativity, Innovation, Critical Thinking, Problem Solving)

Ways of Working (Communication & Collaboration)

Tools for Working (Info & Media Literacy)

Ways of Living in the World (Life & Career)

Reactions to the Final Version

Self-Evaluation of Final Version

What I Learned and Problems I Solved

Grammar and Spelling

Editor

Tower Defense AI

Notes:

  • 0:22 What you’ll be making.
  • 0:57 How a waypoint system works.
  • 1:17 Create an empty game object to store our waypoints and reset the transform.
  • 1:33 Create an empty game object for each waypoint you wish to make and make them all children of the waypoints game object.
  • 1:35 Give the waypoint objects gizmos to make them visible in the scene view.
  • 1:42 Place each waypoint at each checkpoint for the AI.
  • 2:13 Create a script to store our waypoints.
  • 2:24 Create a public array of type transform to store our waypoints.
  • 2:39 Back in Unity, drag and drop the script we just made on the parent game object of our waypoints.
  • 2:47 Lock the inspector and drag and drop all of the waypoints into the “Waypoints” array.
  • 2:56 Unlock the inspector and create a new script for our AI.
  • 3:07 Create a public variable of type float to dictate how fast the AI will move from each waypoint.
  • 3:21 Create a private variable of type Waypoint as a reference to our waypoints.
  • 3:32 In the Start function set the Waypoints variable equal to the Waypoints script from an object with the tag “Waypoints”.
  • 3:43 Create a new tag called “Waypoints” and give it to the parent object of our waypoints.
  • 4:08 Move the AI to the waypoint with index 0.
  • 4:19 Create a private variable of type int to store our waypoint index because hard coding as done above is not a great idea.
  • 4:24 Replace the 0 with the waypoint index variable.
  • 5:01 Check the current distance between the AI and the waypoint their currently traveling towards.
  • 5:13 If the AI has reached the current waypoint they’re traveling to, increment the waypoint index by 1.
  • 5:19 Drag and drop the script onto the character and type in a value for speed.
  • 5:32 The AI moves throughout the path, although a big fat error pops up when the AI is beyond the last waypoint.
  • 5:55 Check if the waypoint index has a value smaller than the number of elements in our “waypoints” array. Subtract the number of elements in the array by one because arrays start at 0 rather than 1.
  • 6:05 If the statement returns true, then keep incrementing the waypoint index by 1.
  • 6:17 If the statement returns false, meaning the AI reached the last waypoint, destroy it in an else clause.
  • 6:43  In the Update function, create a Vector3 for the AI’s direction and give the direction of the current waypoint the AI is going towards minus the AI’s position.
  • 6:51 Under that line, create a float variable for the angle the player is traveling at. Reference the time stamp for the syntax because there is no way I can explain that otherworldly beast of code.
  • 7:08 Now set the AI’s rotation to how many degrees the character should rotate and rotate on the Z-axis.

Stealth Enemy AI (Line of Sight)

Notes:

  • 0:12 What you’ll be making.
  • 0:41 Disclaimer
  • 2:07 Make a script called Enemy.

ROTATING THE ENEMY (OPTIONAL*)

  • 2:17 Make a public variable of type float for the speed the enemy will rotate at.
  • 2:36 Rotate the enemy on the Z-axis in the update function. (This is a 2D tutorial, but this is the only axis you can rotate a sprite on without flipping them).
  • 2:57 Drag and drop the Enemy script onto the enemy and type in a rotation speed.

ENEMY LINE OF SIGHT (REQUIRED)

  • 3:24 Create a Raycast Hit 2D Variable and set it equal to the Raycast method.
  • 3:43 In the parentheses, give the ray an origin (the enemy’s position), a direction (the enemy’s right), and a max distance (which will be set in the inspector).
  • 4:15 Check if the ray has collided with anything.
  • 4:55 In that if statement, draw a red line in the scene view for debugging purposes.
  • 5:21 In an else clause, check if the ray has not collided with anything, if such is the case, draw a green line at the enemy’s position plus their right multiplied by the ray’s max distance to match the ray’s position.
  • 5:31 Save and close the script. Back in unity set the ray’s max distance in the inspector.
  • 5:54 Add a non-trigger 2D collider to the player.
  • 5:59 Add non-trigger 2D colliders to the walls.
  • 6:09 Add a non-trigger 2D collider to the enemy character.
  • 6:26 In the Start function, make sure the ray doesn’t detect the enemy’s collider.
  • 6:46 Check if the ray has collided with an object with the “Player” tag. Nest this if statement in the if statement checking if the ray has collided with anything.
  • 6:58 Destroy the object the ray collided with. (This part is optional, you’ll usually want to do something else when the player’s spotted, but that’ll do for now)
  • 7:01 Add the player tag to the player. (You most likely already have it on him but now is as good a time as any to check)

MAKING A VISUAL FOR THE ENEMY’S LINE OF SIGHT (OPTIONAL**)

  • 8:11 Create an empty game object and add the line renderer component to it.
  • 8:32 Add the Sprite Default material to the line.
  • 8:40 Change the mode to fixed to prevent gradient colors.
  • 8:43 For now, choose a red color.
  • 8:47 Lower the line’s width.
  • 9:07 Create a public variable of type line renderer to store a reference to our line of sight visual.
  • 9:12 Back in Unity, drag and drop the line of sight object into the empty line renderer slot
  • 9:37 In the enemy script, in the else clause of the first if statement we made, set the line’s starting position to the enemy character’s position.
  • 9:57 In the first if statement, set the line’s end position to the ray’s point of contact.
  • 10:07 Back in the else clause, if we don’t hit anything we want the line to shoot out in the same direction as the ray.
  • 10:29 Create two public variables of type gradient, one for red and the other green.
  • 10:36 When the line, collides with something, set it equal to red.
  • 10:41 When the line doesn’t collide with anything, set it to green.
  • 10:46 Set both gradient variables to Fixed in the gradient editor. Remove all transparency from both gradients.
  • 10:48 Set the color of each gradient. Red to red and green to green.

2D AI Patrol

Notes:

  • 0:20 What you’ll be making.
  • 1:17 Placeholder Graphics. Graphics don’t matter for this tutorial as long as you can follow along and make the final product.
  • 1:32 Add a box collider to the platform.
  • 1:41 Create a new script called Patrol
  • 1:50 Delete the Start and Update functions and create a public variable of type float called speed.
  • 2:04 Create a private variable of type bool called moving right and set it equal to true.
  • 2:19 Make a public variable of type Transform called ground detection.
  • 2:26 Create an empty game object called ground detection.
  • 2:28 Add a gizmo to it to easily detect it in the Scene view.
  • 2:36 Make it a child of the patrolling AI.
  • 2:42 Place it in front of the character and slightly above ground level.
  • 2:46 We will be shooting out an invisible ray from this empty game object. If the ray no longer detects any collisions, the AI will move in the other direction.
  • 3:35 Move the AI forward.
  • 3:56 Create a RaycastHit2D below that line.
  • 4:01 Set it equal to Physics2D.Raycast.
  • 4:13 In the parentheses feed in the origin of the ray (ground detection), the direction our ray will travel in (downwards), and the distance of our ray (2f)
  • 5:03 Check if the ray has hit anything
  • 5:23 In that if statement, check if the player was moving right.
  • 5:46 If the AI was moving right and they’ve reached the edge, it’s time for them to face the opposite direction to move left.
  • 5:55 Below that line, set moving right to false.
  • 6:15 Add an else clause to that if statement to set the AI back to default rotation if it was moving left and set moving right back to true.
  • 6:27 Save and close the Patrol script. Drag and drop the ground detection empty in the empty Transform slot in the inspector.
  • 6:31 Type in some value for speed.