Small game engine - trying to implement component system


#1

Hi, first time poster and rust newbie here!

In order to learn graphics programming and rust itself, I’ve decided to try writing a (very small) game engine. All of my former experience in game programming stems almost exclusively from the Unity game engine.
I’m trying to use some of it’s patterns, one of which is the “game object - component” system, where each game object has a list of components of different types all inheriting from the same base class. Each game object has a method

GetComponent<T>();

which returns the component on the game object of the specified type.

My idea for an implementation looked something like this (written in rusty pseudocode):

pub struct GameObject<'w> {
    components: Vec<&'w mut Component>,
}

impl<'w> GameObject<'w> {

    pub fn components(&self) -> Vec<&'w Component> {
        self.components.into_iter().map(|c| &*c).collect()
    }

    pub fn get_component<T>(&self) -> T
    where T: Component
    {
        let component = self.components().retain(|&c| c.type == T.type)[0]; //need some way to compare types
        component as T                                                      //and some way to downcast the component
    }
}

I think the code should explain my problem, do you guys have any idea how to solve it?


#2

I believe the common term for what you’re doing is “Entity-Component System” (ECS)

TL;DR: ECS are (way) harder, but (way) more awesome in Rust

This particular thing is hard to do in Rust, because ECS boils down to “any object can access any component all the time” (bullets writing to the health of player, players inspecting the contents of a chest, chests colliding with bullets, etc.)
This conflicts very much with the data race guarantees that Rust holds sacred, making it quite hard to implement.
If you were looking for a “simple” project to play around with, I’m afraid you’re better off trying something else.

With that out of the way, ECS in Rust is hard, but not impossible.
There is the SPECS project, which is trying to build an ECS in pure Rust.
SPECS’s idea is that, if you get all the fiddling and fencing with the compiler correct (hard!), Rust lets you do multithreading things that no (sane) C-developer would even dream of, because without Rust’s guarantees it’s a racy, crashy, segfaulting, memory-safety minefield.

Specs works, and being used in the Amethyst Engine, although it’s still very much in development. I can really recommend having a look at it if this sort of thing interests you!


#3

Ok, I took a look at SPECS and it sounds very interesting. I think I’ll try to use it.