Explore Free FPS Tutorials – GameDev Academy https://gamedevacademy.org Tutorials on Game Development, Unity, Phaser and HTML5 Thu, 06 Apr 2023 04:57:25 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://gamedevacademy.org/wp-content/uploads/2015/09/cropped-GDA_logofinal_2015-h70-32x32.png Explore Free FPS Tutorials – GameDev Academy https://gamedevacademy.org 32 32 Best FPS Tutorials – Learn To Create A First-Person Shooter https://gamedevacademy.org/best-fps-tutorials/ Tue, 24 Jan 2023 10:03:45 +0000 https://gamedevacademy.org/?p=15483 Read more]]> Ask someone to name a video game, and chances are they’ll come up with a first-person shooter (FPS) series like Call of Duty or Halo. The FPS has been one of gaming’s most popular genres for many years, and so it’s only natural that many budding game designers will want to try their hand at creating their own.

To help out budding FPS developers, we’ve compiled some of the best FPS tutorials available to assist you in learning the basics of creating an FPS and expanding your skill set to take on more complex projects. 

Note that this list is intended for individuals – teachers may have better luck with platforms like Zenva Schools for helping to find teaching resources for the classroom.

Why Should I Learn To Make An FPS?

First-person shooters are some of the most popular games around, with huge franchises like Call of Duty, Battlefield, Halo, Apex Legends and more attracting millions of players with their fast-paced shooting action. As such, there’s a huge market for first-person shooters – so if you make your own, there’ll be no shortage of players for it!

Aside from their popularity, FPSs are also an ideal genre for beginner game developers to practice their skills and master a variety of different mechanics. Creating an FPS involves designing 3D environments, programming enemy AI, creating interactable items, coding player weapons, and more. FPSs are also a helpful backdrop for learning to animate and program 3D characters with simple behaviors, movements, and actions. 

In short, learning to make an FPS helps you pick up all manner of game design skills and systems along the way. Creating an FPS can therefore help beginners to learn a variety of fundamental game design skills while allowing more experienced developers to add new mechanics and systems to their skill set for use in later projects.

Best FPS Tutorials – Learn To Create A First-Person Shooter

The following list includes our top picks for FPS design tutorials that help you to learn about the fundamental systems and mechanics involved in the genre. 

Most of them are designed for beginners, requiring only a basic understanding of the relevant game engine or programming language. However, even more experienced coders will get a lot of use out of these tutorials, as they’re a great way of picking up FPS-specific skills that you might not have encountered before, allowing you to add new systems to other game projects in the future.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Construct A First-Person Shooter

If you’re looking for an entry-level introduction to the world of the FPS, then one of the best options is Construct A First-Person Shooter. This FPS tutorial from Zenva Academy provides a detailed, step-by-step guide to creating your very own FPS in the Unity game engine.

Across a series of video guides, you’ll learn various essential mechanics needed to create a fully-functioning shooter, such as player movement, power-ups, and weapons. You’ll also learn how to create pathfinding enemies that provide a solid challenge for players, helping to create an engaging and exciting experience even within your first game in the FPS genre.

All you need to get started is a basic understanding of Unity and C#, making this a perfect option for beginner coders who have learned the basics and want to make a start on their first real game project.

Key Topics Covered: 

  • Creating a player that can move, jump, shoot, and die
  • Mastering weapons and shooting with C# and object pooling
  • Implementing enemies that can pathfind using Unity’s NavMesh feature
  • Adding health and ammo pickups
  • Setting up audio and particle effects for firing weapons
  • Using Unity’s UI system to create health bars, ammo counters, and more

Duration:  Roughly 3 hours, 40 minutes of video tutorials.

How To Build Your First FPS Game

If you’re a complete beginner in game development and coding and you want an easily accessible entry point, then this official Unity tutorial could be the option for you. Led by two Unity Certified Instructors – Brian Kenney and Alexei Othenin-Girard – the How To Build Your First FPS Game tutorial helps you create your first FPS without even needing to code.

The tutorial uses Unity’s FPS Creator Kit as a starting point, which requires no coding and simply aims to teach beginner game devs about the various mechanics needed for an FPS. Part 1 provides a guide to setting up the Unity Creator Kit, an overview of the Unity Editor, a guide to designing a simple level, and instructions on creating your own prefabs.

Part 2 introduces further skills, showing you how to create interactable elements like locked doors and keys to control level progression, create endpoint triggers, customize weapons and build your complete FPS project.

Since this tutorial requires no coding, those looking for practical experience with Unity and C# may decide to look elsewhere. However, as an introduction to the FPS genre, this tutorial makes for a great place to start for complete beginners.

Key Topics Covered:

  • Setting up Unity and the Unity FPS Creator Kit
  • Using the Unity Editor
  • Designing a simple FPS level in a 3D environment
  • Creating your own prefabs
  • Adding interactable elements and pick-up items
  • Creating endpoint triggers
  • Customizing weapons

Duration: Part 1 lasts just over an hour. Part 2 lasts 57 minutes.

Unity FPS Tutorials

Another Unity tutorial series, this time provided by game dev YouTuber Fuelled By Caffeine, the Unity FPS Tutorials series provides beginners with a detailed guide to creating an FPS from the ground up. This ongoing series explains the process of creating an FPS step-by-step, with each video introducing new mechanics and systems to build into your game.

The tutorial series uses bite-sized videos of around 20 minutes in length to make it easy for beginners to master each concept, or for more experienced coders to jump in at specific points where they want to learn about a particular mechanic. 

As well as covering fundamental aspects of an FPS like player movement, aiming and shooting, this series also covers more advanced systems that can help your project appear more polished. For example, later videos explain how to add idle animations and weapon sway to make your player character’s movements feel more natural and realistic.

Key Topics Covered:

  • Setting up the input system
  • Camera and movement control, including crouching, crawling, sprinting and more
  • Gravity and jumping mechanics 
  • Idle animations and weapon sway 
  • Aiming down sights
  • Leaning mechanics 
  • Shooting

Duration: Currently a series of 21 videos totalling about 5 hours, 10 minutes, with further videos to be added over time.

Develop A First-Person Shooter In Unreal Engine

If Unity isn’t your cup of tea, then there are also plenty of great tutorials that explain how to create an FPS in other game engines. For example, there’s Develop A First-Person Shooter In Unreal Engine, which helps you to do exactly what it says on the tin. 

This tutorial demonstrates how to build an FPS from the ground up using the popular Unreal Engine, enabling you to expand your skills and experience with this platform while also learning the fundamentals of FPS game design. By the end of the tutorial, you’ll have created your own simple FPS game with animated enemies to challenge your players. 

This tutorial makes for a great entry-level project for learning the foundational skills of game design and various game mechanics which you can then implement in other action-oriented game projects. You’ll need a basic understanding of the Unreal Engine before starting, but the tutorial does a great job of walking you through the entire process of crafting your own FPS, so it’s very beginner-friendly.

Key Topics Covered:

  • Creating a first-person camera and player
  • Implementing bullets and shooting
  • Setting up animated enemies that chase the player
  • Developing logic for damaging characters
  • Building a UI with ammo and health information
  • Adding pickups for players to collect

Duration: Roughly 2 hours, 5 minutes of video tutorials 

Make A First-Person Shooter In Unity 

Yet another option for creating your own FPS in Unity is the Make a FIRST PERSON SHOOTER in UNITY tutorial from tutorialsEU. This is a 3-hour course that shows you how to make an FPS from scratch, and it’s an ideal starting point for beginner coders or those who are new to the genre. 

This tutorial provides you with a step-by-step guide to creating a simple FPS game of your own, covering a variety of crucial elements like map design, movement controls, and the user interface. You’ll most likely need some basic Unity and C# experience to follow along, but for beginners looking for their first FPS project, this is a great place to start.

Key Topics Covered:

  • Setting up Unity for an FPS project
  • Building your first shooter map
  • Creating and animating the player character
  • Movement control
  • Creating enemies, programming AI and setting pathfinding 
  • Weapons and raycast for shooting
  • Designing a gameplay loop
  • Creating the UI 
  • Creating a main menu 

Duration: Just under 3 hours, 40 minutes

Build A First Person Shooter With Godot

Another alternative for those who aren’t keen on using Unity for their game development projects is the Build A First Person Shooter With Godot tutorial. This tutorial teaches you to build your own FPS game with Godot, a free, open-source engine designed specifically for use by indie developers. Thanks to this background, the Godot course is perfect for creating an impressive FPS without needing tons of resources. 

The tutorial gives you a step-by-step introduction to the fundamentals of an FPS, providing detailed instructions at each stage to implement various key elements of the genre. These include programming enemy AI, moving your player, collecting powerups, and more. 

This is an excellent starting point for anyone interested in creating their own FPS, and also offers transferable skills in terms of manipulating and animating objects within a 3D environment. You’ll need some existing familiarity with Godot and its GDScript language, but the step-by-step guide makes it a perfect choice for novice game designers.

Key Topics Covered:

  • Creating a 3D environment players can navigate
  • Utilizing ammo and health variables with corresponding UI elements
  • Implementing a first-person camera for the player
  • Manipulating various 3D objects such as guns and bullets
  • Setting up shooting mechanics with in-engine settings and GDScript
  • Adding health and ammo pickups for the player to collect

Duration: Roughly 2 hours, 5 minutes of video tutorials

Conclusion

Creating your own FPS can be a highly rewarding experience that teaches you all manner of skills, concepts, and mechanics that you can apply to future projects, allowing you to create more diverse and complex games. It’s also a fun experience in and of itself, leaving you with your own FPS game to play and challenge others with.

So, if you’re ready to create your first FPS and develop new game design skills, start off with one of the tutorials above and have fun creating an exciting, challenging shooter of your very own! We’re sure that, given its sheer popularity, learning to develop FPS games will continue to pay off for years to come.

Are you an educator? Try out Zenva Schools – a K12 platform of online courses focused on coding for the classroom. Featuring tons of features from classroom management to reporting, Zenva Schools is a one-stop shop for teaching topics like game development.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Best Unity Visual Scripting Tutorials – Making a Game https://gamedevacademy.org/best-unity-visual-scripting-tutorials/ Sun, 22 Jan 2023 08:06:11 +0000 https://gamedevacademy.org/?p=15377 Read more]]> Coding from scratch is hard, and frankly, just not for everyone. However, this should not stop you from making the games of your dreams!

This is where we come to the topic of visual scripting. As the name suggests, visual scripting allows you to add game functionalities visually in various ways – usually without the necessity to code at all. As such, as long as you know how to structure an algorithm, you can build just about any kind of game you might want. Many visual scripting tools also have full access to their engine’s API, so you don’t have to worry about missing out on useful engine tools either.

In this article, we’re going to take a look at some of the best visual scripting tutorials for Unity. Not only will these tutorials help you get started with visual scripting in general, but also show you how to tackle specific projects with it.

If you’re ready to start building games without code, let’s get on with it.

About Visual Scripting and Unity

Just as a brief pause for complete newbies out there, we want to talk about the topic of visual scripting itself and how it presents in Unity. This way, if you’ve never used visual scripting or Unity before, you won’t be lost.

What is Visual Scripting?

As described above, visual scripting is all about “programming” visually. In the case of Unity, this is presented in the form of draggable blocks or nodes that can be added to a canvas/graph. Each node/block has a specific functionality tied to it, such as adjusting an object’s transform, changing variable values, and so forth. By attaching this functionality to an object, you can apply those functions to the object via the block, instead of needing to code it by scratch.

Additionally, and what makes visual scripting powerful, is that you can easily connect blocks together. Say for a character “dying” you want to deduct one life from them and move them to a designated starting position from them. In this case, you’d simply take a block that is set to subtract the life score and connect it to a block that moves the character’s position. Then, you simply trigger this sequence when the character dies – no coding required at all.

Visual Scripting in Unity

When it comes to the popular engine Unity, there are two ways in which we can utilize visual scripting. Note that while accessing the visual scripting tool is different, both still can utilize the same tutorials with some minor differences. As such, you don’t need to get too hung up on which tutorial applies to you.

Unity Bolt

Bolt is a Unity-developed package you can download for any Unity project on version 2018.4.15 or later – up until version 2021.1. This asset gives you a simple graph to work with that comes with visual scripting capabilities. Until recently, this has been long-established as the primary way to use visual scripting in Unity, and is tried and tested through the years.

Unity 2021.1 and Later

Given the success of Bolt, since Unity 2021.1, Unity has packaged visual scripting with the editor by default. While there have been some minor bug fixes and improvements, it operates much the same as Bolt does. However, because it’s bundled with the editor, there’s nothing extra to download. Thus, this is slated to become the new default standard for games made in Unity now.

Make games without Code? Visual Scripting! (Unity, Bolt)

Duration: 13 minutes

For those brand new to visual scripting and interested in Bolt for older versions of Unity, this beginner’s tutorial by Code Monkey has you covered.

This tutorial first shows you how to get Bolt set up for your project – including some useful settings that may come up during this setup process. You’ll also get some tips on how to use Bolt depending on your interest in C# coding from scratch.

After that, the tutorial covers many useful basics, from adding nodes to your visual scripting canvas, to working with regular coding features such as variables. You’ll even learn how to access Unity components such as the Rigidbody component. Thus, regardless of what you want to work on next, this tutorial will at least get your foot in the door.

LEARN NOW

Unity Visual Scripting Getting Started

Duration: 6 minutes

While the above tutorial covers Bolt, this short tutorial by Dave Carrigg covers visual scripting foundations for Unity versions 2021.1 and later.

The main focus of this tutorial is showing you how to access the built-in visual scripting system that comes with your Unity installation. This includes just the set up process itself, as well as how to add nodes to your graph. You’ll of course also learn a tiny bit about how to connect the various mechanic nodes together.

Though this tutorial is probably used best in combination with the tutorial above (as Bolt isn’t dissimilar for the node process itself), it will definitely get you started with visual scripting – especially if you’re coming from an older version of Unity.

LEARN NOW

How to Make a Game with Unity 2021 Visual Scripting (Bolt)

Duration: 57 minutes

In this Bolt tutorial series by Smart Penguins – GameDev, you’ll move past just getting your visual scripting set up and actually build a functioning game.

The project focus of this series is a simple ski slope like game where the player needs to dodge obstacles as they move forward and collect coins down a predefined, straight path. Through this, you’ll learn several aspects required for almost all games. This includes applying physics, detecting input, setting up levels, managing objects, creating UIs, and more – all with visual scripting, of course.

Though the game probably won’t win you any awards, its simplicity makes it perfect for beginners. Not only do you get to learn how to use visual scripting, but also explore the game development fundamentals needed to make Unity games in general.

LEARN NOW

3D Movement Animation w/ Bolt

Duration: 20 minutes

Created by Playing games faster – Mr. Johnny Roo, this Bolt tutorial focuses exclusively on 3D player movement.

This topic comes with two specific components. Of course, the tutorial absolutely covers visual scripting. So, you will learn how to set up inputs and all around affect your player’s transform properties to simulate movement.

However, the second component of this tutorial is a focus on animation. In general, most developers want there player object’s to animate signs of their movement. For Unity, this is achieved with its Animator system, which allows you to set up animations to be played, when they should play, and how they should transition between each other. This tutorial covers not only this set up for your 3D character, but how to access your animations with a visual scripting set up. Thus, you’ll get to move past primitives and create more dynamic characters.

LEARN NOW

How To Use Bolt State Machines In Unity

Duration: 12 minutes

For those who are interested in how state machines work with visual scripting this tutorial by Dapper Dino is a fantastic resource to get a jump start on them.

State machines, for those who don’t know, are models used to control object behavior. Essentially, with a state machine, you define a particular set of states an object can be in, such as chasing the player vs. idle. With these states, you then add specific behaviors the object should exhibit, and define how those states are triggered. This is useful for everything from Unity’s Animator to enemy AI.

This tutorial covers the basics of setting a state machine up with Bolt. You’ll learn to add nodes for the states themselves, attach the behaviors to them, and even various ways you can trigger your states. This is also covered at a very practical but theoretical level, so its simple to adapt this material to whatever you need your state machine for.

LEARN NOW

Input in Unity Visual Scripting

Duration: 7 minutes

Games are nothing without input, and this tutorial by NotSlot will help you with input via the visual scripting method.

There are various ways through which we can interact with games, from touch mechanics to simple mouse clicks. As such, visual scripting offers you many different nodes for detecting these inputs. This tutorial covers a few sets of those nodes, particularly focusing on keyboard input, mouse clicks, and how you can use them to move characters and similar.

However, this tutorial also makes sure to cover Unity’s old Input Manager, which lets you define your key bindings essentially. Thus, you’ll also gain the knowledge you’ll need to personalize your input setup for your project.

LEARN NOW

Easy Way to Make 2D Games with Unity – Unity Visual Scripting

Duration: 6 minutes

If you’re more into the prospect of making 2D games, or want to have a new game for your portfolio fast, this tutorial by Smart Penguins has you covered.

The idea behind this tutorial is to strip back all the complicated mechanics you might see in other genres and focus mainly on movement, item collection, and obstacles. In the case of this tutorial, you’ll make an arcade-like space shooting game where you can move your ship around, shoot randomly spawning asteroids, and collect the coins that they drop.

While not as focused on visual scripting itself, this simplistic tutorial does serve to help you with game development fundamentals and actually using your visual scripting skills to make complete game projects.

LEARN NOW

Bolt FPS Tutorial

Duration: 36 minutes

Created by 1909Games, this short tutorial playlist will do exactly as it’s titled: show you how to make an FPS using only visual scripting.

