Working with Lumberyard’s Script Canvas: Project N.E.M.O Sample Now Available
Today, we’re excited to introduce a ready-to-use Amazon Lumberyard sample called Project N.E.M.O to help you get started with Lumberyard Script Canvas , our visual scripting tool.
We first gave you a sneak peek of Project N.E.M.O at GDC 2019. And following the release of Lumberyard 1.19, we’re happy to give you the full download so you can quickly get to grips with some of the features and workflows used to script common game play functions.
Project N.E.M.O (Nautical Emergency Maneuvers and Operations) is a complete game level sample that showcases some of the latest capabilities of Script Canvas. It’s a short obstacle navigation experience using a 3rd person camera to control a mini sub through an underwater mine field along with pickups to collect along the way.
When we first approached the challenge of building a new scripting system in Lumberyard, we wanted to build something that would benefit developers of all sizes – regardless of skill or expertise. Something that users with limited scripting skills could easily master, and at the same time provide a highly powerful tool for veteran game developers. On a technical level, it was also important that graphs stay small and focused on the immediate tasks, while providing the ability to talk across other scripts as needed.
Using these goals, we’ve created a scripting solution that offers two key elements. First, scripts are self-contained. Which means they allow clear direction to understand what functions are called. Second, they are easy to re-use or replace. Script files are their own file format and accessed by other entities or other events. Should it be required, this is a simple swap within an entities component properties. Node based scripting can get large and unwieldly when you need to address every form of functionality. Our approach allows for event driven scripts, letting you produce small scripts that don’t require complex logic to maintain states.
Below we’ve outlined the different game functions we created for N.E.M.O. It covers submarine functionality, mines and squid behavior, HUD display, pickups, world space UI, game ending and script events.
The submarine slice is the most complex element of this sample as it consists of all the visual, behavior, and player control elements.
The entity hierarchy for the Submarine is as follows:
Entities are grouped within parent entities to keep the submarine’s hierarchy organized and tidy. The different behaviors and effects that make up the submarine slice are grouped accordingly. Here’s a description of each:
- Meshes – This holds purely visual entities, they do not have any behavior, physics, or special effects.
- Effects -This holds all entities that have a particle effect component.
- Environment – This holds entities that are used to improve the art environment around the submarine.
- Illumination – Underwater games tend to be dark. To make the submarine really standout we added many lights around it for cosmetic purposes.
- Weapons -These entities have the components necessary for weapon behaviors, capturing user input and spawning projectiles.
- Camera – The player’s camera is bound at a distance from the submarine in order to control how the game looks.
- Propeller – This is an animated element of the submarine. When it moves forward the propeller spins clockwise. The behavior is procedurally provided in Script Canvas.
- Physics – This holds the elements required to perform collision detection against other physical entities.
- Bubblers – These effect entities have a particle component that emits bubbles as the submarine moves, and adjusts depending how fast it moves. The submarine is saved as a slice, this is a good practice to use when making complex entities as it allows you to create new instances of objects, as well as override parameters. And through slices, you can create varieties of objects.
- Movement – The submarine’s movement is generated by directly modifying the entity’s transform. This was a design decision in order to keep the demo easy to understand. However, there is a tradeoff. Because of this style of movement the submarine does not collide against the environment. In addition to player movement, we are also doing some procedural animation on the submarine itself; this gives the submarine a subtle “floating” motion to simulate being underwater.
Mines are explosive objects that spawn randomly from a Random Timed Spawner that spans the length of the playable space. They are physical objects that rely on gravity and buoyancy in order to give a realistic “falling through water” effect, as well as create hazards for the player to destroy or navigate around.
The Script Canvas graph for mines is responsible for detecting a collision and spawning an explosion when it happens.
When a mine explodes it also needs to deactivate itself in order to release the entity.
If the mine is destroyed by a player’s projectile it spawns the a world space UI and sends the DisplayWorldScore Script Event in order to update the value of the score to display and update the player’s score on the HUD.
The squid consists of two parts. The bottom part (the tentacles) are a separate entity from the top part. This allows the rotation of the tentacles separately from the body.
The body of the squid has a spawner component from which it randomly spawns projectiles.
Squids move vertically throughout their lifetime, if destroyed by the player they will spawn an explosion and deactivate themselves, otherwise they will continue moving vertically until their lifetime expires at which point they’ll deactivate themselves.
HUD (Heads Up Display)
The HUD in this demo consists of four elements; the game logo on the top left corner that fades out over time when the game starts, the score on the top right, ammo count on the bottom left, and the health on the bottom right.
In addition to the HUD there is also a damage feedback screen that is faded into view briefly when the player takes damage from mines or squid projectiles.
HUD UI Canvases
- Logo.uicanvas Displays the game’s logo on the top right when the game starts and fades away.
- HUD.uicanvas Manages the display of the player’s health, ammo & score.
- Damage.uicanvas Displays a full screen image to communicate that the player has taken damage.
- GameOver.uicanvas Displays the end of game screens (Success or Failure) if the player loses all health or crosses the trigger at the end of the level.
Pickups allow the player to collect a score. It works by using a trigger area as the mechanism to detect if a player has collided with it. The “On Area Entered” event from the trigger component handles the Script Canvas graph. It’s used to notify the game that a pickup occurred, and to spawn a world space UI entity that displays the score the player will receive for collecting this pickup.
World Space UI
When the player collects coins or destroys squids an entity that displays the score is spawned briefly.
This uses render to texture in order to render UI in world space, the entity consists of the following components:
- Look At Component – Aligns the entity to another specified entity, in this case, the player’s camera.
- Mesh – Uses a primitive_plane with a material override, the worldui000.mtl material. Notice that the Diffuse texture map is set to $worldscore, we will use this in order to bind the UI Canvas render to target with the texture map in this material.
- Script Canvas – Controls the movement of the entity, updating the UI canvas with the value of the score, fading out and destroying the entity.
- UI Canvas on Mesh – Allows us to specify a Render target override in order to use the render to target feature, we set this to $worldscore to match the Diffuse texture map of the material.
- UI Canvas Asset Ref – The UI Canvas for the score display.
Game end is determined in two ways, the first is if the player’s health reaches 0, in this case we display a mission failed screen.
The player crossing an “end of game” trigger determines mission success.
Script Events communicate information & data across entities and Script Canvas graphs. They allow us to create an event sent directly, or as a general broadcast and received then handled by. Below are descriptions of each:
Game Events (Broadcast)
This script event is used to communicate game level events, when the player crosses the end of level trigger or when the player’s health reaches 0. This displays the mission success/failed screens as well as displays the player’s total score.
Game Over <Score, Success>
Used to notify that the game is over. The score and the players success (or not), displays the correct screen.
Player Events (Broadcast)
These are game time events related to player actions:
When the player fires, this communicates to the HUD the remaining player’s ammo.
Collision <Force:Number, Type:String>
When the player collides against a mine or enemy projectile, this communicates the force of the collision and the type of damage.
When the player collects a coin, this communicates the points received in order to update the player’s score.
These are events used to communicate with the world space UI element that is spawned when the player collects coins or defeats squids.
This communicates to the world UI entity the value it should display depending on the score received for either picking up a coin or destroying a squid. It addresses directly to the world UI entity in order for it and only it to update and display this value.
OnPickup <Tag, Value>
Used to notify that the player has picked up an item, what kind of item and the value is used to determine the score.
This input binding controls the left/right movement of the submarine, it is bound to the gamepad’s left thumbstick X axis, and the A and D keys on the keyboard.
Event value multiplier -1.0
This input binding controls the up/down movement of the submarine, it is bound to the gamepad’s left thumbstick Y axis, and the Q and E keys on the keyboard
Event value multiplier: =-1.0
This input binding controls the forward and backwards motion of the submarine. It is bound to the gamepad’s right trigger and the W and S keys on the keyboard
Event value multiplier: = -1.0
This input binding controls the ability to shoot projectiles from the submarine. It is bound to the gamepad’s A button, the space bar on the keyboard and the left mouse button
To Install the N.E.M.O sample, copy the downloaded .zip file to your Lumberyard 1.19 dev folder. Unzip the files. Open Project Configurator and follow the user guide to switch to the N.E.M.O project. You’ll need to do a quick rebuild for content to work. You can find steps for the rebuild process in our documentation pages.
The Lumberyard team is working hard to get new features too you and there’s much more on the way. As always, we want your help in driving our roadmap and providing suggestions for future features, improvements, and learning materials. Send us feedback at Lumberyardfirstname.lastname@example.org.
This blog was co-authored by Lumberyard Creative Director Christo Vuchetich, and Software Development Engineer Luis Sempe.