### Leveling up Game Development
*with*
# Rust
<img src="https://i.redd.it/rhq3ezvso9611.png" alt="drawing" width="500"/>
Note:
I'm excited to be giving my talk today about game development in Rust.
So, let's dive into Leveling up Game Development with Rust!
---
## *Hi, I'm Forest!*
- Student in Ottawa @ Carleton :flag-ca:
- Github Campus Expert
- I :heart: open source
- Rustacean!
<img src="https://cdn.discordapp.com/attachments/444005079410802699/931241589093843034/cB5k6xa8JVCCGEWOH8f6jxr46WWnAAAAAElFTkSuQmCC.png" alt="drawing" width="200"/>
Note:
Hi, I'm Forest! I'm a student in Ottawa, at Carleton University. I'm studying computer science, with honours in game development.
I also love working on open source projects. I'll tell you about some of them in a bit.
I'm also a Rustacean! You'll probably see Ferris several times throughout this talk, so keep an eye out for them!
---
# This talk
- Overview of game development
- Features of Rust
- Entity Component Systems
- Rust gamedev ecosystem
- Conclusion
Note:
Before we get started, I'm going to break down what the layout of this talk will look like.
First, we're going to look at an overview of game development, and some of the challenges involved with it.
Next, we're going to learn about what the Rust language is, and explore the features that are relevant to game development.
We're then going to explore a dominant pattern for game development in Rust, the Entity Component System.
Next, we'll examine the current state of the Rust gamedev ecosystem.
We'll finish off by looking at what you can do to get involved in this world.
---
## Problem Statement
Note:
First, let's look at the problem statement.
Video games are intricate programs that require a lot of planning and collaboration to create.
----
## Games are realtime
33 milliseconds per loop
Note:
They're real-time applications, and often run in loops that must execute in under 30 milliseconds, or over 30 times a second.
----
## Games are complex
Tons of systems interacting
Note:
Further, games are comprised of many systems that are working together.
This includes AI, rendering, game logic, networking, and many other systems.
----
## Games are data-driven
Lots of state
Note:
All of these moving parts operate on underlying data shared between them.
We need good abstractions for working with this data
----
## To Recap
- Frames need to be quick and reliable
- Teams must work together with ease
- Data must be easy to manipulate
Note:
So, to recap, we need to be rendering frames quickly and reliably.
Cross-discipline teams working on games need to work on different systems cohesively together.
Finally, we need to have easy access to the underlying data.
----
### Words of warning
<img src="https://www.pinclipart.com/picdir/big/173-1736275_explain-alarmed-ferris-convention-rust-lang-clipart.png" alt="drawing" width="200"/>
Note:
However, we should also briefly set some expectations.
I'll be going over lots of improvements to game development that might not be clear to someone just entering the field for the first time.
When developing games with rapid iteration times, such as for a game jam, I tend to use a higher-level game engine, like Godot.
That said, it's important to not try to solve every problem before you know the question.
It's easy to fall into a rabbit hole of over-engineering.
I do also want to acknowledge that this talk does have some complex ideas, so don't worry if you don't understand it all! I'll be available during the whole conference on Discord, so feel free to reach out to me to ask more questions.
---
<!-- ========== -->
<!-- Rust Intro -->
<!-- ========== -->
# Rust
![](https://tutsnode.com/wp-content/uploads/2020/12/Rust-lang-The-complete-beginners-guide.jpg)
Note:
Now, let's get started with the real premise here.
I'm going to start by adding a bit more to my intro.
----
## Veloren
![](https://cdn.discordapp.com/attachments/539518074106413056/931181583308832768/ezgif.com-gif-maker.gif)
Note:
Within the Rust world, I'm currently working on a game called Veloren.
I'm one of the core developers of the game, where, among other things, I work on continuous integration, cross-compilation, and outreach.
----
## Rust Gamedev WG
<iframe allowtransparency="true" style="background: #FFFFFF" width="100%" height="500" src="https://gamedev.rs/" frameborder="2";></iframe>
Note:
I'm also a team member of the Rust gamedev working group.
On that team, I focus on editing the monthly newsletter, running a monthly meetup, and co-hosting the Rust gamedev podcast.
---
<!-- ==== -->
<!-- Rust -->
<!-- ==== -->
# What is Rust?
Note:
Now, let's dive into Rust.
----
### Rustlang
- Systems language
- Compiled
- Concurrent
<img src="http://www.arewelearningyet.com/images/rust-9000.png" alt="drawing" width="200"/>
Note:
Rust is a systems language.
It's a compiled language, and is most often compared to C or C++.
However, it has many inspirations from other languages.
It borrows from the functional paradigm, and also has a strong type system.
It's also very expressive.
We often feel that it is easier to accomplish our goal in Python than in C++, but then arrive at a point where we wish we had the structure that C++ provided.
However, in Rust, we can have the best of both of these worlds.
---
## Compiler == ⚔️ == 💖
Note:
This has led to some popular sayings in Rust.
The first, "fighting the compiler", comes from not being allowed to compile your code until all the rules are followed.
The second, "if it compiles, it probably works", is where we reap the rewards of our labour.
----
### Contract with the Compiler
![](https://media2.giphy.com/media/Pjlkz2Qk6Qsi2NkSfW/giphy.gif?cid=ecf05e472780w5pg7t0iw8i5ctuksysqu9hjz3skkl9dzxp7&rid=giphy.gif&ct=g)
Note:
In effect, we're signing a contract with the compiler.
By following rules more strict than in other languages, we are able to have more trust in our programs while they run.
----
## 👩🦰 🧑🦱 🧑🦳 👩🦱 👍
Note:
In terms of game development, this guarantee means a lot.
It means that while working on large cross-discipline teams, we can trust the compiler to prevent us from hurting others unintentionally.
If we can compile our code locally, we can be more sure it will merge with the code of others.
Most importantly, this contract spans the whole codebase.
Whether code touches several systems or just one; the same requirements must be met.
Mistakes you make that affect code on the other side of the codebase can be super difficult to track down, especially without the right tooling.
---
## Fearless Concurrency
Note:
Memory safety gives us another of Rust's pillars, "fearless concurrency".
This is the idea that if we want code to pass data across thread boundaries, we can stay safe.
This helps run parallelized code without the fear of data races. Let's break this down a bit.
CPUs today aren't getting much better at single-core performance.
In terms of classical CPUs, Moore's law is dying.
However, the number of cores in CPUs is increasing rapidly.
Because of this, performance in the modern age of computing is becoming synonymous with distributing work.
We hear the term "horizontally scaling" a lot in modern cloud development.
So when we care about performance, we really need to be figuring out how to run our code efficiently across many threads on our system.
---
## Error handling
Note:
Next, let's take a look at error handling in Rust.
Errors happen when you haven't defined how your program should handle some edge case that it has come across.
Making sure that we're able to handle errors is essential in game development.
We don't want our games crashing for players during a multi-hour gaming session.
----
## Crashing accidentally is *hard*
*But possible of course*
Note:
In Rust, crashing a program is easy.
Like many other languages, you have a way of throwing an exception, called "panicking".
However, when you're not actively trying to crash, it's surprisingly hard to have it happen by accident.
----
## No segfaults
![](https://cdn.discordapp.com/attachments/444005079410802699/931258557897244712/Youre_dereferencing_a_null_pointer.gif)
Note:
As I mentioned before, Rust's compiler prevents segfaults.
If you have experience with C or C++, you're surely familiar with debugging crashes of this nature.
Without the worry of segfaulting from a vast array of reasons, we've already made the error handling task easier.
----
## You must deal with areas
## that can crash
Note:
Now, let's look at areas where the program fails and need to recover.
----
```rust=
let number_string = "27";
let number = number_string.parse::<i32>().unwrap();
```
Note:
Here's an example of that.
We're converting a string to a number.
Easy enough, we parse it to the i32 type, and then we do something called "unwrap"
What happens if the string isn't a number though?
----
```rust=
let number_string = "12ab34";
let number = number_string.parse::<i32>().unwrap();
```
```shell=
thread 'main' panicked
called `Result::unwrap()` on an `Err`
value: ParseIntError { kind: InvalidDigit }
```
<img src="https://user-images.githubusercontent.com/689247/27258101-0dde5842-53a6-11e7-9759-23f285d0fd70.png" alt="drawing" width="200"/>
Note:
Oh no! We see that the program panicked while it was running.
We've even got Ferris panicking!
Didn't I promise that this wouldn't happen?
Well, not exactly. I promised that it wouldn't happen *accidentally*.
What the second line says is take the string, and try parsing it as an i32.
What I get back from that is a Rust Result.
A result can be one of two variants; either Ok, or an Err.
By using "unwrap" on it, I'm saying "I believe you're the Ok variant, and I want what you contain".
However, "unwrap" will panic if it receives the Err variant.
But this was my fault!
I told the compiler that it would always be ok, and I lied.
In that case, it's more helpful for the program to crash so that I know an edge case was reached that I didn't anticipate.
----
```rust=
let number_string = "12ab34";
let number = match number_string.parse::<i32>() {
Ok(num) => num,
Err(_) => 0,
};
```
<img src="https://i.imgur.com/XhqemgE.png" alt="drawing" width="200"/>
Note:
Here's an example of how to handle this error properly.
There is a bit more syntax here, so let's walk through it.
On lines two through four, we're now matching against the two Result variants, Ok and Err.
The match statement is similar to switch cases in other languages.
We're saying that if the parsing returned an Ok, we'll take the number out of it, and return it.
But then we also say that if it was an Err, we'll just return 0.
The underscore means that we don't want to extract the rest of the information about the Err.
The error is now handled, and Ferris is happy again!
---
## To Recap
- Rust is memory safe
- Code can be parallelized easily
- Error handling is powerful
Note:
To recap what we've seen here, Rust is memory safe as a non-garbage-collected language.
This has many benefits, including the fact that we can parallelize code easily.
Finally, we must always acknowledge places where errors can happen by handling them in some way.
---
<!-- === -->
<!-- ECS -->
<!-- === -->
## Entity Component Systems
Note:
Now that we've explored some foundational benefits that Rust provides for game development, we're going to dive into patterns that work well for game development in Rust.
---
## Objected Oriented Programming
<img src="https://media.geeksforgeeks.org/wp-content/cdn-uploads/20190501121513/inheritance.png" alt="drawing" width="400"/>
Note:
When coding in other languages, we're often most familiar with object-oriented programming.
We can model data through abstractions such as inheritance and polymorphism.
We hear the classic "a dog and cat can both inherit attributes from animal".
---
## ~~Objected Oriented Programming~~
Note:
Rust, however, is not an object-oriented language.
It does have structs that can be used to model data, but there is no inheritance.
---
## Entity
## Component
## System
Note:
We're going to take a look at Entity Component Systems, or ECS. ECS is an architecture pattern.
Let's break down what an ECS is. At its core, an ECS is just an API that gives you a way to access and manipulate data in arrays. An ECS follows a principle of composition over inheritance. By this, I mean instead of creating entities that inherit from base classes, entities are built using components. We can break down "ECS" into its three terms: entity, component, and system.
----
## Entity
Note:
Starting with Entity, we have just an ID. What an entity is gets defined by the components that are attached to it, so we keep the idea of "entity" as lean as possible. This also means that any base "entity" can take the shape of anything, whether it be a cat, a sound emitter, a tree, a car, or anything we might call an "object".
----
## Component
Note:
Next, we have components. This is where all the data goes. We can think of components as "the entity has a...". Entities can have an arbitrary number of components, all of which represent some different type of data.
And components of the same type store the same data regardless of the entity they're attached to. For example, a "position" component might include x and y integers, and any entity that gets this component will then be able to store its x and y position.
----
## System
Note:
Finally, we have systems. Systems allow us to query and manipulate data. A system works on components mostly outside of the context of what they make up. For example, I could ask for every entity that has a position component and a velocity component, and update the position based on velocity. In this example, I didn't care what the full entity represents; only that I need to update everything that has a position and velocity. This allows us to cover the OOP case of "a dog and a cat" since both would have these position and velocity components!
----
## Memory layout
Note:
Although there are different ways to implement an ECS library/framework, one popular way is one that resembles the design of a database. We can compare this method to a relational database, without the need to store to disk. Each entity has an ID, and stores IDs of components that it has. Components can then be easily stored in their own tables.
---
## What's that Entity?!?
<hr>
| Components | 0 | 1 | 2 | 3 |
|------------ |--- |--- |--- |--- |
| Position | x | x | x | x |
| Velocity | x | x | | |
| Health | x | | x | |
| AI | | x | | |
| Minable | | | x | |
Note:
Let's look at what some sample data might look like with the ECS model.
We have 4 entities here, with IDs 0 through 3. We can see them on the top row.
We also have 4 components that we can see on the left.
Now, try to think about what each entity could represent.
Remember, we're thinking in terms of "entity zero has a position, velocity, and health".
But we're also saying that it doesn't have an AI component, or a minable component.
Also, the implementation of these components is unclear, so it might represent more than one thing.
When I created this, I was thinking entity 0 could be a player character.
It needs to move around the world, so it needs velocity. But it doesn't need the AI component, since it's playable.
I imagined entity 1 to be an NPC character. In this game, NPC characters can't die, so they have no need for health.
Entity 2 is a bit different; it doesn't have a velocity component, but it does have a health component. What could that be?
In this case, I imagined it to be a rock that you could mine from. This is why it has the "minable" component.
A system could iterate over each entity that has the "minable" component each frame, and if it has received damage, maybe drop some resources near it.
Finally, we have entity 3.
It's similar to entity 2 but doesn't have the minable component.
I imagined it to be a tree in the world.
We don't want the player to destroy the beautiful trees in our towns, so it doesn't have health.
All it needs is a position!
Also note, I left it quite ambiguous as to if this was a 2D or 3D game.
Since we're modeling underlying data, we don't really need to know how the actual game will look.
---
## ECS Parallelization
Note:
Entity Component Systems not only allow us to model data differently but also operate on it rapidly and safely. One reason for this is how easy it is to parallelize with different CPU threads. Let's say each frame, we need to update the position of 10,000 entities based on their velocity. It's very easy for us to send the first half of this to one thread, and the second half to another thread. Or divide it down into as many threads as there are.
---
## To Recap
- ECS is an alternative to OOP
- Entities "have a \<component\>"
- Systems run on certain components
Note:
To recap, Entity Component Systems are an alternative to structuring data in an Object-Oriented way
We can say that entities "have a certain component", or several of them
Systems are able to pick and choose which components they run on
---
<!-- ========= -->
<!-- Ecosystem -->
<!-- ========= -->
# What is the Ecosystem?
Note:
Finally, we'll end off this talk with a look at the state of Rust game development.
----
## Are we game yet
<iframe allowtransparency="true" style="background: #FFFFFF" width="100%" height="500" src="https://arewegameyet.rs/" frameborder="2";></iframe>
Note:
With many domains in Rust, the best place to search for information is areweXyet. In this case, the game development ecosystem can be explored at arewegameyet. This site shows lots of games being developed in Rust, as well as tools, and other crates.
As you can see, we can view the crates available from many categories relevant to game development.
----
# Engines
<img src="https://repository-images.githubusercontent.com/234798675/18016580-dab2-11ea-9864-452f7149499c" alt="drawing" width="400"/>
<img src="https://repository-images.githubusercontent.com/48364554/2e8fd885-9025-4b7a-943a-4e9a40c3f331" alt="drawing" width="400"/>
<img src="https://github.com/FyroxEngine/Fyrox/raw/master/pics/logo.png" alt="drawing" width="150"/>
Note:
In the area of game engines, several large projects are paving the way. The most popular right now is Bevy, which just released its 0.6 version. Bevy focuses on the idea of the ECS controlling everything about the engine; from the data, to the UI, to the renderer. It took the Rust ecosystem by storm, as it built from the experiences of existing engines. There are also several other engines that are quite popular. Fyrox has a scene editor that already allows for very powerful 3D world-creation tooling. Amethyst has been a staple in the ecosystem for a while, although it's coming to the end of its maintenance cycle.
----
## Embark Studios
<img src="https://media-exp1.licdn.com/dms/image/C561BAQFZkGxRPdpzCA/company-background_10000/0/1555070185820?e=2159024400&v=beta&t=oan3kUc6Eu84lNGN_sz3fn1ixjU4KYJzItD-CXA9WJM" alt="drawing" width="600"/>
Note:
In terms of the industry, there is currently one company that is pushing forward quite heavily in this space. Embark is a game studio in Stolkholm, Sweden, that is working on a dozen or so open source projects in the game development and graphics ecosystem. This is to help them with games they are developing, but also pushes forward the agenda on what others can make use of. One of their major projects is RustGPU, which aims to allow shader code for GPUs that is written in Rust.
----
## Upcoming
Note:
There is a lot of movement happening in the Rust gamedev ecosystem right now. From recent newsletters, we've seen several games that are getting releases on Steam. Also, more initiatives and events are starting to take place. The Rusty Jam is going to run its second game jam soon, and the Rust gamedev podcast has an exciting 2022 planned.
---
<!-- ========== -->
<!-- Conclusion -->
<!-- ========== -->
## What can you do?
- Read the Rust book!
- Playing with Bevy
- Contributing to Veloren
Note:
Now that we're at the end of the talk, I want to show you some ways you can get started if you like. I'd highly recommend starting by reading the Rust book. It will give you a good foundation for the rest of the language, and explore principles I've discussed here in much more depth.
Going through the Bevy tutorial can be a good way to get introduced to using an Entity Component System.
Another opportunity is looking to contribute to Veloren or other Rust projects. In fact, many of Veloren's developers started using Rust for the first time to contribute to the game. There are many areas that don't require too much experience to get started with. We've recently been running what we like to call the Veloren Reading Club, where one of the core devs breaks down some of the more intricate systems.
{"metaMigratedAt":"2023-06-17T20:45:13.562Z","metaMigratedFrom":"YAML","title":"Leveling Up Game Development with Rust","breaks":true,"slideOptions":"{\"center\":true,\"transition\":\"slide\",\"showNotes\":false,\"allottedMinutes\":15}","contributors":"[{\"id\":\"db349910-53c1-45a5-aa34-1ac5434980b0\",\"add\":53282,\"del\":32086}]"}