The series featured is divided into three parts. In the first part, you’ll learn how to set up your level and player. The second part covers shooting mechanics, and the third part covers making enemies that patrol. The end result is a nifty FPS prototype that didn’t require a shred of manual C# coding.

Though there are many types of games one can learn to make with visual scripting, learning to make FPS games come with a few advantages. First, it teaches you the mechanics of first-person cameras, which come with a lot of quirks and are good to know how to make – regardless of whether you’re using visual scripting or not. Second, it also forces you to learn things such as object spawning, AI, and more – all which are aspects used throughout other genres.

LEARN NOW

Unity Visual Scripting Recommended Practices

Duration: 22 minutes

This tutorial by Gorilla Tactics is a bit unique for tutorials on this list, as this one actually expects you to also want to use C# coding.

Although first impressions may lead you to think that you can ONLY use visual scripting in your project or ONLY use C# scripting, this is false. In fact, because they are completely compatible with each other, you can mix and match visual scripting setups with other aspects you code manually. As such, even if you are a C# coder, you can take advantage some benefits visual scripting can provide.

The video focuses on this exact subject and tries to convey two things about this topic. The first, and less obvious, is the advantages and disadvantages between these two methods of “coding” your game. The second, and more implied by the title, is the best way to combine visual scripting and C# so you’re making clean code and keeping your game running effeciently.

LEARN NOW

Unity Visual Scripting Tutorials

Duration: 1 hour, 20 minutes

This playlist by munchmo is perhaps the best one for those who are looking to dive deep into visual scripting, even with some more intermediate concepts.

In the first part of this series, you’ll simply get a short introduction into the most important nodes, such as On Start, On Update, and so forth. This way, you can jump into the second part of the series understanding some of Unity’s most important triggers.

The second part of the series is where the deep dive begins. You’ll learn a variety of things, from the basics of using visual scripting itself (including subgraphs), to implementing complicated structures for singletons or coroutines. It even covers concepts related to data management. So if you’re ready for some intermediate level stuff, this tutorial will help you take that plunge.

LEARN NOW

How To Make Local Multiplayer Games W/ Unity Visual Scripting + New Input System

Duration: 39 minutes

Last but not least, this tutorial by Megahertzs will teach you how visual scripting works within the confines of Unity’s new Input System.

While there have always been ways to access input data – as was even covered in a tutorial above – Unity’s new Input System takes this to the next level. With this Input System, the idea was to create a level of abstraction between the inputs and the actions in game. In so doing, this would offer developers more freedom in how they mapped their controls – and came with the added bonus that local multiplayer games would be easier to create as well.

As the title probably clued you in, this particular tutorial focuses on the local multiplayer aspect of this Input System in particular. You’ll learn primarily how to set up moveable characters that can be accessed at the same time with different control sets – with, of course, an emphasis on visual scripting to get the job done.

LEARN NOW

Parting Words

We’ve reached the end of our list, and now you have some of the best Unity visual scripting tutorials at your fingertips. While visual scripting is often considered an easier entry point than coding, don’t think there isn’t any hard work involved. However, with visual scripting, you can focus even more so on the exact mechanics you want for your game – and worry less about pesky C# syntax.

Of course, learning how to code in Unity is always an option later – as there are just as many tutorials on that topic. Nevertheless, visual scripting is a great option for those who just aren’t interested in that part. So, find what works best for you in that regard!

Regardless of your choice, we hope you explore even more visual scripting topics, and we wish you the best of luck.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
How to Create a First-Person Shooter in the Unreal Engine https://gamedevacademy.org/unreal-engine-fps-tutorial/ Fri, 03 Jun 2022 01:00:23 +0000 https://gamedevacademy.org/?p=11964 Read more]]> Whether you’re a fan or not, there’s no denying that first-person shooters are a popular game genre.  Thus, it can be beneficial to know how to make one, whether it’s just to round out your own skills or to create that FPS game idea you’ve had haunting your dreams.  It can be even more beneficial to learn how to do this with Unreal Engine, the popular and graphically stunning engine behind a ton of popular games.

In this tutorial, we’re going to show you how to create a first-person shooter game inside of the Unreal Engine. The game will feature a first-person player controller, enemy AI with animations, and various shooting mechanics.  We will also cover the Unreal Engine blueprinting system for the logic, so no other coding knowledge is needed.

So, without further ado, let’s start learning how to build an FPS with Unreal Engine!

Unreal Engine FPS game in GIF form

Project Files

There are a few assets we’ll be needing for this project such as models and animations.  You can also download the complete Unreal project via the same link!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Project Setup

Before we start though, it’s important to know that this tutorial won’t be going over the basics of Unreal Engine. If this is your first time working with the engine, we recommend you follow our intro tutorial here.

To begin, create a new project making sure to include the Starter Content. This should then open up the Unreal Engine editor. Down in the Content Browser, create four new folders.

  • Animations
  • Blueprints
  • Levels
  • Models

Unreal Engine Content Browser window

Next, download the required assets (link at the start of tutorial). Inside the .ZIP file are three folders. Begin by opening the Models Folder Contents folder and drag all the folders inside of that into the Models folder in the Content Browser. Import all of that.

Then do the same for the Animations Folder Contents. When those prompt you to import, set the Skeleton to mutant_Skeleton. The mutant model and animations are free from Mixamo.

Unreal Engine Import Options with mutant skeleton selected

Finally, drag the FirstPerson folder into the editor’s Content folder. This a is a gun asset that comes from one of the Unreal template projects.

Unreal Engine with FirstPerson folder added to Content Browser

Now we can create a new level (File > New Level) and select the Default level template. When the new level opens, save it to the Levels folder as MainLevel.

Unreal Engine with new level scene

Setting Up the Player

Let’s now create the first-person player controller. In the Blueprints folder, create a new blueprint with the parent class of Character. Call it Player. The character parent includes many useful things for a first-person controller.

Unreal Engine with Player blueprint added to content

Double click it to open the player up in the blueprint editor. You’ll see we have a few components already there.

  • CapsuleComponent = our collider
    • ArrowComponent = forward direction
    • Mesh = skeletal character mesh
  • CharacterMovement = movement, jumping, etc.

Unreal Engine components for Player object

We can start by creating a new Camera component. This allows us to see through our player’s eyes into the world.

  • Set the Location to 0, 0, 90 so that the camera is at the top of the collider.

Unreal Engine camera for FPS player

For the gun, create a Skeletal Mesh component and drag it in as a child of the camera.

  • Set the Variable Name to GunModel
  • Set the Location to 40, 0, -90
  • Set the Rotation to 0, 0, -90
  • Set the Skeletal Mesh to SK_FPGun
  • Set the Material to M_FPGun

Unreal Engine with gun object added for FPS

Finally, we can create the muzzle. This is a Static Mesh component which is the child of the gun model.

  • Set the Variable Name to Muzzle
  • Set the Location to 0, 60, 10
  • Set the Rotation to 0, 0, 90

We’re using this as an empty point in space, so no model is needed.

Unreal Engine Details for gun object

That’s it for the player’s components! In order to test this out in-game, let’s go back to the level editor and create a new blueprint. With a parent class of Game Mode Base, call it MyGameMode. This blueprint will tell the game what we want the player to be, etc.

In the Details panel, click on the World Settings tab and set the GameMode Override to be our new game mode blueprint.

Unreal Engine World Settings windows

Next, double-click on the blueprint to open it up. All we want to do here is set the Default Pawn Class to be our player blueprint. Once that’s done: save, compile, then go back to the level editor.

Unreal Engine with Default Pawn Class attached to Player

One last thing before we start creating logic for the player, and that is the key bindings. Navigate to the Project Settings window (Edit > Project Settings…) and click on the Input tab.

Create two new Action Mappings.

  • Jump = space bar
  • Shoot = left mouse button

Unreal Engine Action mapping for FPS

Then we want to create two Axis Mappings.

  • Move_ForwardBack
    • W with a scale of 1.0
    • S with a scale of -1.0
  • Move_LeftRight
    • with a scale of -1.0
    • D with a scale of 1.0

Unreal Engine Axis Mapping for standard movement

Player Movement

Back in our Player blueprint, we can implement the movement, mouse look and jumping. Navigate to the Event Graph tab to begin.

First we have the movement. The two axis input event nodes will plug into an Add Movement Input node, which will move our player.

Player Movement Event Manager blueprinting in Unreal Engine

We can then press Play to test it out.

Next up, is the mouse look. We’ve got our camera and we want the ability to rotate it based on our mouse movement. We want this to be triggered every frame so start out with an Event Tick node.

This then plugs into an AddControllerYawInput and an AddControllerPitchInput. These nodes will rotate the camera along the Z and Y axis’. The amount will be based on the mouse movement multiplied by 1 and -1. -1 because the mouse Y value inverts the camera movement.

Event Manager to rotate camera with Player

If you press play, you’ll see that you can look left to right, but not up and down. To fix this, we need to tell the blueprint that we want to the camera to use the pawn’s control rotation. Select the Camera and enable Use Pawn Control Rotation.

Camera Event Graph overview

Now when you press play, you should be able to move and look around!

Jumping is relatively easy since we don’t need to manually calculate whether or not we’re standing on the ground. The CharacterMovement component has many build in nodes for us to do this easily.

Create the InputAction Jump node which is an event that gets triggered when we press the jump button. We’re then checking if we’re moving on ground (basically, are we standing on the ground). If so, jump!

Jumping logic for FPS player in Unreal Engine

We can change some of the jump properties. Select the CharacterMovement component.

  • Set the Jump Z Velocity to 600
  • Set the Air Control to 1.0

Event Graph overview for character movement

You can tweak the many settings on the component to fine tune your player controller.

Creating a Bullet Blueprint

Now it’s time to start on our shooting system. Let’s create a new blueprint with a parent type of Actor. Call it Bullet.

Bullet Blueprint created in Unreal Engine

Open it up in the blueprint editor. First, let’s create a new Sphere Collision component and drag it over the root node to make it the parent.

Sphere collision shape added to bullet in Unreal engine

In the Details panel…

  • Set the Sphere Radius to 10
  • Enable Simulation Generates Hit Events
  • Set the Collision Presets to Trigger

Now we have the ability to detect collisions when the collider enters another object.

Details for Bullet in Unreal Engine

Next, create a new component of type Static Mesh.

  • Set the Location to 0, 0, -10
  • Set the Scale to 0.2, 0.2, 0.2
  • Set the Static Mesh to Shape_Sphere
  • Set the Material to M_Metal_Gold
  • Set the Collision Presets to Trigger

Gold metallic material added to FPS bullet

Go over to the Event Graph tab and we can begin with out variables.

  • MoveSpeed (Float)
  • StartTime (Float)
  • Lifetime (Float)

Then click the Compile button. This will allow us to now set some default values.

  • MoveSpeed = 5000.0
  • Lifetime = 2.0

Components for bullet blueprint in Unreal Engine

We want our bullet to destroy itself after a set amount of time so that if we shoot the sky, it won’t go on forever. So our first set of nodes is going to set the start time variable at the start of the game.

Event Graph for Bullet blueprint in Unreal Engine

Over time, we want to move the bullet forward. So we’ll have the event tick node plug into an AddActorWorldOffset node. This adds a vector to our current location, moving us. The delta location is going to be our forward direction, multiplied by our move speed. You’ll see that we’re also multiplying by the event tick’s Delta Seconds. This makes it so the bullet will move at the same speed, no matter the frame rate.

AddActorWorldOffset node for Bullet shooting logic

Connect the flow to a Branch node. We’ll be checking each frame if the bullet has exceeded its lifetime. If so, we’ll destroy it.

DestroyActor node for Bullet blueprint

All the bullet needs now, is the ability to hit enemies. But we’ll work on that once enemies are implemented.

Shooting Bullets

Back in our Player blueprint, let’s implement shooting. First, we need to create an integer variable called Ammo. Compile, and set the default value to 20.

Ammo component added in Unreal Engine

To begin, let’s add in the InputAction Shoot node. This gets triggered when we press the left mouse button. Then we’re going to check if we’ve got any ammo. If so, the SpawnActor node will create a new object. Set the Class to Bullet.

Spawn logic for bullet in Unreal Engine

Next, we need to give the SpawnActor blueprint a spawn transform, owner and instigator. For the transform, we’ll make a new one. The location is going to be the muzzle and the rotation is going to be the muzzle’s rotation. For the owner and instigator, create a Get a Reference to Self node.

Spawn location logic for bullet in Unreal Engine

Finally, we can subtract 1 from our ammo count.

Ammo subtraction logic for FPS Unreal Engine project

We can now press play and see that the gun can shoot!

Creating the Enemy

Now it’s time to create the enemy and its AI. Create a new blueprint with the parent class of Character. Call it Enemy.

Enemy blueprint created for Unreal Engine FPS

Inside of the blueprint, create a new Skeletal Mesh component.

  • Set the Location to 0, 0, -88
  • Set the Rotation to 0, 0, -90
  • Set the Skeletal Mesh to mutant

Enemy mesh settings in Unreal Engine

Select the CapsuleComponent and set the Scale to 2. This will make the enemy bigger than the player.

Unreal Engine with capsule collision box added

Next, let’s go over to the Event Graph and create our variables.

  • Player (Player)
  • Attacking (Boolean)
  • Dead (Boolean)
  • AttackStartDistance (Float)
  • AttackHitDistance (Float)
  • Damage (Integer)
  • Health (Integer)

Hit the Compile button, then we can set some default values.

  • AttackStartDistance = 300.0
  • AttackHitDistance = 500.0
  • Health = 10

Unreal Engine components for Enemy blueprint

Let’s get started. First, we want to be using the Event Tick node which triggers every frame. If we’re not dead, then we can move towards the player. Fill in the properties as seen below.

Enemy Event Graph logic for moving towards the player

Back in the level editor, we need to generate a nav-mesh for the enemy to move along.

  1. In the Modes panel, search for the Nav Mesh Bounds Volume and drag it into the scene
  2. Set the X and Y size to 1000
  3. Set the size to 500

You can press P to toggle the nav-mesh visualizer on or off.

Unreal Engine with nav-mesh visualized for Enemy

You can also increase the size of the platform and nav mesh bound. Back in the enemy blueprint, let’s make it so when the game starts, we set our player variable.

Event Graph with Player variable set

Finally, let’s select the CharacterMovement component and change the Max Walk Speed to 300.

Character walking movement with max walk speed circled

Back in the level editor, let’s increase the size of the ground and nav mesh bounds.

Unreal Engine editor showing navmesh bounds

Let’s set some default values for the variables.

  • AttackStartDistance = 300.0
  • AttackHitDistance = 500.0
  • Damage = 1
  • Health = 10

Enemy Animations

Next, is to create the enemy animations and have those working. In the Blueprints folder, right click, select Animation > Animation Blueprint. Select the mutant for our skeleton, then click Ok. Call this blueprint: EnemyAnimator.

Animation blueprint for enemy

Double-clicking on it will open up the animation editor. On the top-left, we have a preview of our skeleton. At the bottom-left, we have a list of our 4 animations. You can open them up to see a preview in action.

Unreal Engine AnimGraph window

What we want to do now, is in the center graph, right click and create a new state machine. A state machine is basically a collection of logic to determine what animation we currently need to play.

New State Machine node for AnimGraph

You can then double-click on the state machine to go inside of it. This is where we’re going to connect our animations so that the animator can move between them in-game. Begin by dragging in each of the 4 animations.

Animation assets added to Enemy State Machine

Then we need to think… If we’re idle, what animations can we transition to? All of them, so on the idle state, click and drag on the border to each of the three others.

Animation state machine with various connections

We then need to do the same with the other states. Make the connections look like this:

State machine with various other connections for enemy animations

In order to apply logic, we need to create three new Boolean variables. Running, Attacking and Dead.

Variables available for Enemy in FPS Unreal project

You’ll see that next to the state transition lines is a circle button. Double-click on the one for idle -> run. This will open up a new screen where we can define the logic of moving along this transition. Drag in the Running variable and plug that into the Can Enter Transform node. So basically if running is true, then the transition will happen.

Running variable node added for Enemy

Back in the state machine open the run -> idle transition. Here, we want to do the opposite.

NOT node to project state machine logic in Unreal Engine

Go through and fill in the respective booleans for all of the transitions.

While we’re at it, let’s double click on the Mutant_Dying state, select the state and disable Loop Animation so it only plays once.

Enemy dying logic added to state machine

At the top of the state screen is an Event Graph tab. Click that to go to the graph where we can hook our three variables up to the enemy blueprint. First, we need to cast the owner to an enemy, then connect that to a Sequence node.

Event Graph for enemy with animation nodes

To set the running variable, we’re going to be checking the enemy’s velocity.

Logic to check enemy velocity

For attacking, we just want to get the enemy’s attacking variable.

Logic to check if enemy is attacking

The same for dead.

Logic to check if enemy is dead

Back in the Enemy blueprint, select the SkeletalMesh component and set the Anim Class to be our new EnemyAnimator.

Enemy with Anim Class added in Unreal Engine

Press play and see the results!

Attacking the Player

In the Enemy blueprint, let’s continue the flow from the AIMoveTo component’s On Success output. We basically want to check if we’re not current attacking. If so, then set attacking to true, wait 2.6 seconds (attack animation duration), then set attacking to false.

Attack logic for enemy to attack FPS player

If you press play, you should see that the enemy runs after you, then attacks. For it to do damage though, we’ll first need to go over to the Player blueprint and create two new variables. Compile and set both default values to 10.

Unreal Engine components for Health

Next, create a new function called TakeDamage.

Logic to take damage for FPS Unreal Engine project

Back in the Enemy blueprint, create a new function called AttackPlayer.

Enemy logic for attacking the player in FPS

To trigger this function, we need to go to the enemy animation editor and double-click on the swiping animation in the bottom-left. Here, we want to drag the playhead (bottom of the screen) to the frame where we want to attack the player. Right click and select Add Notify… > New Notify…

Call it Hit.

Hit trigger added to enemy attack

Then back in the animator event graph, we can create the AnimNotify_Hit event. This gets triggered by that notify.

AnimNotify Hit node added to Event Graph

Now you can press play and see that after 10 hits, the level will reset.

Shooting the Enemy

Finally, we can implement the ability for the player to kill the enemy. In the Enemy blueprint, create a new function called TakeDamage. Give it an input of DamageToTake as an integer.

Inputs Details circled in Unreal Engine Event Graph

Then in the Bullet blueprint, we can check for a collider overlap and deal damage to the enemy.

Bullet blueprint checking for collider in Unreal Engine

If you press play, you should be able to shoot the enemy and after a few bullets, they should die.

Conclusion

And there we are!

Thank you for following along with the tutorial! You should now have a functional first-person shooter with a player controller and enemy AI – complete with animations and dynamic state machine!  Not only will your players be able to dash about the stage jumping and shooting at their leisure, but the health mechanics create a challenge to stay alive.  You’ve accomplished this and more with just Unreal Engine’s blueprinting system as well, learning how to control nodes to provide a variety of functionality.

From here, you can expand the game or create an entirely new one.  Perhaps you want to add more enemies, or create an exciting 3D level where enemies might be just around that shadow-y corner!  The sky is the limit, but with these foundations you have all you need to get started with robust FPS creation in Unreal Engine.

We wish you luck with your future games!

Unreal Engine FPS game project

]]>
How to Create a Roblox FPS Game https://gamedevacademy.org/roblox-fps-tutorial/ Wed, 14 Jul 2021 01:00:52 +0000 https://gamedevacademy.org/?p=14200 Read more]]> With this step-by-step tutorial, you’re going to learn how to create an exciting and action-packed Roblox FPS game complete with lobby, arena, scoreboard, and goal of getting 10 kills per round.

In addition, thanks to Roblox’s built-in multiplayer features, your game will be ready to be enjoyed by the millions of Roblox players in an instant – something becoming a necessity into today’s game industry!

If you’re ready to master building FPS games right in Roblox, let’s get started!

roblox fps game

Project Files

You can download the complete project here. Unzip the file and double-click RobloxFPS to open it up in Roblox Studio.

Note that this tutorial won’t be going over the basics, so if this is your first time developing in Roblox, I recommend you follow this tutorial first to learn Roblox game making fundamentals.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Creating the Lobby

Let’s start by creating a new Roblox game, using the Baseplate template.

Then in the Toolbox window, let’s look for a warehouse model to act as our lobby. This is the one I’m using.

creating the warehouse model

By default this warehouse doesn’t have collisions, so let’s go inside and add some parts to act as collider walls.

first collider wall

Cover all 4 sides of the inside.

collider walls

We can then select all of them and…

  • Set the Transparency to 1
  • Enable Anchored

Let’s also drag in the SpawnLocation object as we want our players spawning inside of the lobby room.

spawn location in lobby

Finally, we can create a folder in the workspace called Lobby, and put all of our lobby related objects in it.

Roblox Explorer for the Lobby

Creating the Arena

Now let’s create our arena. For this, let’s go over to the Toolbox and look for a “compound”. These normally have walls surrounding it with buildings inside – perfect for an FPS arena. This is the one I’m using.

creating the compound

We can also change the Baseplate to match the compound.

  • Set the Material to Sand
  • Set the Color to Bright orange
  • Delete the child Texture object

Roblox Properties Window for Compound Level

Next, let’s border up all the gaps so players can’t escape. Starting with the door, we can just rotate to close it.

Door object added to Roblox compound FPS level

We can do the same thing for the back entrance. Just copy and paste the doors there.

Door rotated to block players in Roblox FPS game

Now players should be blocked in and not able to get out.

Next up, are the spawn points. Go ahead and create a new SpawnLocation object inside of the Workspace and set it up how you like.

creating the arena spawn

Go ahead and copy/paste a lot of them around the arena.

Top down view of Roblox FPS arena

That’s our arena done! Let’s finish it off by creating a new folder called Arena and put all of the objects that relate to it, inside.

Roblox Explorer showing Arena level objects

Teams

The way we’re going to have players spawn in the lobby at the start of the game and in the arena afterwards is going to be done through teams. Players can be assigned a team and spawn locations too. So when a player respawns, they will spawn at their team’s designated ones. Down in the Teams service, create 2 new Teams.

  • Lobby, with a TeamColor of White.
  • Playing, with a TeamColor of Lime green.

The team color is what will differentiate the 2 teams.

creating the teams

Now let’s select all of our arena spawn locations and…

  • Disable Neutral
  • Set the TeamColor to Lime green

setting up the arena spawn location teams

Then for the single lobby spawn location…

  • Disable Neutral
  • Set the TeamColor to White

setting the lobby spawn location team

Game Loop

Now that we’ve got the lobby, arena and spawn locations setup, let’s create the game loop. Let’s start by creating a new script inside of the ServerScriptService service and rename it to GameManager.

game manager script

Then, inside of the ReplicatedStorage service, we’re going to create a few value objects to hold data.

  • Create a BoolValue and call it GameActive
  • Create a StringValue and call it GameStatus
  • Create an IntValue and call it KillsToWin
    • Set the value to 10.

int values

These are going to be used to hold data that we can change and refer to. Now let’s go over to the GameManager script and start with creating some variables.

local LobbyWaitTime = 5
local KillsToWin = game.ReplicatedStorage.KillsToWin
local GameActive = game.ReplicatedStorage.GameActive

local CurrentTime
local GameStatus = game.ReplicatedStorage.GameStatus

local LobbySpawn = workspace.Lobby.SpawnLocation

local Players = game.Players

local LobbyTeam = game.Teams.Lobby
local PlayingTeam = game.Teams.Playing

The LobbyTimer function will be called when players return to the lobby to await the next game. It will countdown from LobbyWaitTime, change the GameStatus string value to display the countdown. Then when the countdown is complete, it will set GameActive to true.

local function LobbyTimer ()
    CurrentTime = LobbyWaitTime

    while GameActive.Value == false do

        CurrentTime -= 1
        GameStatus.Value = "Game starting in... " .. CurrentTime	
		
        if CurrentTime <= 0 then
            GameActive.Value = true
        end

        wait(1)
    end
end

After this, we want to listen to when our GameActive BoolValue changes. When it does, we will either teleport players to the lobby or arena depending on if it’s true or false.

GameActive.Changed:Connect(function(value)
	
    if value == true then
        -- change all players team and respawn them
        for i, player in pairs(Players:GetChildren()) do
            player.Team = PlayingTeam
            player:LoadCharacter()
        end
		
        GameStatus.Value = "First to ".. KillsToWin.Value .. " kills wins!"
		
    elseif value == false then		
        -- change all players team and respawn them
        for i, player in pairs(Players:GetChildren()) do
            player.Team = LobbyTeam
            player:LoadCharacter()
        end
    
    end	
end)

Now to get things started, let’s call the LobbyTimer function at the end of the script.

LobbyTimer()

If you press play, you should spawn in the lobby and after 5 seconds spawn in the arena.

Game Status GUI

We’ve got the GameStatus string value setup and changing, but we can’t see what it’s saying in-game. So let’s create some GUI text.

In the StarterGUI service, create a new ScreenGui and inside of that, create a TextLabel. Rename it to GameStatusText.

game status text

Let’s now move the text over to the top-center of the screen.

  • Set the BackgroundTransparency to 1
  • Set the TextColor3 to white
  • Set the TextSize to 40

aligning text

Then under the ScreenGui object, we need to create a new LocalScript. This is a script that runs only on the local player’s computer.

ui local script

This script is just going to have two variables. One for the text object and the other for the GameActive value. Then we’ll change the text whenever the value of GameStatus has been changed.

local Text = script.Parent.GameStatusText
local GameStatus = game.ReplicatedStorage.GameStatus

GameStatus.Changed:Connect(function(value)
    Text.Text = GameStatus.Value
end)

Now if you press play, you should see the text counting down and when in the arena, displaying the kills to get.

First-Person Mode

Right now, you’ll notice that the player is still third-person. To fix this, select the StarterPlayer.

  • Set the CameraMode to LockFirstPerson
  • Set the CameraMaxZoomDistance to 0.5

starter player fps

Pressing play, the camera should now be locked in first-person mode.

Creating the Gun

With our player setup, let’s create our gun. Over in the Toolbox, search for Handgun and we want to find the Working Handgun model. Here’s a link to the asset. Drag that into the game and open it up, we’re going to modify it a bit.

Delete all parts except for…

  • The base Handgun tool.
  • The Handle and its sounds.

setting up handgun

Now we can create a local script for the gun called GunScript.

creating gun script

Before we write code, let’s go over to the ReplicatedStorage service and create a new RemoteEvent. A remote event can be used to communicate between the client and server. In our case, when the player shoots another player, we’ll be telling that to the server so they can damage them.

damage player remote event

Now back to our gun script. Let’s start with some variables.

-- Parts
local weapon = script.Parent
local camera = workspace.CurrentCamera

-- Sound Effects
local shootSFX = weapon.Handle["FireSound"]
local reloadSFX = weapon.Handle["Reload"]

-- Replicated Storage
local replicatedStorage = game:GetService("ReplicatedStorage")
local damagePlayerEvent = replicatedStorage:WaitForChild("DamagePlayer")

-- Damage
local Damage = 25

-- Ammo
local CurMagAmmo = 12
local MagSize = 12
local ReserveAmmo = 48

local CanShoot = true

Next, we can create the Shoot function which gets called when we press the left mouse button.

function Shoot (mouse)	

    -- play shoot sfx
    shootSFX:Play()

    local target = mouse.Target
    local humanoid = nil

    CurMagAmmo -= 1

    -- get the target HUMANOID
    if target.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent:FindFirstChild("Humanoid")
    elseif target.Parent.Parent:FindFirstChild("Humanoid") then
        humanoid = target.Parent.Parent:FindFirstChild("Humanoid")
    end

    -- if we hit a player, damage them
    if humanoid then
        local hitPlayer = game.Players:GetPlayerFromCharacter(humanoid.Parent)
        damagePlayerEvent:FireServer(hitPlayer, Damage)
    end	
	
end

The Reload function gets called when we need to reload our gun. Here’s what it does:

  1. Disable the ability to shoot.
  2. Play the reload sound and wait for it to finish.
  3. Enable the ability to shoot.
  4. Subtract from the reserve ammo.
  5. Set the current mag ammo.
function Reload ()

    CanShoot = false

    reloadSFX:Play()
    wait(reloadSFX.TimeLength)

    CanShoot = true

    local leftOverAmmo = CurMagAmmo

    if ReserveAmmo < MagSize then
        CurMagAmmo = ReserveAmmo 
    else
        CurMagAmmo = MagSize
    end

    ReserveAmmo -= MagSize - leftOverAmmo

    if ReserveAmmo < 0 then
        ReserveAmmo = 0
    end

end

Alright, now how do we connect these functions to actual interactions? When we equip the gun, we’ll attach a new event that gets called when we press the left mouse button. When that happens, we’ll either shoot, reload or do nothing.

weapon.Equipped:Connect(function (mouse)
	
    mouse.Button1Down:Connect(function()

        if CanShoot == true then
            if CurMagAmmo > 0 then
                Shoot(mouse)
            elseif ReserveAmmo > 0 then
                Reload()
            end
        end		
    end)	
end)

Now let’s test it out. But how do we give the player their gun? Well let’s drag it out of the Workspace and into the StarterPack. This is where we can give the players things when they join the game.

handgun placement

If you press play, you can test it out. After shooting 12 times, you should hear the reload sound.

Weapon Gui

In order to see our current ammo, we’ll need to create a gui. In the StarterGui, create a new ScreenGui object called AmmoGui and inside of that create a new TextLabel called AmmoText.

weapon gui text

Position and setup the ammo text to look like this:

ammo text placement

Now we’re not going to keep the gui inside of StarterGui. So let’s drag it over to ReplicatedStorage. This is because we need to clone and destroy it.

ammo gui

Back in the GunScript, let’s create two new variables.

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
local AmmoText = nil

PlayerGui is the container which holds all player gui at runtime. AmmoText is what we’ll assign when we create the gui.

Just below the variables, let’s create the UpdateAmmoText function. This will simply update the text to display the current ammo.

function UpdateAmmoText ()
	
    if AmmoText ~= nil then
        AmmoText.Text = CurMagAmmo .. "/" .. ReserveAmmo
    end
	
end

Down where we listen to the Equipped event, let’s add in code to create, assign and update the ammo text.

weapon.Equipped:Connect(function (mouse)

    -- NEW CODE STARTS HERE	

    local guiClone = game.ReplicatedStorage.AmmoGui:Clone()
    guiClone.Parent = PlayerGui
    AmmoText = guiClone.AmmoText

    UpdateAmmoText()

    -- NEW CODE ENDS HERE
	
    mouse.Button1Down:Connect(function()

        if CanShoot == true then
            if CurMagAmmo > 0 then
                Shoot(mouse)
            elseif ReserveAmmo > 0 then
                Reload()
            end
        end		
    end)
end)

Then we need to listen to when the weapon is unequipped and destroy the gui.

weapon.Unequipped:Connect(function()
	
    PlayerGui.AmmoGUI:Destroy()
	
end)

Finally, at the end of both the Shoot and Reload functions, we need to call the UpdateAmmoText function to update the text.

UpdateAmmoText()

Now you can press play and test it out!

Here’s the gun script as of this point in the tutorial:

-- Parts
local weapon = script.Parent
local camera = workspace.CurrentCamera

-- Sound Effects
local shootSFX = weapon.Handle["FireSound"]
local reloadSFX = weapon.Handle["Reload"]

-- Replicated Storage
local replicatedStorage = game:GetService("ReplicatedStorage")
local damagePlayerEvent = replicatedStorage:WaitForChild("DamagePlayer")

-- Damage
local Damage = 25

-- Ammo
local CurMagAmmo = 12
local MagSize = 12
local ReserveAmmo = 48

local CanShoot = true

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")
local AmmoText = nil

function UpdateAmmoText ()

	if AmmoText ~= nil then
		AmmoText.Text = CurMagAmmo .. "/" .. ReserveAmmo
	end

end

function Shoot (mouse)
	
	-- play shoot sfx
	shootSFX:Play()

	local target = mouse.Target
	local humanoid = nil

	CurMagAmmo -= 1

	-- get the target HUMANOID
	if target.Parent:FindFirstChild("Humanoid") then
		humanoid = target.Parent:FindFirstChild("Humanoid")
	elseif target.Parent.Parent:FindFirstChild("Humanoid") then
		humanoid = target.Parent.Parent:FindFirstChild("Humanoid")
	end

	-- if we hit a player, damage them
	if humanoid then
		local hitPlayer = game.Players:GetPlayerFromCharacter(humanoid.Parent)
		damagePlayerEvent:FireServer(hitPlayer, Damage)
	end
	
	UpdateAmmoText()
	
end

function Reload ()

	CanShoot = false

	reloadSFX:Play()
	wait(reloadSFX.TimeLength)

	CanShoot = true

	local leftOverAmmo = CurMagAmmo

	if ReserveAmmo < MagSize then
		CurMagAmmo = ReserveAmmo 
	else
		CurMagAmmo = MagSize
	end

	ReserveAmmo -= MagSize - leftOverAmmo

	if ReserveAmmo < 0 then
		ReserveAmmo = 0
	end
	
	UpdateAmmoText()

end

weapon.Equipped:Connect(function (mouse)
	
	local guiClone = game.ReplicatedStorage.AmmoGui:Clone()
	guiClone.Parent = PlayerGui
	AmmoText = guiClone.AmmoText

	UpdateAmmoText()
	
	mouse.Button1Down:Connect(function()

		if CanShoot == true then
			if CurMagAmmo > 0 then
				Shoot(mouse)
			elseif ReserveAmmo > 0 then
				Reload()
			end
		end		
	end)
end)

weapon.Unequipped:Connect(function()

	PlayerGui.AmmoGUI:Destroy()

end)

Leaderstats

Let’s now create the leaderboard to display kills, deaths, and wins.

In the ServerScriptService, create a new script called Leaderboard.

We also need to create what’s known as a BindableEvent inside of ReplicatedStorage. Call it WinGame.

win gam remote event

A bindable event is like a remote event, but instead of being client-server or server-client, a bindable event is just server-server.

Now in our Leaderboard script, let’s begin with some variables.

local GameManager = game.ServerScriptService.GameManager
local KillsToWin = game.ReplicatedStorage.KillsToWin
local WinGameEvent = game.ReplicatedStorage.WinGame

Then when a new player is added to the game, we can listen for that.

-- create leaderstats when a new player is added
game.Players.PlayerAdded:Connect(function(player)
	
end)

Inside of this event, let’s create our leaderstats folder and make it a child of our new player.

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player

Then as a child of this leaderstats folder, we need to create values for the kills, deaths, wins and attacker (the player who is currently attacking us).

local kills = Instance.new("IntValue")
kills.Name = "Kills"
kills.Value = 0
kills.Parent = leaderstats

local deaths = Instance.new("IntValue")
deaths.Name = "Deaths"
deaths.Value = 0
deaths.Parent = leaderstats

local wins = Instance.new("IntValue")
wins.Name = "Wins"
wins.Value = 0
wins.Parent = leaderstats

local attacker = Instance.new("ObjectValue")
attacker.Name = "Attacker"
attacker.Value = nil
attacker.Parent = player

Next, we need a way of changing these values when a player is killed. Add this code just under where we created our values but still inside of the player added event.

-- change leaderstats when a player dies
player.CharacterAdded:Connect(function(character)
    character:WaitForChild("Humanoid").Died:Connect(function()
        player.leaderstats.Deaths.Value += 1
			
        -- increase the killer's kills
        if player.Attacker.Value then
            local killer = player.Attacker.Value
            killer.leaderstats.Kills.Value += 1
				
            -- if the killer has enough kills, they win!
            if killer.leaderstats.Kills.Value == KillsToWin.Value then
                WinGameEvent:Fire(player.Attacker.Value)
            end
        end			
    end)
end)

What are we doing here?

  • When a player dies, increase their Deaths value by 1.
    • Increase their Attacker kills by 1.
    • If the Attacker has the KillsToWin call the win game event with the attacker as the parameter value.

Now if we press play, you should see the leaderboard at the top-right.

Damaging Players

We’ve already got the DamagePlayer remote event setup and calling in the gun script. Now we need to create a new script inside of ServerScriptService called PlayerDamageManager.

First, let’s get our variables. The replicated storage and damage event.

local replicatedStorage = game:GetService("ReplicatedStorage")
local damagePlayerEvent = replicatedStorage:WaitForChild("DamagePlayer")

Then we can listen to when the event has been called on the server. It will send over three values. The attacker, hit player and damage.

damagePlayerEvent.OnServerEvent:Connect(function(attacker, hitPlayer, damage)	
    hitPlayer.Attacker.Value = attacker
    hitPlayer.Character.Humanoid:TakeDamage(damage)	
end)

We can test this out with multiple players by going to the Test tab, setting the player number and clicking Start.

testing the Roblox FPS game

You should be able to shoot and kill other players. You can always increase the lobby wait time in the GameManager if the clients aren’t all in the arena.

Winning the Game

Let’s go over to the GameManager script. Here, let’s first set the player’s initial team to Lobby once they join the game.

-- called when a player joins the game
Players.PlayerAdded:Connect(function(player)
    player.Team = LobbyTeam
end)

Next, we need to create a variable to reference the win game remote event.

local WinGameEvent = game.ReplicatedStorage.WinGame

Now let’s also listen to the WinGame remote event. This gets called once a player reaches a certain amount of kills.

WinGameEvent.Event:Connect(function(winner)
    -- increase the winner's wins stat
    winner.leaderstats.Wins.Value += 1

    GameActive.Value = false
end)

This will increase the winner’s Wins and set GameActive to false. This will teleport players back to the lobby.

Conclusion

Congratulations on completing the tutorial! We just finished creating a Roblox FPS game from scratch – and learned quite a lot while doing so. We covered setting up a lobby and arena, how to make an FPS camera in Roblox, and even made a multiplayer-friendly leaderboard so every player can see where they stand.

From here, though, you can expand upon this game and skills in a lot of ways. For this project, you could strive to add new mechanics such as health packs, ammo packs, different weapons, etc. Or, if you want to try your hand at something, you can try making a first-person survival game. The sky is the limit with the systems set up here and they can easily be used for other games and genres!

Thank you very much for following along, and I wish you the best of luck with your future Roblox games.

]]>
Make Games without Coding – Free Unreal Engine Ebook https://gamedevacademy.org/make-games-without-coding-free-unreal-engine-ebook/ Mon, 28 Dec 2020 01:22:48 +0000 https://gamedevacademy.org/?p=2044 Read more]]> We are excited to announce our latest eBook: Unreal Engine Game Development for Beginners

Authored by Unreal Engine expert Daniel Buckley, this eBook explores all there is to know about getting started with Unreal Engine development. You’ll learn not only how to work with the foundations of the engine itself, but also develop several projects from scratch including an FPS game, an action RPG, a road-crossing game, a platfromer, and a puzzle-like game! In addition, you’ll do all this while using the Blueprints Visual Scripting system – meaning no prior coding knowledge is required or needed to create your game projects!

Whether you’ve always wanted to learn Unreal Engine or want to start putting knowledge into practice, this eBook will help you gain the in-demand skills necessary to start building your dream game projects!

Download the eBook here

]]>
Free eBook – Godot Game Development for Beginners https://gamedevacademy.org/free-ebook-godot-game-development/ Wed, 01 Jul 2020 08:09:57 +0000 https://godottutorials.pro/?p=3566 Read more]]> We’re overjoyed to bring you our latest eBook: Godot Game Development for Beginners.

With tutorials created by experienced game developer Daniel Buckley, this eBook will set you on an exciting path of 2D and 3D game development with the open-source Godot game engine.  You’ll learn to create platformers, RPGs, first-person shooters, and more as you dive into various mechanics and the engine’s personal scripting language, GDScript.

By the end, you will have gained in-demand skills for shooting mechanics, raycasting, level set up, player controllers, and more – all of which can be expanded and applied to your own game projects!

Download the eBook here

 

]]>
How to Create an FPS Player and Camera https://gamedevacademy.org/fps-player-camera-tutorial/ Fri, 19 Jun 2020 01:00:56 +0000 https://godottutorials.pro/?p=3503 Read more]]>

You can access the full course here: Build a First-Person Shooter with Godot

 

Creating The Player

In this lesson, we’re going to create our player object.

Let’s begin by creating a new scene. Go to Scene > New Scene.

Godot Scene window with New Scene selected

Click on ‘Other Node‘ and create a new Root Node of type KinematicBody.

Godot Create New Node window for KinematicBody

KinematicBody is a type of body that is not affected by physics, and it can only be moved by code or by an AnimationPlayer. It also has a built-in API for moving objects. For more information, visit the documentation: https://docs.godotengine.org/en/stable/classes/class_kinematicbody.html

We’ll rename the node to “Player” and save it as “Player.tscn”.

Next, add a child node (Ctrl+A) of type CollisionShape.

Godot Create New Node window for CollisionShape

In the Inspector panel, we can set the Shape property to ‘CapsuleCollider‘.

Godot Inspector with CollisionShape options

Select the Capsule in the Inspector, and set the Radius and Height to 0.5 and 1.5, respectively.

Godot with Capsule CollisionShape added

We’ll set the rotation degrees to 90 on the X:

Capsule collision shape rotated on the Y-Axis

We’ll also set the Y translation to 1.25 so that the collider just sits above Y zero.

Godot Capsule CollisionShape moved up

Next, we’ll add a new Child Node to the Player node (Ctrl+A) of type Camera.

Godot Create New Node window with Camera selected

Let’s set the position to be 2.5 so it can sit just above the player’s head.

Godot editor with camera set to player's head

We can click on the ‘Preview‘ button in the scene view to have a look through the camera/player’s perspective.

Preview button in Godot for the camera

Setting up the player weapon

First, we need to drag in the model of the weapon (Models > Weapon > Shotgun.obj) into the scene.

Shotgun Object added as child of Camera in Godot

The gun model should follow the camera around wherever we look. You can ensure that by setting the model as a child of the Camera object.

Godot Scene showing shotgun as child of Camera

We’ll rename the node to ‘GunModel‘ and set the translation to be (0.2,-0.2,-0.6), so the model is positioned at the right side of the screen when we look through the camera.

GunModel object with translation settings applied

Set the Scale to be (10, 10, 10) and rotation degrees to be (0, 180, 0) so it is facing the right way.

Godot transform settings for gun model

That’s it for the gun model setup. Now, let’s add a new child node of type Spatial for the gun muzzle.

Godot create new node window with spatial selected

Rename the node to “Muzzle” and position it at the muzzle of the gun model. (You can enable Orthographic View by pressing 5 on Numpad, and Top view by pressing 7.)

Gun positioning using the orthographic view

We’ll align it from the Side View as well (Press 3 on Numpad).

Side view of gun model in Godot

Let’s save the scene (Ctrl+S) and go back to our main scene. Drag in Player.tscn into the scene and place it at the centre of the scene by setting the Translation to be (0,0,0).

Player dragged onto Godot scene

Now, if you save the scene and press play.

Test play of Godot FPS with player

Scripting the Player – Variables

In this lesson, we are going to script our Player, so we can look/move around and jump.

Open up the Player scene that we created in the previous lesson. Select the root node and create a new script (Script > New Script).

Player in Godot with new script added

Setting up variables

First, we need to create variables of type integer to store our stats. We’ll assign the default values to our current health, maximum health, ammo, and score.

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

Now, we’re going to create some physics variables for moving and jumping.

extends KinematicBody


# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

We’ll create another float variable for look sensitivity. We also need variables to clamp the vertical rotation of our camera, so we can look 90 degrees up/down instead of 360 degrees.

extends KinematicBody


# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

We also need a Vector3 variable to store our current velocity, which includes x,y, and z position, and a Vector2 variable to track our mouse movement (both horizontal and vertical).

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

Now, we need to get components because our player node has separate child nodes for “GunModel” and “Muzzle” that we’ll be controlling in the script.

Note that the ‘onready‘ keyword is used to call the get_node() function once the node is initialized. This allows us to look through our node structure and find the target node.

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

# components
onready var camera : Camera = get_node("Camera")
onready var muzzle : Spatial = get_node("Camera/Muzzle")

Setting up key actions

To allow certain actions (e.g. move/jump/attack) upon key press, we need to define the keys in Project Settings > Input Map.

Godot Project window with Project Settings selected

Godot Project Settings with Input Map tab selected

You can create a new action by typing in the name and press the ‘Add‘ button.

Godot Project settings window with keys being added

Here is the list of key actions we need to create:

  • move_forward
  • move_backward
  • move_left
  • move_right
  • jump
  • shoot

We can then assign a key to the action by clicking on ‘+‘ on the right and then press ‘Key’.

Godot Project Settings with Key Assignment options

When the ‘Please Confirm…’ pop-up shows up, you can just press whatever key you want that to be assigned to and then hit OK.

Godot Key Assignment confirmation window

As you already know, the conventional FPS key settings are W,A,S,D to move, Space to jump, and LMB (Left Mouse Button) to shoot.

Final Godot FPS key movements

Once it’s all set up, close the window and save the project. Let’s open up our script again.

We now need to create a function that runs the physics. For this, we’ll be using the Godot’s built-in function ‘_physics_process(delta)‘, which runs at a consistent 60 frames per second.

func _physics_process(delta):

In the next lesson, we’re going to be adding more to this function (e.g. detecting inputs, moving the player, jumping, gravity, etc.).

Scripting the Player – Movement

In this lesson, we are going to add codes that will allow movement, jump and gravity.

The first thing we want to do is reset our x and z velocity because we want to stop moving once we let go of a button.

func _physics_process(delta):

	# reset the x and z velocity
	vel.x = 0
	vel.z = 0

Now we need to create a vector to check inputs for movement. This variable will be of type Vector2 as we will be moving along x-axis (left, right) and y-axis (forward, backward).

func _physics_process(delta):

	# reset the x and z velocity
	vel.x = 0
	vel.z = 0
	
	var input = Vector2()
	
	# movement inputs
	if Input.is_action_pressed("move_forward"):
		input.y -= 1
	if Input.is_action_pressed("move_backward"):
		input.y += 1
	if Input.is_action_pressed("move_left"):
		input.x -= 1
	if Input.is_action_pressed("move_right"):
		input.x += 1

At the moment, when we’re moving diagonally, we can move faster as the speed for movement on both axis adds up. We can prevent this by normalizing the vector, which means the magnitude of all the axis added together will equal one.

input = input.normalized()

Our next step is to get our forward and right directions because right now we’re only moving along the global x and z axes and not taking the player’s local rotation into consideration.

# get the forward and right directions
var forward = global_transform.basis.z
var right = global_transform.basis.x
	
var relativeDir = (forward * input.y + right * input.x)

the variable relativeDir will return a Vector3 which is the direction we’re going to move in. Now, we can pass this value back to our velocity vector as such:

# set the velocity
vel.x = relativeDir.x * moveSpeed
vel.z = relativeDir.z * moveSpeed

Applying Gravity

# apply gravity
vel.y -= gravity * delta

Applying gravity can be simply done by vel.y -= gravity. However, our root function ‘_physics_process(delta)‘ gets called 60 times per second, so it is not easy to guess what value would be ideal for our gravity.

Hence, we can multiply the gravity value by delta to convert it into ‘per second‘ rather than ‘per frame’.

Moving the Player

Finally, we can apply this velocity vector (vel) to the KinematicBody using a built-in function called move_and_slide().

# move the player
vel = move_and_slide(vel, Vector3.UP)

move_and_slide() moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately.

For more information, visit the documentation: https://docs.godotengine.org/en/stable/classes/class_kinematicbody.html

Adding in the ability to Jump

# jumping
if Input.is_action_pressed("jump") and is_on_floor():
	vel.y = jumpForce

First, we need to check if the jump key is pressed, using is_action_pressed(“jump”).

We also need to check if the player is on the floor, using is_on_floor(),  which requires move_and_slide() to be called first.

Now you can press WASD to move, Space to jump, and have gravity applied to us when we’re jumping. Here’s the complete script:

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

# components
onready var camera : Camera = get_node("Camera")
onready var muzzle : Spatial = get_node("Camera/Muzzle")

func _physics_process(delta):

	# reset the x and z velocity
	vel.x = 0
	vel.z = 0
	
	var input = Vector2()
	
	# movement inputs
	if Input.is_action_pressed("move_forward"):
		input.y -= 1
	if Input.is_action_pressed("move_backward"):
		input.y += 1
	if Input.is_action_pressed("move_left"):
		input.x -= 1
	if Input.is_action_pressed("move_right"):
		input.x += 1
		
	input = input.normalized()
	
	# get the forward and right directions
	var forward = global_transform.basis.z
	var right = global_transform.basis.x
	
	var relativeDir = (forward * input.y + right * input.x)
	
	# set the velocity
	vel.x = relativeDir.x * moveSpeed
	vel.z = relativeDir.z * moveSpeed
	
	# apply gravity
	vel.y -= gravity * delta
	
	# move the player
	vel = move_and_slide(vel, Vector3.UP)
	
	# jumping
	if Input.is_action_pressed("jump") and is_on_floor():
		vel.y = jumpForce

Scripting the Player – Camera Look

In this lesson, we’re going to focus on being able to look around with our camera.

First of all, we need to figure out how and where is our mouse moving. (i.e. What is the direction our mouse is moving in, and how far is it moving?)

We’re going to be checking that inside of a built-in function to Godot, which is called func _input(event).

func _input(event):

Whenever a keyboard input’s detected, the function gets called with the corresponding information sent over in the event parameter.

func _input(event):
	
	if event is InputEventMouseMotion:

If the event has something to do with the mouse, then we want to set mouseDelta as the direction that the mouse is moving in.

func _input(event):
	
	if event is InputEventMouseMotion:
		mouseDelta = event.relative

Now we’re going to use func _process(delta), which is another built-in function that gets called every frame.

func _process(delta):

We want to rotate the camera along the x-axis. The up and down of the mouse movement multiplied by lookSensitivity multiplied by delta, so it’s converted in terms of seconds for smoother movement.

func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta

Currently, we can rotate upwards until it loops back around, so our next step is to clamp the camera rotation on the x-axis.  For this, we will use float clamp(value, min, max), which is a function that clamps ‘value’ and returns a value not less than ‘min’ and not more than ‘max’.

func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
	
	# clamp camera x rotation axis
	camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)

Now, we need to set up rotating left and right, using the same method we just used for the x-rotation.

func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
	
	# clamp camera x rotation axis
	camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
	
	# rotate the player along their y-axis
	rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta

Finally, we go reset the mouseDelta vector so that we don’t keep looking in the direction that the mouse is moving.

func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
	
	# clamp camera x rotation axis
	camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
	
	# rotate the player along their y-axis
	rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta
	
	# reset the mouseDelta vector
	mouseDelta = Vector2()

Here is how the script should look so far:

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

# components
onready var camera : Camera = get_node("Camera")
onready var muzzle : Spatial = get_node("Camera/Muzzle")

	
func _physics_process(delta):

	# reset the x and z velocity
	vel.x = 0
	vel.z = 0
	
	var input = Vector2()
	
	# movement inputs
	if Input.is_action_pressed("move_forward"):
		input.y -= 1
	if Input.is_action_pressed("move_backward"):
		input.y += 1
	if Input.is_action_pressed("move_left"):
		input.x -= 1
	if Input.is_action_pressed("move_right"):
		input.x += 1
		
	input = input.normalized()
	
	# get the forward and right directions
	var forward = global_transform.basis.z
	var right = global_transform.basis.x
	
	var relativeDir = (forward * input.y + right * input.x)
	
	# set the velocity
	vel.x = relativeDir.x * moveSpeed
	vel.z = relativeDir.z * moveSpeed
	
	# apply gravity
	vel.y -= gravity * delta
	
	# move the player
	vel = move_and_slide(vel, Vector3.UP)
	
	# jumping
	if Input.is_action_pressed("jump") and is_on_floor():
		vel.y = jumpForce
		
		
func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
	
	# clamp camera x rotation axis
	camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
	
	# rotate the player along their y-axis
	rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta
	
	# reset the mouseDelta vector
	mouseDelta = Vector2()

func _input(event):
	
	if event is InputEventMouseMotion:
		mouseDelta = event.relative

Now, if you save the script and hit Play, you’ll notice that you can look left, right, up, down. But once the mouse leaves outside the game window, it doesn’t continue to track.

What we need to do is lock the mouse cursor in the middle of the screen and hide it, so the cursor doesn’t go off the screen.

To do so, we’re going to call func _ready() at the top of the script. _ready() is a function that gets called once the node is initialized, so this should be called right at the start of the game.

func _ready():

We’ll be using .set_mouse_mode to lock and hide our mouse using one of these options:

  • MOUSE_MODE_VISIBLE — Makes the mouse cursor visible if it is hidden.
  • MOUSE_MODE_HIDDEN — Makes the mouse cursor hidden if it is visible.
  • MOUSE_MODE_CAPTURED — The mouse will be hidden and unable to leave the game window.
  • MOUSE_MODE_CONFINED — Makes the mouse cursor visible but confines it to the game window.
func _ready():
	
	# hide and lock the mouse cursor
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)	

Save the script and hit Play. You will now see that the mouse is hidden. You can press Alt+4 to close the game window. Here is the final script:

extends KinematicBody

# stats
var curHP : int = 10
var maxHP : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 10.0

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

# components
onready var camera : Camera = get_node("Camera")
onready var muzzle : Spatial = get_node("Camera/Muzzle")

func _ready():
	
	# hide and lock the mouse cursor
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)	
	
func _physics_process(delta):

	# reset the x and z velocity
	vel.x = 0
	vel.z = 0
	
	var input = Vector2()
	
	# movement inputs
	if Input.is_action_pressed("move_forward"):
		input.y -= 1
	if Input.is_action_pressed("move_backward"):
		input.y += 1
	if Input.is_action_pressed("move_left"):
		input.x -= 1
	if Input.is_action_pressed("move_right"):
		input.x += 1
		
	input = input.normalized()
	
	# get the forward and right directions
	var forward = global_transform.basis.z
	var right = global_transform.basis.x
	
	var relativeDir = (forward * input.y + right * input.x)
	
	# set the velocity
	vel.x = relativeDir.x * moveSpeed
	vel.z = relativeDir.z * moveSpeed
	
	# apply gravity
	vel.y -= gravity * delta
	
	# move the player
	vel = move_and_slide(vel, Vector3.UP)
	
	# jumping
	if Input.is_action_pressed("jump") and is_on_floor():
		vel.y = jumpForce
		
		
func _process(delta):
	
	# rotate the camera along the x axis
	camera.rotation_degrees.x -= mouseDelta.y * lookSensitivity * delta
	
	# clamp camera x rotation axis
	camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
	
	# rotate the player along their y-axis
	rotation_degrees.y -= mouseDelta.x * lookSensitivity * delta
	
	# reset the mouseDelta vector
	mouseDelta = Vector2()

func _input(event):
	
	if event is InputEventMouseMotion:
		mouseDelta = event.relative

In the next lesson, we’re going to focus on setting up the ability to shoot bullets.

 

Transcript

Creating The Player

Welcome back, everyone. In this lesson, we’re gonna begin to create our player object. This is going to be the player scene, which is gonna hold the player, it’s collider and the camera. And from there we’re gonna begin scripting the player.

So to begin let’s go up to Scene here and we’re gonna create a new scene. It’s gonna be of type kinematic body right here. Now this is very similar to the 2D kinematic body, which basically allows us to have some sort of physics interactions. It allows us to move along surfaces, collide with various different things. It’s really good for characters and character controls pretty much.

So I’m gonna rename this here to player. I’m gonna save it as, player.tsen and as a child of this node, we’re gonna be creating, first of all, a collider. So we’ll just look up a collision shape right here. And this is gonna be basically the sort of size of the player what they can collide with. So we’ll set a shape here to be a new capsule shape right here. Right now, it’s a bit odd. So what we’re gonna do is we’re gonna select the capsule shape. We’re gonna set the radius to 0.5 and the height to 1.5 Now we need to rotate it and position it. So in the transform drop down here, we’re gonna set the rotation degrees to 90 on the X. So it’s vertical now and actually 1.25 on the Y translation, so it is just sitting above Y zero right here.

Okay, great. So we got our player right here. Now what we need to do is add in the camera and the camera is going to be what we see through the player’s eyes, we’re gonna then be able to move this camera around with our mouse. So for the camera, I’m gonna right click on player, add child node and we’re gonna add in a camera right here. By default, it’s positioned down its feet. We’re going to be a bit higher up so I’m gonna set the Y position of the camera here, the Y translation to be 1.5. We want it to actually be 2.5, so it is sitting just above the player’s head right here and looking outwards. And in fact we can click on the preview button right here in the scene view to have a look through the camera and through the player’s eyes.

All right, great. So we got that, we got the camera set up. Now what we need to do is set up the player’s weapon. We need to set up the weapon that the player is gonna have on their screen so we can see what we’re holding onto and to do that we’re gonna open up our model’s folder here, weapon and I’m gonna drag in the shotgun.obj. Make sure it is gonna be a child of the camera object because when we do look around, we do want the gun model to follow the camera around wherever we look.

Okay. So we select the model. I’m gonna rename this here to be our gun model. Now in the inspector, I’m gonna set the translation to be zero, zero, zero, so it is nice and centered here. You might notice it’s also pretty small. So what we need to do is increase the scale a bit. I’m gonna set the scale here to maybe five by five by five. That’s still a tiny bit small, so let’s actually increase it to 10 by 10 by 10. We’ll set the Y rotation degrees to 180, so it is flipped around and facing the right way here and then what we can do is drag it forward a bit. Maybe move it down a bit, move it to the right a bit, and let’s look through our camera.

So I’m gonna select the camera here, click on preview, and there we go, we got a gun model. Now let’s just reposition it a bit so it’s in a bit of a better position. All right, so I’m gonna set the X translation here to be 0.2 I’m gonna set the Y here to be zero, which is a bit high so maybe -0.5 nope, we’ll probably wanna make that -0.2. There we go and Z we’ll put that -0.6, something like that. So here we go, we got our gun model. we got that pointing outwards and we are also in needing to create a new node, which is a child of the gun model. Actually it doesn’t have to be the child of the gun model. In fact, we are just gonna make it a child of the camera.

So right click on camera, go add child node and this is just gonna be a spatial node and this is gonna be for the gun muzzle. So where are we gonna be spawning the bullet to then shoot? Okay. So, this spatial here, I’m gonna rename it to muzzle and we want to position it basically just at the muzzle of the gun here. Now with this view, it’s kinda hard to orientate yourself.

So what we can do in Godot is have some automatic orientations applied to the camera here, the scene camera, and for that you do need Numpad, so, make sure on your Numpad, you have Numlock turned on so you have the light with the Numlock on and then I’m gonna press seven to have above view right here and what we’re gonna do with the muzzle is drag it forward a bit and in fact right now we’re in perspective view, you can see that things change perspective as we zoom in, but if we press five we’ll go into orthographic mode so that there is no depth shown.

So what I’m gonna do here is hold down shift and with middle mouse we can pan across like this. I’m gonna position this right about here, there we go. We can then press one to get a side view and actually we’ll press three to get this side view and then drag that down to line it up, luxor. You can press five to get out of the orthographic mode and there we go, we got our gun model, we have the muzzle and everything here should be ready to go.

If you go back into the main scene now, what we can do is drag in our player.tsen into the scene, set the transform here to be zero, zero, zero. They should be standing in the middle of the field here and they should be standing on top of the surface here. Now if we press play, you’ll notice that it says no main scene has been defined. So we’ll select the main scene right here, press play, and there we go. We got our camera, we got our gun model here and we’re ready to begin scripting. But before we do that it’s good practice to actually go to our player here, select the camera and enable current right here. Just in case you do have multiple cameras in the scene, it’s good to basically tell the game that this here is the camera we want to use.

So there we go. Thanks for watching and I’ll see you in the next lesson.

Scripting the Player – Variables

Welcome back everyone, in this lesson we are gonna begin to script air player, we gonna have the ability to look around via camera, move around as well, and jump and have gravity applied to us, we’re gonna create a first person controller here in Godot. So, in the previous lesson we set up air player scene right here, I’ll just open it up, we set up a kinematic body as air an air, then a collate, a camera and as a child of the camera we have the gun model and the muzzle where the bullets are gonna come out.

So we got that all set up, now what we need to do, is select the player node here and we are going to create a new script here in the inspector and this script we’ll just keep it called player by default. Okay, so we got the script right here, up and ready to go, so the first thing I wanna do is create a variable. First up, let’s create some start song and then separate these by, some comments and a comment you can just go hashtag and then write whatever you want, these won’t get compound with the code as these are just for us to see.

So first up, we’re gonna have some stats that we’re not really gonna be working with just yet but we’ll be needing them later on. So first up, we have our CurHp for our current health and that is gonna be of top integer and by default that will equal 10. We also need a maxHp to know how much health can go up to, that will also be an int of 10 by default. Then we got our ammo, which is int again and we’ll have that at 15 and we have a score which we’ll have as an int and that will be zero by default.

So we’re not going to be using these values just yet, instead, we’re gonna be going down here and we’re gonna create some physics variables, and these are going to be with the actual movement jumping and gravity. So first up we have a moveSpeed, of top float so we want very precise numbers we can have decimals and partifoar we gonna have this equal five, then we want to have a jump force, so how much force is applied upwards when we wanna jump, that is gonna be of top float again and we’ll have that as five by default. And then we also wanna have the gravity, which is also gonna be float, and this is going to be a… We’ll have it at around 12, we can tweak this depending on, if it’s a bit too strong or if it’s a bit too weak.

Okay, so we got that? As well as this goes I need some variables for a camera looking. So with our camera, so just look at Cam look here, we need to figure out what is the maximum angle we can look upwards and what is the maximum angle we can look downwards because we don’t want to be able to look up and down and just do a 360 that way, we want to sort of clamp the vertical rotation, so here we’ll have var for minLookAngle of top float, and this will equal negative 90.

Also have a max look angle, so maxLookAngle of top float and this will equal 90 as well so we can look 90 degrees up and 90 degrees down. Along with this we’ll also need a look sensitivity because when we are moving a mass around it might be a bit too slow or a bit too fast, so we do want to be able to change the speed at which we look around, so we go var and this will just be lookSensitivity of top float and this will equal 10.

So we got those set up as well as this you will also need some vectors. We need to store our current velocity and the massDelta which is basically how far, in which direction has the mass moved in the previous frame. So we’ll just have our vectors here, and these are going to be first of all var for vel for velocity is gonna be of top vector three so we’re storing a x, y and z-position because we are moving around in 3D space, so our velocity can be in any direction. And by default we’ll just make this a new empty vector three like so, and we also want the mouseDelta, now since the mouse only works on two axes, horizontal and vertical, we only need to have a vector two for this so is giving me old type vector two and we’re gonna make it a empty vector two by default, there we go.

So, look that here, now what we need to do is actually get components because our player node right here we have a few things that we need access to such as the camera and the muzzle. We need to know where the muzzle is in order to spawn bullets and we need to know what the cameras is in order to move it around. So am just gonna go here components, and we’re gonna have a var camera which is gonna be of type camera and we won’t be able to access this once the game starts.

So am gonna switch this variable over to an on ready variable, which basically means whatever is after this equal sign here will be called once this node here is initialized, and this allows us to basically look through air node structure and find the camera so we can get underscore node and then we can just search camera and it is gonna get the camera node that it finds.

Now we also need to get the muzzle so we can go on ready var muzzle is gonna be of type spatial because this here is just gonna be an empty node and this is gonna equal get underscore node. Now we need to get the node path to that node, now it is a child of camera. So first of all we need to enter in camera, slash muzzle, there we go, so that’s how we access the muzzle node right here. And with all that setup lets actually go ahead press play, make sure there’s no errors with any of these on ready variables right here so we press play and we are all good there’s no errors popping up here so we can exit out of this.

And from here we’ve got all our variables, now what we can do is actually start and setting up air Physics setting up air movement, setting up air jumping, air gravity and looking around with the mouse.

So first of all before we actually jump into that, what we need to do is set up air actions, air key actions, because right now the game doesn’t really know what move left, move right, move forward, move back means, it doesn’t know what the attack button is, it doesn’t know what the jump button is, so we need to define these things inside of Godot here. And to do that we can go over to project, project settings, input map and over here is where we can enter in air new actions.

So first up we gonna have one action, this is is gonna be move underscore forward, press enter to add it to the actions here, we also want move underscore backward, backwards, move underscore left, move underscore right we also then want jump and we want shoot. So we got these six new actions here and what we want to do is assign a key to it, ’cause right now they got no keys, you can see some of these other actions here.

There are default and Godot do have actions or do have keys corresponding to that action, so if we move forward lets click on the plus icon right, to its right select key and the we can just click on whatever key we want that to be assigned to. So to move forward I’m gonna set it to W, press okay, move backwards we gonna set that to S, move left we’ll set that to A, move right here can be D, jump we’ll have it as Space, and shoot here is gonna be a mouse button so am gonna click on the plus choose mouse button and as you can see by default it is left button right here you can choose from all the very several mouse buttons.

Device, with device here it doesn’t really matter what you select, you can select device zero but am just gonna select all devices, just to make sure, because there’s no multiple controllers in this game so all devices is just the safe way to go, click add and there we go, we got our move forward, backwards left, right, jump and shoot actions all set up ready to go so we can start detecting them inside of our script.

So click close right here, and what we gonna do now is, actually start to create air function which is going to run the physics, and this is going to be the underscore Physics underscore process function. So let’s create it right here, so am just gonna go func underscore physics and what you should see is it automatically pops up with a selection we can just enter, and it creates the physics process function, now this function is built into Godot, most specifically it’s built into air player’s kinematic body node right here, which we are extending from at the top, so we do have those attributes we can access and this function gets called 60 times a second. This is a consistent update function.

Now Godot also does has the default underscore process function which gets called every single frame, but doing physics in the process function at times might not be the best because that is not a steady call right, that gets called as many times as you have frames per second so you might be fluctuation between 60, 100, so the process function can be called any number of times during a second, where as the physics process function gets called at a consistent 60 frames per second, which is good for physics as you don’t want variations in the time step.

So we got the physics process function right here and we gonna be doing a number of things here, and we’ll be doing a number of things here such as detecting inputs, moving the player, jumping, having gravity being applied to us, and we’ll be working on that in the next lesson.

Scripting the Player – Movement

Welcome back, everyone, in the previous lesson we start to create our player script right here. We entered in all of our variables we’re gonna be using for now, and we also created the physics_process function which gets called 60 times a second. Now, there is gonna be an error right now because we don’t actually have anything in the function, so, it’s got some problems with it being empty, but let’s go fill it in.

So, first of all, what we want to do is reset our x and z velocity of this velocity vector right here because when we let go of a button, we don’t wanna continuously be moving in the same direction as when we were holding a button down, so, we wanna stop once we let go of a button, and the reason why we’re not resetting the vector as a whole is because we want to maintain the y velocity, because if we’re falling and we let go of a button, we don’t all of a sudden wanna reset our y velocity, we wanna keep falling down.

So, here we’re gonna reset the x and z velocity and to do that we’re just gonna go vel.x = 0 and vel.z = 0. Now what we need to do is create a new vector to basically get our inputs, because what we’re gonna do is we’re gonna be checking if we press WASD, and these keys are gonna correlate to moving forward, if we’re moving back, if we’re moving left, if we’re moving right, and we’re gonna store that in a temporary variable which is gonna be a Vector2. So, we’re gonna go var input = Vector2.

So, I’m gonna be storing the left, right, and up, and down, inputs in this vector right here, and we’re gonna do that in movement inputs. So we’re gonna be checking, first of all, if we’re pressing the forward button. So, if Input.is_action_pressed, every frame that this action is being held down, this is going to be true, so, we wanna check for move_forward, colon at the end, and what we’re gonna do if this is true then we’re gonna set input.y -= 1, but right now if we press move_forward, y is gonna be -1.

Now, we need to do this for all four movement axes, so, then we can go if Input.is_action_pressed and we wanna check for move_backward, then we are gonna go input.y += 1. As well as this, then, we need to check the left, right, then we’re good. So, I’m just gonna copy this right here and paste this twice more. We’ll check move_left and then move_right, like so. If we’re moving left, we want to go on the x-axis and go -= 1, and if we’re moving right, we want it to go += 1 on the x-axis. So, we’re gonna have movement inputs and this input vector here is being changed depending on which buttons we have held down.

Now what we need to do is normalize this vector, and what normalizing it does basically means that the magnitude or the total of all the axes added together will equal one. And the reason why we’re gonna do this, especially for a character controller, a player controller, is because if we were holding down, let’s just say the forward and right button, we’re gonna be moving at a diagonal angle, and this movement is actually gonna be faster than if we were just moving forward or backwards, or left or right. If we’re moving at an angle, by default, it is gonna move us faster, so we want to normalize this vector, so, no matter which direction we’re moving in, it is always gonna be the same speed. To do that, we’re just gonna input = input.normalized.

Now that we have our inputs set up and ready to go, what we’re gonna do is get our forward and right directions of our player. We wanna know which way is our forward direction and which way is our right direction, and we’re gonna need these in order to actually figure out which way should set our velocity, because right now if we just set our velocity, it’s not gonna take into consideration, which way we’re looking. It’s gonna move us along the global x and z axes.

So, what we need to do is we need to get the forward and right directions, and to do this, we are gonna create a variable here called forward, and this is gonna be equal to our global_transform. So, we’re getting our global properties instead of our local properties because local might be different, depending on if we’re a child of another object, so we’re getting the global_transform.basis.z. So, this returns us the direction we are looking forward. Now, to get the direction were looking towards, or, not direction we’re looking, but the direction to our right, which we need for moving sideways, we’re gonna go var right = global_transform.basis.x.

So, now that we have our forward and right direction what we can do now is create a new vector which is gonna store the relative directions. So, this is what we’re gonna be, then, assigning to our velocity in order to move in the direction we are facing. So, I’ll create a new var for our vector which is going to be called relativeDir here, and this is gonna be equal in parentheses here. We’re gonna do a bit of a calculation to figure out which way we’re facing with our forward and right direction, as well as our input here which we’re gonna be using to figure out which we’re gonna be moving.

So, we’re gonna go forward * input.y + right * input.x and this is gonna give us a Vector3 which is gonna be the direction we’re gonna move in. So, we got that, now what we need to do is set the velocity. Now, with our velocity vector, we don’t wanna set the x, y, and z, we just wanna set the x and the z, because the y is gonna be set a bit later on after this depending on if we’re jumping or not. So, for this, we’re gonna go vel.x = relativeDir.x multiplied by our moveSpeed because we do wanna have that variation in our moveSpeed. If we wanna increase it, we can increase it later on. Then we’ve got vel.z = relativeDir.z * moveSpeed as well. So, our velocity vector is being filled in.

Now, what we need to do is apply gravity. So, with gravity here, we’ll go apply gravity. All we’re gonna do for this, is just go vel.y -= gravity * delta. So, each section we are going to be adding this amount of downward velocity to ourselves, and this multiplied by delta pretty much converts this into per second rather than per frame, because if we didn’t have this, then we would be subtracting gravity which is around 12, at the moment, so we’d be adding in negative 12 velocity to our player along the y-axis every single frame, 60 times a second, which is a lot. Instead we’re gonna be adding that every second which is done by multiplying by delta which is the time duration between each frame, so we are applying our gravity.

Now what we need to do is just move the player. Have this velocity vector be applied to the KinematicBody so we can move, and what’s really handy of this is that the KinematicBody comes with a function which allows us to easily do this. So, move the player, what we’re gonna do is just go vel = move_and_slide which also includes some collision stuff as well, and we just wanna give it the property of our velocity and the ground normal.

So, which direction is the ground facing? That is gonna Vector3.UP, which is a built in vector which is just 010 for up, and then we go. So, we’re moving the player here, now all we need to do finally for this function is add in the ability to jump, and that can be done by going, so, we’ll just have jumping and that can be done by going if Input.is_action_pressed.

So, if we’re pressing down, the jump button, then, what we also wanna check is are we grounded, because if we can just press the jump button, then, we’ll be jumping continuously. So, we want to check also, and is_on_floor which is built into the KinematicBody as well. So, if so, if we’re on the floor, and we hold down the jump button, then, what we’re gonna do is go vel.y = jumpForce, so, we’re setting our y velocity to be whatever the force is to jump upwards, okay, there we go.

So, we’ve got our function right here. We’ve got all this functionality built in. Now, let’s press play and test it out. So, I press play. We can’t look around right now, but if I go WASD we’ll see that we can move, Space jumps us up. It’s a sort of big jump, but we could tweak that a bit, and, yeah, there we go, we can move around, we can jump, we have gravity applied to us.

In the next lesson what we’re gonna do is focus on setting up the mouse look so we can rotate our head around and move in the direction we’re looking. So, thanks for watching, and I’ll see y’all, then, in the next lesson.

Scripting the Player – Camera Look

Welcome back, everyone. In the previous lesson, we set up our ability to actually move around, jump, and have gravity being applied to us. So in this lesson, we’re gonna be focusing on actually being able to look around with our camera.

So, first of all what we need to do is figure out how and where is our mouse moving? What is the direction our mouse is moving in, and how far is it moving? And we’re gonna be checking that inside of a built-in function to Godot, which is called func_input. And it comes with an event parameter. And what this function does, is it gets called whatever an input is detected in Godot. So, whenever a keyboard input’s detected, if you click a mouse button, even if you move the mouse, this function here gets called with the corresponding information sent over in the event parameter here.

So, what we wanna do is check first of all, if this event right here, is that to do with the mouse motion, so is this to do with moving the mouse? If it is about moving the mouse then we want to set the mouseDelta, to be basically the direction that the mouse is moving in. So, we’re gonna go, if our event is InputEventMouseMotion, right here, so if the event is to do a mouse motion, then what we want to do is just go, mouseDelta = event.relative, like so, okay?

And what we can do now is up inside of process function which gets called every single frame, we’re doing it in the process function and not the physics process because if you got stuff that isn’t really to do with physics, it’s recommended that you just do it in the process function so I’m gonna create the process function here, _process, which gets called every frame.

And what we want to do here is, first of all, we want to rotate the camera along the x-axis. Because with this camera set up the way we’re gonna be doing it, is we’re gonna be rotating our camera vertically, so we’re gonna be rotating the camera node up and down, so we can look up and down. But we’re not gonna be rotating the camera left and right. Instead, we’re gonna be rotating the actual play node here left and right and the camera is gonna be staying still. So, the camera is only ever gonna be rotating up and down, and if we look left and right, we’re gonna be rotating the entire kinematic body node left and right. This just makes it a lot easier for when we’re calculating stuff, such as the forward direction, which we’ve done previously.

So, to do this, we’re gonna go camera.rotation_degrees.x, and what we’re gonna do is we’re gonna subtract equals, so we’re gonna take away from this the mouseDelta.y. So, the up and down of the mouse movement multiplied by lookSensitivity multiplied by delta, so it’s converted in terms of seconds, so it’s a bit smoother. And now what we’re going to do is clamp the rotation, because if we have our mouse and we move it upwards, the cameras gonna rotate upwards, and it’s gonna keep rotating upwards until it loops back around and it’s just gonna be really weird and not really fit with this first person controller. So, we wanna clamp it so we can only look so far up and so far down.

So, clamp camera x-axis, and to do this we’re gonna go camera.rotation_degrees.x = clamp. Now, this clamp function takes in three values. It takes in the value that we wanna clamp, then we need to give it a minimum and a maximum. So, the value we wanna clamp is gonna be the camera.rotation_degrees.x. The minimum is going to be the minLookAngle, and the max is going to be the maxLookAngle. Just like that, okay? So, got that all set up.

Now, we need to set up actually rotating left and right. Because right now we can look up and down. Let’s look left and right. So, we’re gonna rotate the player along the y-axis, here. And to do this, we can just go rotation_degrees, because this is, the script is attached to the player that we’re rotating. So, we go rotation_degrees.y =, oh we need to go minus equals, mouseDelta.x, multiplied by lookSensitivity multiplied by delta. And we don’t have to clamp this value because looking left and right, there’s no minimum or maximum angle we can look, we can look full 360 degrees horizontally, so we can just leave it like that.

Finally, we go to reset the mouse delta vector so that we don’t keep looking in the direction that the mouse is moving. So, we’ll go mouseDelta = Vector2 to reset it. And that is pretty much it.

So, what we can do now is press play and hopefully it works. All right, so we can look around and there you go. We can look left, right, up, down. But something you might want in this game is for the ability for the mouse to not be free like this. ‘Cuz right now if we look outside of the window the mouse, it doesn’t continue to track. If you move it in, it continues. But it’s very weird and it’s not that usable. So, what we need to do is lock the mouse cursor in the middle of the screen and hide it so when we move our mouse we don’t see the cursor and the cursor can’t go offscreen.

Now, to do that we’re gonna go to our player script here. We’re gonna go to the top of the script, and we’ll create the underscore ready function. Now, the underscore ready function gets called once the node is initialized, so this is gonna be called once right at the start of the game. And what we’re gonna do here is we are going to hide and lock the mouse cursor. So, to do this we are gonna go input.set_mouse_mode. And with this, we can give it a number of different modes right here. There’s captured, there’s confined, there’s hidden, and there’s visible.

Visible is what it is right now, it’s visible on screen, and we can move it around freely. Hidden basically just hides the mouse cursor so we can’t see it, but it’s still gonna be moving. Confined means that it is just gonna be confined to the screen, that’s kinda what we want, but we don’t want the mouse visible. So, we’re gonna be using mouse mode captured, which hides the mouse and locks it into the center of the screen. So there we go.

And now what would happen is if we press play here, you’ll see that when we press play, the mouse cursor disappears and here we are with our character. We can look around, the mouse doesn’t appear offscreen, and if we move, you’ll see that we move in whatever direction we’re looking at. That is being done by getting the forward and right directions and creating the relative direction in order to actually set this up. If we look up you’ll see that we don’t continue to look up, we sort of clamp at the top here. It’s kinda hard to see, so I’ll go near a tree. You see how we look up, it sort of stops. If we look down, it also stops. So we can’t look all 360 degrees up and down, but left and right, that is possible. Jumping works, as well.

And yeah, so that overall is our player controller setup. We have the movement implemented, we have the camera looking implemented, and that is pretty much how you set up a basic character controller inside of Godot. In the next lesson we’re gonna be focusing on actually setting up the ability to shoot bullets as that’s gonna be one of the main mechanics in this game. We’ve got our gun here, we’ve got that muzzle object set up, now all we need to do is be able to left click on the mouse button and shoot our bullet. And from there, we’ll also set up enemies that we can shoot, pick ups, and the UI system later on.

Just something quickly, also. You may notice that you can’t really get out of this window right here, you click escape, nothing really happens. It’s kinda hard to get out of this window. So what you can do is you can just hit alt f4 to quit out of that little gameplay window. It goes back to the Godot Editor, and it stops playing the game. So yeah, there you go. I’ll see you all in the next lesson.

Interested in continuing?  Check out the full Build a First-Person Shooter with Godot course, which is part of our Godot Game Development Mini-Degree.

]]>
Create a First Person Shooter in Godot – Part 2 https://gamedevacademy.org/fps-godot-tutorial-part-2/ Thu, 20 Feb 2020 16:00:47 +0000 https://godottutorials.pro/?p=3196 Read more]]> Introduction

Welcome back, and I hope you’re ready to finish creating our Godot FPS tutorial.

In Part 1, we set up our arena, our player character, our FPS camera, our gun, our bullets, and even our red enemies.  However, while we certainly implemented the shooting mechanics, our enemies can’t yet damage players, get damaged themselves, or move.  In addition, we have no pickups to speak of, let alone a UI to give the player essential health and ammo information.  As such, in this tutorial, we will be jumping into setting those up.

By the end, you will have not only learned a lot about 3D game development, but also have a nifty FPS to add to your portfolio!

Project Files

For this project, we’ll be using a handful of pre-made assets such as models and textures. Some of these are custom-built, while others are from kenney.nl, a website for public domain game assets.

  • You can download the assets for the project here.
  • You can download the complete FPS project here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Scripting the Enemy

Create a new script on the Enemy node. Let’s begin with the variables.

# stats
var health : int = 5
var moveSpeed : float = 1.0

# attacking
var damage : int = 1
var attackRate : float = 1.0
var attackDist : float = 2.0

var scoreToGive : int = 10

# components
onready var player : Node = get_node("/root/MainScene/Player")
onready var timer : Timer = get_node("Timer")

In the _ready function, we’ll set up the timer to timeout every attackRate seconds.

func _ready ():

    # setup the timer
    timer.set_wait_time(attackRate)
    timer.start()

If we select the Timer node, we can connect the timeout signal to the script. This will create the _on_Timer_timeout function. We’ll be working on this later on.

func _on_Timer_timeout ():
    pass

In the _physics_process function, we’ll move towards the player.

func _physics_process ():

    # calculate direction to the player
    var dir = (player.translation - translation).normalized()
    dir.y = 0

    # move the enemy towards the player
    move_and_slide(dir * moveSpeed, Vector3.UP)

The take_damage function gets called when we get damaged by the player’s bullets.

# called when we get damaged by the player
func take_damage (damage):

    health -= damage

    # if we've ran out of health - die
    if health <= 0:
        die()

The die function gets called when our health reaches 0. The add_score function for the player will be added soon.

# called when our health reaches 0
func die ():

    player.add_score(scoreToGive)
    queue_free()

The last function to add is the Attack function. We’ll be creating the player’s take_damage function soon.

# deals damage to the player
func attack ():

    player.take_damage(damage)

Finally in the _on_Timer_timeout function, we can check the distance to the player and try to attack them.

# called every 'attackRate' seconds
func _on_Timer_timeout ():

    # if we're at the right distance, attack the player
    if translation.distance_to(player.translation) <= attackDist:
        attack()

Player Functions

In the Player script, we’re going to add in a number of functions which we need right now and in the future. The die function will be filled in later once we have our UI setup.

# called when an enemy damages us
func take_damage (damage):

    curHp -= damage

    if curHp <= 0:
        die()

# called when our health reaches 0
func die ():

    pass

# called when we kill an enemy
func add_score (amount):

    score += amount

# adds an amount of health to the player
func add_health (amount):

    curHp = clamp(curHp + amount, 0, maxHp)

# adds an amount of ammo to the player
func add_ammo (amount):

    ammo += amount

Now we can go to the MainScene and drag the Enemy scene into the scene window to create a new instance of the enemy. Press play and test it out.

Pickups

For our pickups, we’re going to create one template scene which the health and ammo pack will inherit from. Create a new scene with a root node of Area.

  1. Rename it to Pickup.
  2. Save the scene.
  3. Attach a child node of type CollisionShape.
  4. Set the Shape to Sphere.
  5. Set the Radius to 0.5.

Pickup Node in Godot with CollisionShape

Next, create a script on the Pickup node. First, we’ll create an enumerator which is a custom data type that contains different options.

enum PickupType {
    Health,
    Ammo
}

Then for our variables.

# stats
export(PickupType) var type = PickupType.Health
export var amount : int = 10

# bobbing
onready var startYPos : float = translation.y
var bobHeight : float = 1.0
var bobSpeed : float = 1.0
var bobbingUp : bool = true

In the _process function, we’re going to make the pickup bob up and down.

func _process (delta):

    # move us up or down
    translation.y += (bobSpeed if bobbingUp else -bobSpeed) * delta

    # if we're at the top, start moving downwards
    if bobbingUp and translation.y > startYPos + bobHeight:
        bobbingUp = false
    # if we're at the bottom, start moving up
    elif !bobbingUp and translation.y < startYPos:
        bobbingUp = true

Select the Pickup node and connect the body_entered node to the script.

# called when another body enters our collider
func _on_Pickup_body_entered (body):

    # did the player enter our collider?
    # if so give the stats and destroy the pickup
    if body.name == "Player":
        pickup(body)
        queue_free()

The pickup function will give the player the appropriate stat increase.

# called when the player enters the pickup
# give them the appropriate stat
func pickup (player):

    if type == PickupType.Health:
        player.add_health(amount)
    elif type == PickupType.Ammo:
        player.add_ammo(amount)

Now that we’ve finished the script, let’s go back to the scene and you’ll see that the Pickup node now has two exposed variables.

Godot Inspector with Health Script Variables circled

We’re now going to create two inherited scenes from this original Pickup one. Go to Scene > New Inherited Scene… and a window will pop up asking to select a base scene. Select the Pickup.tscn and a new scene should be created for you. You’ll see that there’s already the area and collider nodes there since they are a parent. This means any changes to the original Pickup scene, those changes will also be applied to the inherited scenes.

All we need to do here is…

  • Rename the area node to Pickup_Health
  • Set the pickup type to Health
  • Drag in the health pack model

Pickup Health Node with model added in Godot

We also want to do the same for the ammo pickup.

Pickup Ammo node in Godot with model added

Back in the MainScene, we can drag in the Enemy, Pickup_Health and Pickup_Ammo scenes and place them around.

Godot FPS level with health and ammo pickups added

UI

Now it’s time to create the UI which will display our health, ammo, and score. Create a new scene with the root node being User Interace (control node).

  • Rename the node to UI
  • Create a new child node of type TextureProgress
  • Enable Nine Patch Stretch
  • Rename it to HealthBar
  • Move the health bar to the bottom left of the screen and re-size it
  • Drag the 4 anchor points (green pins) to the bottom left of the screen
  • Set the Under and Progress textures to the UI_Square.png image
  • Set the Tints as seen in the image.

UI HealthBar created in Godot

For the text, we need to create a new dynamic font resource. In the file system, find the Ubuntu-Regular.ttf file – right click it and select New Resource…

  • Search for and create a DynamicFont
  • In the inspector, set the Font Data to the ubuntu font file
  • Set the Size to 30

Godot Inspector for Dynamic Font

Now we can create the text elements. Create a new Label node and call it AmmoText.

  • Resize and position it like in the image below
  • Set the Custom Font to the new dynamic font file
  • Move the anchor points down to the bottom left

Ammo text for FPS game added in Godot scene

With the node selected, press Ctrl + D to duplicate the text.

  • Rename it to ScoreText
  • Move it above the ammo text

Score UI text added in FPS Godot game

Scripting the UI

Now that we have our UI elements, let’s create a new script attached to the UI node called UI.

First, we can create our variables.

onready var healthBar : TextureProgress = get_node("HealthBar")
onready var ammoText : Label = get_node("AmmoText")
onready var scoreText : Label = get_node("ScoreText")

Then we’re going to have three functions which will each update their respective UI element.

func update_health_bar (curHp, maxHp):
	
    healthBar.max_value = maxHp
    healthBar.value = curHp
	
func update_ammo_text (ammo):
	
    ammoText.text = "Ammo: " + str(ammo)
	
func update_score_text (score):
	
    scoreText.text = "Score: " + str(score)

So we got the functions to update the UI nodes. Let’s now connect this to the Player script. We’ll start by creating a variable to reference the UI node.

onready var ui : Node = get_node("/root/MainScene/CanvasLayer/UI")

Then in the _ready function, we can initialize the UI.

func _ready ():

    # set the UI
    ui.update_health_bar(curHp, maxHp)
    ui.update_ammo_text(ammo)
    ui.update_score_text(score)

We want to update the ammo text in both the shoot and add_ammo functions.

ui.update_ammo_text(ammo)

We want to update the health bar in both the take_damage and add_health functions.

ui.update_health_bar(curHp, maxHp)

We want to update the score text in the add_score function.

ui.update_score_text(score)

And now we can go back to the MainScene and create a new node called CanvasLayer. Whatever is a child of this, gets rendered to the screen so let’s now drag in the UI scene as a child of this node.

Godot CanvasLayer with UI added

Now we can press play and see that the UI is on-screen and updates when we take damage, collect pickups, and kill enemies.

Conclusion

Congratulations on completing the tutorial!

If you’ve been following along, you should now have a complete Godot FPS game at your fingertips.  Players will be able to fire on enemies, gather pickups for ammo and health, and even potentially be defeated by our menacing red capsules!  Not only that, but you also have boosted your own knowledge in how Godot’s 3D engine works and how you can utilize 3D’s unique features in a number of ways.  Of course, from here, you can expand upon the FPS game we created in any way you please – adding in new systems, models, sound, etc.

Thanks for following along, and I hope to see you in the next Godot tutorial.

]]>
Create a First-Person Shooter In Godot – Part 1 https://gamedevacademy.org/fps-godot-tutorial/ Wed, 19 Feb 2020 16:00:21 +0000 https://godottutorials.pro/?p=3144 Read more]]> Introduction

Welcome to the tutorial, and get ready to learn some in-demand skills for creating first-person shooter games!   Throughout this tutorial, we will work with the 3D aspects of the Godot game engine to enhance your foundations when it comes to action game development.  Additionally, we’ll be creating a first-person shooter from scratch, which will show you how to set up the FPS player and camera, enemies, efficient shooting mechanics, health and ammo pickups, and more.

Before we begin, it’s important to know that a basic understanding of the Godot engine is required. If this is your first time using Godot, I recommend you read through the How to Make Games with the Godot Game Engine post first. It will teach you how to install Godot, and the basics of the engine and GDScript.

Already know how to do all this?  Go ahead and skip to Part 2!

Project Files

For this project, we’ll be using a handful of pre-made assets such as models and textures. Some of these are custom-built, while others are from kenney.nl, a website for public domain game assets.

  • You can download the assets for the project here.
  • You can download the complete FPS project here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Let’s Begin

To begin, create a new Godot project. We have a few assets such as models and textures we’ll be using (download above), so let’s drag the Font, Models and UI folders into the FileSystem.

Godot FileSystem window with assets imported

Now that we have our assets, let’s create our first scene by going to the scene panel and selecting the 3D Scene option.

  1. Rename the node to MainScene.
  2. Save the main scene to the file system.

Godot with MainScene selected in Scene hierarchy

Building Our Environment

The first thing we’re going to do is create our environment so we have somewhere for the player to exist. In our Models/Environment folder, we have a Ground model. Drag that into the scene window to create a new MeshInstance node. Set the position to 0.

Godot with ground object added to game

The MeshInstance node will render a model, but that’s it. In our case, we want the player to be able to collide with the ground, otherwise they’d sink through.

So to do this, we can select the ground node and in the scene panel, select Mesh > Create Trimesh Static Body.

Godot Mesh menu with Create Trimesh Static Body selected

This will create two children nodes.

  • StaticBody: static physics object which can detect collisions
  • CollisionShape: defines the shape and dimensions of the object’s collider

Ground object in Godot with a StaticBody

With this node, we can change the position, scale and rotation. Go ahead and create an environment.

Godot level with grass plains and trees

One thing you may notice, is that the node structure is starting to get quite long and convoluted since we have a lot of models. To fix this, we can create a new node as a container and store the models in as children.

Create a new node of type Node as a child of the MainScene. Drag the model nodes inside to make them children. Now we can visually open or close the node container.

Models dropdown in Godot Scene window

Another thing you might notice is that the scene is quite dark. To fix this, we can add in a directional light which will act like a sun.

  1. Create a new node of type DirectionalLight.
  2. Enable shadows.
  3. Set the Rotation Degrees to -60, 45, 0.

DirectionalLight added to Godot FPS scene

Creating the Player

Now we can create the player. Create a new scene with a root node of KinematicBody and rename it to Player. We can then save the scene.

Godot Player node in Scene

Let’s add a CollisionShape node to detect collisions.

  1. Set the Shape to Capsule
  2. Set the Radius to 0.5
  3. Set the Height to 1.5
  4. Set the Translation to 0, 1.25, 0
  5. Set the Rotation to 90, 0, 0

Collision Shape added to Player node in Godot

Next, add a new Camera node. This will allow us to see through the player’s eyes.

  1. Set the Environment to default_env.tres (found in file system)
  2. Enable Current
  3. Set the Translation to 0, 0.25, 0

Camera in Godot added as a child to Player

For the gun, drag the shotgun.obj model into the scene and make it a child of Camera. To see through the camera’s perspective, select the camera and in the scene view toggle the Preview option (top left of the window).

  1. Rename the node to GunModel
  2. Set the Translation to 0.2, -0.2, -0.7
  3. Set the Rotation Degrees to 0, -180, 0
  4. Set the Scale to 10, 10, 10

GunModel added as a child to the Godot camera

The gun also needs a muzzle so we know where to spawn the bullets. Create a new Spatial node as a child of GunModel.

  1. Enable Use Local Space (shortcut = T) so that the gizmos are orientated in local space
  2. Rename the node to Muzzle
  3. Position the node in front of the gun

Muzzle object added as child of GunModel in Godot

Back in the MainScene, let’s drag in the Player.tscn to create a new instance of the Player scene.

Player object added to Godot MainScene

With this here, we can press the play button (make the MainScene the main scene) and you should be looking through the player’s eyes.

Finally, before we begin scripting, let’s set up our input actions. Open the Project Settings window (Project > Project Settings) and go to the Input Map tab. Create a new action for:

  • move_forward (W key)
  • move_backward (S key)
  • move_left (A key)
  • move_right (D key)
  • jump (Space key)
  • shoot (Left Mouse Button)

Godot Input Map window

Scripting the Player

Now that we have our player scene setup, let’s get to scripting the player movement, jumping, gravity, shooting, etc.

In the Player scene, create a new script on the Player node. By default, it should be called Player.gd. We’ll begin by filling in our variables.

# stats
var curHp : int = 10
var maxHp : int = 10
var ammo : int = 15
var score : int = 0

# physics
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 12.0

# cam look
var minLookAngle : float = -90.0
var maxLookAngle : float = 90.0
var lookSensitivity : float = 0.5

# vectors
var vel : Vector3 = Vector3()
var mouseDelta : Vector2 = Vector2()

# player components
onready var camera = get_node("Camera")

First, we can begin by setting up the ability to look around. The _Input function is built into Godot and gets called whenever an input is detected (keyboard, mouse click and movement). What we’re doing here, is getting the direction and length that our mouse moved.

# called when an input is detected
func _input (event):

    # did the mouse move?
    if event is InputEventMouseMotion:
        mouseDelta = event.relative

Next, we’ll create the _process function. This is built into Godot and gets called every frame. Here, we’re going to use that mouseDelta vector and apply that to the camera and player rotations.

# called every frame
func _process (delta):

    # rotate camera along X axis
    camera.rotation_degrees -= Vector3(rad2deg(mouseDelta.y), 0, 0) * lookSensitivity * delta

    # clamp the vertical camera rotation
    camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, minLookAngle, maxLookAngle)
	
    # rotate player along Y axis
    rotation_degrees -= Vector3(0, rad2deg(mouseDelta.x), 0) * lookSensitivity * delta
	
    # reset the mouse delta vector
    mouseDelta = Vector2()

We can now press Play and see that we look around when we move the mouse.

Next up is movement. This will all be done in the _physics_process function. It’s built into the KinematicBody node and gets called 60 times a second (good for physics).

# called every physics step
func _physics_process (Delta):

First, we’re going to check for our keyboard inputs.

# reset the x and z velocity
vel.x = 0
vel.z = 0

var input = Vector2()

# movement inputs
if Input.is_action_pressed("move_forward"):
    input.y -= 1
if Input.is_action_pressed("move_backward"):
    input.y += 1
if Input.is_action_pressed("move_left"):
    input.x -= 1
if Input.is_action_pressed("move_right"):
    input.x += 1

# normalize the input so we can't move faster diagonally
input = input.normalized()

Next, we need to get the forward and right direction of our player, so we know which way we’re facing and can apply that to our velocity.

# get our forward and right directions
var forward = global_transform.basis.z
var right = global_transform.basis.x

We can then set our velocity, apply gravity and move the player!

# set the velocity
vel.z = (forward * input.y + right * input.x).z * moveSpeed
vel.x = (forward * input.y + right * input.x).x * moveSpeed

# apply gravity
vel.y -= gravity * delta

# move the player
vel = move_and_slide(vel, Vector3.UP)

Finally, we’re going to check for the jump action and change the Y velocity when that happens.

# jump if we press the jump button and are standing on the floor
if Input.is_action_pressed("jump") and is_on_floor():
    vel.y = jumpForce

If we press the play button now, you’ll be able to move, look around and jump. That’s how to create a basic first-person controller in Godot. Now let’s get working on the rest of the game.

Creating the Bullet Scene

Before we start to script the ability to shoot, we need to create a scene for the bullet. Create a new scene with a root node of Area. This is a node which can detect physics collisions.

  1. Save the scene to the FileSystem.
  2. Drag the ammo_pistol.obj model into the scene as a child of Bullet.
  3. Set the model’s Scale to 10, 10, 10. (not in image)
  4. Set the model’s Rotation Degrees to 90, 0, 0. (not in image)
  5. Attach a new CollisionShape node.
  6. Set the Shape to Capsule
  7. Set the Radius to 0.03
  8. Set the Height to 0.07

Bullet node in Godot with collision shape

On the Bullet node, create a new script called Bullet.gd. We’ll start of with the variables.

var speed : float = 30.0
var damage : int = 1

Inside of the _process function, we’ll move the bullet forwards at a rate of speed units per second.

# called every frame
func _process (delta):

    # move the bullet forwards
    translation += global_transform.basis.z * speed * delta

Now it’s time to detect if we’re hitting something. Select the Bullet node and over in the inspector, click on the Node tab to see all of the signals that the node emits. A signal is like an event which can call a function when something happens. In our case, we want to connect the body_entered signal to our script. This gets called when the collider enters another node’s collider.

Double click on that signal and hit enter. A new function should have appeared in the bullet script.

We’re going to check if the body we hit has a function called take_damage. We haven’t created this yet, but we will do it soon. If so, deal the damage and destroy the bullet by calling the destroy function. This is a custom function we’re going to create right after this one.

# called when we enter the collider of another body
func _on_Bullet_body_entered (body):

    # does this body have a 'take_damage' function?
    # if so, deal damage and destroy the bullet
    if body.has_method("take_damage"):
        body.take_damage(damage)
        destroy()

The destroy function will simply destroy the bullet instance.

# destroys the bullet
func destroy ():

    queue_free()

We now have a bullet which will move forward and damage whatever it hits (yet to be added). Let’s also add in something so that the bullet can’t travel forever if it misses its target.

In the Bullet scene, create a new node of type Timer. This node will count up and when it hits a certain amount, we’ll call the destroy function.

  1. Set the Wait Time to 5
  2. Enable Autostart

Bullet object in Godot with setting in Inspector

Over in the node tab, let’s connect the timeout signal to our script. This gets called once the wait time has been reached. Double click on the timeout signal and a window will pop-up. Change the Receiver Method to destroy. This will connect the signal to our existing function.

Connect a Signal to a Method window in Godot for FPS bullet

Shooting Bullets

Now that we have our bullet, let’s implement the ability to shoot it. Over in the Player script, let’s create some new variables to keep track of our components.

onready var muzzle = get_node("Camera/GunModel/Muzzle")
onready var bulletScene = preload("res://Bullet.tscn")

Down in the _process function, let’s check for when the shoot action is pressed.

# check to see if we're shooting
if Input.is_action_just_pressed("shoot"):
    shoot()

The shoot function will spawn a new instance of the bullet scene and position it.

# called when we press the shoot button - spawn a new bullet
func shoot ():

    var bullet = bulletScene.instance()
    get_node("/root/MainScene").add_child(bullet)

    bullet.global_transform = muzzle.global_transform
    bullet.scale = Vector3.ONE

    ammo -= 1

If you want the mouse to be locked when we’re playing the game, we can do so in the _ready function which gets called when the node is initialized.

func _ready ():

    # hide and lock the mouse cursor
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

We can now press play and test it out.

Creating the Enemy

Create a new scene with a root node of KinematicBody.

  1. Rename it to Enemy.
  2. Save the scene.
  3. Attach a new node of type MeshInstance.
  4. Rename it to Model.
  5. Set the Mesh to capsule.
  6. Set the Radius to 0.5.
  7. Set the Mid Height to 1.5.
  8. Rotate and re-position the mesh so that it is orientated like below.

Enemy node with capsule model in Godot

In the MeshInstance node, you’ll see a Material property which is empty. Select it and click New SpatialMaterial.

  1. Set the Albedo Color to red.

Godot Inspector with red albedo added to enemy

Let’s then attach a new CollisionShape node and make it match the mesh.

Enemy node in Godot with collision shape added

Finally, we’ll attach a Timer node to the enemy. This is going to be used in order to attack the player.

Enemy Node in Godot with Timer added

Continued Part 2

And that’s where we’ll conclude for the time being!

At this point, we’ve learned several essential foundations for setting up a first-person shooter in Godot.  First, we established our arena where all the action will take place.  We then created a player, along with a camera, which is scripted to follow the mouse movements as we move the player around.  To this player, we also added a gun model that can shoot bullets – which we also created with performance in mind. Lastly, we set up our enemy model and learned a bit about materials in the process.

Of course, there is still more needed to complete our FPS!  In Part 2 of this tutorial, we will finish up building our Godot FPS by implementing the enemies’ movement, setting up ammo and health pickups, and polishing everything off with a nifty UI!  We hope to see you there.

]]>
Creating a Multiplayer Battle Royale Map & Camera https://gamedevacademy.org/multiplayer-battle-royale-tutorial/ Fri, 09 Aug 2019 15:00:32 +0000 https://gamedevacademy.org/?p=10207 Read more]]>

You can access the full course here: Battle Royale – Multiplayer Projects

Part 1

Folder Structure

Let’s start by setting up out folder structure and 2 scenes.

  • Materials
  • Models
  • Photon
  • Prefabs
  • Resources
  • Scenes
    • Game scene
    • Menu scene
  • Scripts
  • Textures

Menu Scene

In our menu scene, let’s setup the camera for when we do the menu UI in a later lesson.

  • Set the Clear Flags to Solid Color
  • Set the Background to a green-blue color
  • Set the Projection to Orthographic

Unity Inspector for main camera

Game Scene

In our game scene, let’s setup our map. First, we’ll drag in the Terrain model.

  • Create an empty game object called _Map and drag the terrain in as a child of that
  • Set the Position to 0
  • Set the Scale to 10
  • Create a new material called Terrain and apply it to the terrain model
  • Add a Mesh Collider component to the terrain

Unity scene with green terrain mesh added

You might notice that the shadows are quite dark. To fix this we can go to the Lighting screen (Window > Rendering > Lighting) and click on the Generate Lighting button at the bottom.

Unity Inspector with Generate Lighting selected

Building our Map

Now we’re going to create the various structures and put them around our map. Let’s start by dragging in the Building model. Like with the terrain, we can create a new material and apply it to the model.

Right now we’d be able to walk through the walls. So what we need to do, is add a Mesh Collider component. This will make a custom collider to match the dimensions of the mesh.

Unity Mesh Collider component

Finally, we can save it in our Prefabs folder to both use later, and make sure all changes are applied to all instances.

Unity building prefab in assets

Do the same for the Barrier and Platform models.

Unity scene with barrier and platform added

Finally, we can go around and populate the map with our structures.

Unity scene with battle royale map

In the next lesson, we’ll start to create our network manager.

Part 2

CameraController Script

Create a new C# script called CameraController and attach it to the main camera. In this lesson, we’ll just be setting up the spectator camera functionality. When we create our player controller, we’ll do the rest. First up is our variables.

[Header("Look Sensitivity")]
public float sensX; 
public float sensY;

[Header("Clamping")]
public float minY;
public float maxY;

[Header("Spectator")]
public float spectatorMoveSpeed;

private float rotX;
private float rotY;

private bool isSpectator;

The first thing we want to do is lock and hide the mouse cursor in the Start function.

void Start ()
{
    // lock the cursor to the middle of the screen
    Cursor.lockState = CursorLockMode.Locked;
}

For actually checking the input and applying it to our rotation, we’ll be doing that inside of the LateUpdate function. The reason for this, is that doing it in the Update function, can cause jittering.

void LateUpdate ()
{

}

First up, let’s get our mouse inputs.

// get the mouse movement inputs
rotX += Input.GetAxis("Mouse X") * sensX;
rotY += Input.GetAxis("Mouse Y") * sensY;

Then we can clamp the vertical rotation.

// clamp the vertical rotation
rotY = Mathf.Clamp(rotY, minY, maxY);

For the spectator camera, we’re going to be able to look around as well as moving with the keyboard.

// are we spectating?
if(isSpectator)
{
    // rotate the cam vertically
    transform.rotation = Quaternion.Euler(-rotY, rotX, 0);

    // movement
    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");
    float y = 0;

    if(Input.GetKey(KeyCode.E))
        y = 1;
    else if(Input.GetKey(KeyCode.Q))
        y = -1;

    Vector3 dir = transform.right * x + transform.up * y + transform.forward * z;
    transform.position += dir * spectatorMoveSpeed * Time.deltaTime;
}
else
{

}

Back in the editor, we can fill in the values.

  • SensX = 10
  • SensY = 10
  • MinY = -90
  • MaxY = 90
  • SpectatorMove peed = 10

 

Transcript 1

Hey everybody and welcome to the course. My name’s Daniel Buckley and I’ll be instructor. Let’s have a look at what we’ll be making.

We are going to be creating a multiplayer, 3D, battle royale game. Here’s an example of two players who are playing the game. The player on the right, you can see, can kill the player on the left, and once he does that, he is the last player alive and wins the game. This can feature as many players as you want. We are just going to be testing it out with around two or three, but as you can see, we have a level here and we also have a force field in the background that closes in.

For this project, we will be using Photon Unity Networking. This is a free networking framework that is very useful and very popular within Unity. It’ll allow us to connect servers, create rooms, have lobby browsers, and send each other messages to create a fully working multiplayer game.

So one of the first things we’ll create is the player controller. This is what you will control. You’ll be able to move, jump, shoot, heal when you pick up a health pack, and add ammo when you pick up an ammo pack. When a player gets hit by a bullet, they take on damage; and when their health reaches zero, they will die and the camera will actually become a spectator camera so you’ll then be able to fly around the map and look at the remaining players while they play the game.

We’ll also have pickups, health and ammo packs, that the player can find around the map, and just like any battle royale game, we have a force field that will encapsulate the players and force them into smaller and smaller areas on the map. This will damage the player every second or so while they’re outside the force field, and it will shrink every so meters every so and so seconds. This is a very customizable force field that we’ll be creating.

One of the things we’ll also create is a lobby and menu system. Players can join a game and wait in a lobby before starting. On the left is our lobby browser. When a player creates a game, the players will be able to find it in the lobby browser. As you can see, it has the room name, as well as how many players are currently in it, and then on the right we have the actual lobby. This will display all the list of players who are in the room, as well as the name of the room, and it’ll allow the host to begin the game whenever they want.

To do this, we’ll be using Unity’s UI system. On the left is what the game UI will look like. We’ll use sliders for the health bar, text for all the stats and even an image for crosshair. On the right we have the same thing. We have, this time, also a scroll bar. We’ll be learning how to use the scroll racks and setting all that up to create a dynamic server browser as well so that you can update constantly when you click the refresh button.

So, ZENVA is an online learning academy with over 400,000 students. We feature a wide range of courses for people who are just starting out or for people who just want to learn something new. Our courses are also very versatile. You can view them wherever you are and whenever you want. There’s also lesson summaries so you can choose to follow along and watch the videos or even read the courses and we’ve included project files. You can create the project however you want. Now with all that said, let’s get started on our project.

Transcript 2

Welcome back, everyone! In this lesson, we’re gonna be setting up our project, and first of all, our project file structure. Then we’re gonna move on and set up each of our scenes.

So, to begin, let’s create our folders. We’ve already got our Photon and Scenes folder right here. So let’s create another folder, and this one is gonna be called Prefabs. Now, this is where we’re gonna be storing all of our different Prefabs that we’re gonna be using. Let’s also make a folder called Materials, to store our materials in, and then another folder for our models.

This project also comes with some included files and some of those are models that we’re gonna be using. So, these models are the AmmoBox, Barrier, Building, Force Field, Health Pack, Platform and Terrain. So, I’m just gonna drag those in right here.

Apart from that, we also then want to create another folder here. This folder is gonna be called our Scripts and this is where we’re gonna be storing all of our different scripts we’re gonna be creating and then another folder for the resources. And in the Resource folder, I’ll get into more detail about this later, but, this is where we need to put Prefabs that we want to instantiate over the network with Photon. I’ll go into this in more detail later on, when we actually start instantiating those, but for now, let’s create our next folder, and this folder is going to be called Textures.

Now, the only texture we’re really gonna be having is going to be our CrossHair, which is another included asset in the project files, so you can just drag that in. And by default, let’s actually just set this up right now, let’s click on this crosshair right here, and we have to change the texture type from default to Sprite, 2D and UI. And just click on apply, like so. And that’s all we have to do. And that’s it for the folders.

Now, let’s go into our scenes folder, and we want to create two new scenes. The first scene we want to create is going to be our menu scene, which is going to be where we can create lobbies, join rooms, and then start the game. And then we want our next scene to be the actual game. And this is where all the action is going to be taking place.

And let’s actually open up the menu scene right now and inside of here, we can go into the game view, have a look. Let’s actually set up the camera as well right now. So let’s click on the main camera, and we want to change its projection from Perspective to Orthographic. The reason for that is because since we’re working with UI and 2D aspects in this scene, we don’t really need depth, because we’re not trying capture distance of 3D objects. So we can set it to Orthographic to make it much easier, and we’ll actually change the background, because we don’t really want this skybox background for a menu. So what we can do is click on Clear Flags up here and change that from SkyBox to Solid Color. And this color can then be changed here, and let’s change this to a sort-of greeny-blue color. Something like this.

All right, and with that done, let’s now save that and go into a game scene where we are gonna create our level. So, first thing, let’s go our models folder, and we want to drag in the terrain model right here into the scene. Now, it doesn’t have texture on it just yet, but before we do that, let’s actually set-up the hierarchy here a bit.

Let’s right-click and go Create Empty and we’re gonna call this one, let’s zero this out, we’re gonna call this one _Map. Now, this is just gonna be an empty game object that’s gonna be holding all of our, all of the objects that are related to the map. All of the structures and stuff like that. Just so it’s a lot neater here in the hierarchy and we can look through it and understand what object is for what thing.

So, let’s drag our terrain into the map object right here and let’s actually make a texture for this terrain. So, let’s go to our materials folder that we just created we’ll right-click here, go Create, Material and let’s call this Terrain. To apply a material, we can simply drag this on like so and let’s change this material over here, let’s set the smoothness all the way down and let’s change the albedo color to a green. So, we’ll go green here. Yeah, something like that.

You may notice though that the shadows look quite dark and not really that good. This is just how it is by default, but what we can do to easily fix this is go over to the Lighting Panel. If you don’t have the Lighting Panel, you can go up to Window here, go Rendering, and then Lighting Settings. And once we’re on here, all we need to do is just click on the Generate Lighting button down here at the bottom right. Just click that, it should take barely any time and there we go, it’s done. We have our shadows and everything and it looks so good now. Since we’re using real-time lighting, we don’t really have to do that again, unless you want optimize it. But, for us, we’re fine just like this.

So, with our terrain, we can now, and it might look a bit too bright, that green. So, let’s change this to something a bit more green like that, I reckon. That green looks good. So we’ll keep it like that. Now, the thing with our terrain right now is that it looks pretty good, it looks pretty much the size, but the problem is, we want to be using Unity units. We want to be scaling everything within the units inside of Unity. And that just makes it a lot easier for the physics to work as we want and just makes things, everything to scale.

So, what we can do now is just right-click here, just do for reference, go to 3D object, Cube and this cube here, if we zero this out, is one by one meter. Now, if we compare that to the rest of the terrain, it makes the terrain look quite small in comparison to that one meter cube. So, let’s get our terrain here, and let’s scale it up a bit. Let’s set the scale here to maybe 10 by 10 by 10. With that done, we can actually delete that cube, and let’s start on actually adding in our buildings and all about that.

So, let’s go to our models folder again, and we actually drag in the building asset right here. Just like that. Let’s create a texture for it, by going back to our materials folder. We’ll create a new material and we’ll call this one Building. Let’s apply it to the building here, and we’ll set the smoothness back down to zero again. And for the albedo, let’s set this to maybe a sort of dark brown sort of color like that. Yeah, something like that, there we go.

At the moment though, if we click on a building, we’ll see that we can actually, we actually don’t have a collider on it. So, people can walk through the walls, they can shoot through the walls, but we don’t want that. So, we’re gonna be adding a component here, and the component we want to add is going to be a mesh collider. And what this does is this makes it so that basically the mesh is a collider. It’s not necessarily a box collider or sphere collider; it just has it so you can’t walk into the actual object itself. So, the collider covers the entire object. There we go.

For this building, let’s actually go to our Assets window, into our Prefabs and let’s actually save this as a Prefab, so we can easily use it later on. We’ll just keep it, call it Building, and let’s drag it into here. We’ll go original Prefab and there we go, with our building asset. Our building Prefab saved, so let’s actually drag this into our map object, as that’s where it belongs.

Let’s add in our next environment model, which is gonna be the barrier. And this is just gonna be a sort-of shield of protection that the players can hide behind. Let’s again add a mesh collider to cover that. And let’s actually change this default white material to something else. So, we’ll create a new material in our materials folder and we’ll call this one Barrier. We’ll apply that, set the smoothness down to zero, and for the albedo, let’s make this say, sort of dark, dark gray like that. Yeah, something like that. Okay, that barrier is done, so let’s drag that into our Prefabs folder as well. We’ll make a Prefab of that, original Prefab.

And, the last thing we need to make is going to be our platform. This is just gonna be another structure that the players can climb up on top, look out from the top of, and shoot other players from. So, let’s actually re-use some of our materials, because what we can do is, for this platform here, we can set this as the building material there, and for the centerpiece, we can just do that as the barrier. So, there we go, we can reuse material like that, we can create new materials, if you want, for this, but I reckon we’ll just keep it with this sort of theme like that. It just looks pretty nice.

So, yeah, with these three things here, let’s actually first of all, go to Prefabs and save this platform as a Prefab, like so. And actually, we need to add in our colliders for this as well, so inside of here, we can select the cube and the other cube here, for both the different models, go Add Component, Mesh Collider. Click on the platform here, we can drag that back into the Prefabs folder, save it as a Prefab and there we go.

Now, what I’m gonna do is, I’m just gonna go around, I’m going to design the map. You can choose where you want to place them how many different objects you want, but just customize your map. Put things where you want and yeah, so I’ll be back once my map is finished.

So, there we go. I’ve got my map complete. I just put the houses, I’ve put the buildings around the different areas here up on this little hill here in different little areas and mixed around that with the towers, as well as the barriers. Something we also have to do, that I just remembered, is actually add a collider to our terrain, because otherwise, we’ll just fall right through the floor. So selecting the terrain, let’s just add a component, and add a mesh component, just, add a mesh collider, just like all the other ones. And that’s all we needed to do.

In the next lesson, we’re gonna be starting on our network manager, which is gonna be actually connecting us to the Photon Servers and allowing us to create rooms, join rooms, and all the rest. So, I’ll see you all then.

Transcript 3

All right, welcome back everyone. In this lesson, we’re gonna be starting to create our camera controller script.

At the moment, I’m in the game scene right now, and let’s actually create a new script here in our scripts folder. And we’re gonna be calling this one CameraController. Now with our camera controller script, let’s actually attach this to our camera by just dragging that on like so and opening it up in Visual Studio.

Now there are gonna be two different modes for this camera. There’s gonna be the first one where it’s actually attached to the player, and they’ll be able to look around, they’ll be able to look horizontally and look vertically. And then when the player dies the player will go into spectator mode, which will allow them to fly around the map using WASD or the arrow keys, and they will still be able to look around. So it’ll allow them to view the battle even after death.

So let’s remove the Start and Update functions here, as we won’t be needing them, and begin with our variables. Now we’ll be needing a few variables to keep track of the different sensitivities and positions and rotations. So I’m gonna separate these by headers, which is an attribute like so. And this just has a bold text in the inspector, so we can easily differentiate these.

And the first one we’re gonna do is going to be Look Sensitivity. And for this we’re gonna have a public float senseX for our X-axis sensitivity. And another one for a float for our senseY for our Y-axis sensitivity when we move the mouse. Then we also want to clamp our rotation, so got clamping and this is going to be our public float, minY, so what’s the lowest Y rotation we can look at. And then for the max, which is going to be maxY and what is the most vertical we can look – so how high up can we look before it clamps.

And then after that we then want to know for spectator, so we’ll go Header Spectator but then want to know how fast the spectator can move. So spectator or just go spectatormovespeed here. And after that we’re gonna go into our private variables. And first of all we then want to know our private float rotX, so what’s our current X rotation and the same for the Y, so what’s our current Y rotation. And that’s it for all the variables.

Now what we want to do first of all is – in many games you may notice that once you hop in it you can no longer see the mouse and the mouse actually doesn’t go off the screen. And that is because the mouse cursor is locked, and to do that inside of UNC we will do this in the Start function here. We will lock the cursor, so we can actually access the curse by going cursor and then lockstate and this is equal to CursorLockMode.Locked. So the cursor will be stuck in the middle of the screen, and it will be invisible. So it’ll feel just like all those other FPS’es.

Now let’s get on to working on in the main part of this script which is gonna be actually rotating and moving the camera. And to do this we’re gonna not do it in the update function, but we’re gonna be doing it in the Late Update function. Now what the Late Update function is, is this is basically just like the Update function, but this runs at the end of the frame. So this runs after everything in the other update functions has already run.

And the reason for doing this, is because when the camera is attached to the player and we’re doing the rotations and all that, there can be some interference with how the player rotates compared to how the camera then rotates. So it can have some sort of jittering if we have this in the Update function. But having it in a Late Update function solves those issues.

So first thing we’re gonna do is we wanna get the mouse movement inputs. And to do that we can go rotX, so we’re gonna add to our X rotation, that is going to be done by plus equals input.GetAxis. And the axis we want to get is going to be Mouse X like so. And then, of course, we want to multiply that by our X sensitivity. And again for the Y we can go rotY plus equals input.GetAxis mouse Y and multiply that by our senseY just like that.

Okay, now what you want to do is you want to clamp the vertical rotation so that we can’t look all the way up, and then wrap back around as that can cause some issues with the rotation and cause the controls to actually flip. So we’re gonna be clamping the rotation so that it doesn’t do that, and we can only look so far vertically and so far down. So to do that we can go to rotY as Y is gonna be the up-and-down rotation and that is gonna be equal to the mathf.clamp. And we wanna send in the value where we want to clamp – that is rotY. The min, which is going to be minY, and Max, which is going to be the maxY, like so. Great,

With that done we can then check are we spectating or are we not spectating – or so are we alive or are we dead. So are we spectating? And for that we can just go if isSpectating, if isSpectator then we’ll do whatever’s in here. Otherwise, if we attach the player will do this, and the reason for this is because as well as having the movement when we’re a spectator, when we attach the player to our X rotate, we don’t actually rotate the camera horizontally. So we won’t be looking left and right, instead we’ll be rotating the player left and right. And the reason for that is so that we can easily have the player point in the forward direction that we’re looking (so we don’t have to do some other calculations later on in the player controller).

So let’s work here in the isSpectator first, as that’s what we’ll be setting up this lesson. So first of all we want to rotate the camera vertically, and to do that we’ll just go transform.rotation equals Quaternion.Euler. And we just wanna pass in our negative rotY and our rotX. We’re doing negative rotY because it is flips, if you do wish to have inverted Y controls, then you can just have that as rotY. Okay, and then for the Z rotation, we just want zero as we don’t want the camera tilting left and right.

And now for the movement, we can go here, and we can just go for our X input. We can go input.GetAxis horizontal, so this is going to be our horizontal input, and then we can go for our forward input. So when we’re in forward and backwards they can go equal to input.GetAxis vertical, so the up and down keys compared to the horizontal which is the left and right keys. And for the Y this can be equal to zero for now as we’re gonna be changing it down here.

Now for the Y we’re also gonna make it so that the player can move up and down and that’s gonna be done with the E and Q keys. So if input.GetKey, KeyCode.E then Y is gonna be equal to one else if input.GetKey, KeyCode.Q then we’re gonna be setting y to equal to negative one so they’ll move down. N

ow to apply that, we need to do a calculation right now to make it so that when we move, we’re moving in the direction that we’re looking. Because if we just applied these X, Z and Y directions to our transform at the moment, that would move us based on the global positions and rotations. So if we’re looking to the left we might instead move forward if we try and move left for example. So what we’re trying to do is we wanna make it so that no matter where we’re looking we will move forward, left, right and backwards relative to our rotation.

And for that we’ll create a Vector3, call that dir for direction and that will be equal to transform.right, so our right transform direction. So the direction that is to our right, multiply that by X plus transform.up, multiply by Y plus transform.forward, multiply it by Z. And with that, we can then apply that to our local position we’re going. Transform.position plus equals dir at the direction we want to travel times SpectatorMoveSpeed times Time.deltaTime (so it is independent of framerate), and we move at the exact same time no matter what framerate we have.

And that’s that, let’s actually hop now back into the editor here and test it out. Let’s actually go back in here and just set isSpectator to true for now manually, so that we can test it out. And for our X sensitivity, I will zoom in here. For our X sensitivity, we can set this to – and I’ll say 10 for now, Y is 10, min Y will set this to negative 90, Max Y 90. Spectator Move Speed will go 10. Okay and let’s press play and see if this works. See if we can look around. As you can see I can look around with the mouse, and with the arrow keys I can move like so. I can press E to go up, Q to go down.

In the next lesson, we’re gonna be starting on our player controller. Connecting up the rest of the camera to the player and finishing off the camera script when it’s actually attached to the player so that we rotate not only the camera, but the player as well to face the direction. Also when you’re in this mode you can’t really press the play button. So what you can do is you can either go press Escape to get the mouse like so and click it or you can just go control + P to toggle the plane like so. So yeah I’ll see you all in the next lesson.

Interested in continuing? Check out the full Battle Royale – Multiplayer Projects course, which is part of our Multiplayer Game Development Mini-Degree.

]]>