All Projects → amethyst → Legion

amethyst / Legion

Licence: mit
High performance Rust ECS library

Programming Languages

rust
11053 projects

Labels

Projects that are alternatives of or similar to Legion

Ecs Refarch Continuous Deployment
ECS Reference Architecture for creating a flexible and scalable deployment pipeline to Amazon ECS using AWS CodePipeline
Stars: ✭ 776 (-26.02%)
Mutual labels:  ecs
Mu
A full-stack DevOps on AWS framework
Stars: ✭ 948 (-9.63%)
Mutual labels:  ecs
Endless Runner Entitas Ecs
Runner template for Unity
Stars: ✭ 41 (-96.09%)
Mutual labels:  ecs
Feather
A Minecraft server implementation in Rust
Stars: ✭ 896 (-14.59%)
Mutual labels:  ecs
Ecsctl
Command-line tool for managing AWS Elastic Container Service and Projects to run on it.
Stars: ✭ 15 (-98.57%)
Mutual labels:  ecs
Specs Hierarchy
A generic scene graph extension for Specs
Stars: ✭ 34 (-96.76%)
Mutual labels:  ecs
Aliyun Sdk Js
阿里云 SDK for Javascript,支持在浏览器和 Nodejs 环境使用,支持大部分阿里云服务。
Stars: ✭ 727 (-30.7%)
Mutual labels:  ecs
Ecs Dotnet
.NET integrations that use the Elastic Common Schema (ECS)
Stars: ✭ 46 (-95.61%)
Mutual labels:  ecs
Ecs
A simple and easy to use entity-component-system C++ library
Stars: ✭ 20 (-98.09%)
Mutual labels:  ecs
Waliyun
阿里云Node.js Open API SDK(完整版)
Stars: ✭ 40 (-96.19%)
Mutual labels:  ecs
Ecs.hpp
C++17 Entity Component System
Stars: ✭ 25 (-97.62%)
Mutual labels:  ecs
Alibaba Cloud Sdk Go
Alibaba Cloud SDK for Go
Stars: ✭ 876 (-16.49%)
Mutual labels:  ecs
Terraform Aws Ecs Fargate
Terraform module which creates ECS Fargate resources on AWS.
Stars: ✭ 35 (-96.66%)
Mutual labels:  ecs
Unitymmo
an unity mmo demo, base on ecs(game play), xlua(ui)
Stars: ✭ 780 (-25.64%)
Mutual labels:  ecs
Ecs Snake
Simple snake game powered by ecs framework.
Stars: ✭ 41 (-96.09%)
Mutual labels:  ecs
Aliyungo
Go SDK for Aliyun (Alibaba Cloud) - Golang API for ECS, OSS, DNS, SLB, RDS, RAM, MNS, STS, SLS, MQ, Push, OpenSearch, DM, Container Service etc.
Stars: ✭ 756 (-27.93%)
Mutual labels:  ecs
Aws Scalable Big Blue Button Example
Demonstration of how to deploy a scalable video conference solution based on Big Blue Button
Stars: ✭ 29 (-97.24%)
Mutual labels:  ecs
Unity Jobsystem Boids
No ECS, Job system and Burst only minimalist boids sample
Stars: ✭ 50 (-95.23%)
Mutual labels:  ecs
Amazon Ecs
With Laravel, search and lookup Amazon products easily.
Stars: ✭ 43 (-95.9%)
Mutual labels:  ecs
Ecs Monitor
A simple monitoring solution for Amazon's Elastic Container Service (ECS)
Stars: ✭ 40 (-96.19%)
Mutual labels:  ecs
Legion ECS

Build Status Crates.io Docs.rs

Legion aims to be a feature rich high performance Entity component system (ECS) library for Rust game projects with minimal boilerplate.

Getting Started

Worlds

Worlds are collections of entities, where each entity can have an arbitrary collection of components attached.

use legion::*;
let world = World::default();

Entities can be inserted via either push (for a single entity) or extend (for a collection of entities with the same component types). The world will create a unique ID for each entity upon insertion that you can use to refer to that entity later.

// a component is any type that is 'static, sized, send and sync
#[derive(Clone, Copy, Debug, PartialEq)]
struct Position {
    x: f32,
    y: f32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
struct Velocity {
    dx: f32,
    dy: f32,
}

// push a component tuple into the world to create an entity
let entity: Entity = world.push((Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }));

// or extend via an IntoIterator of tuples to add many at once (this is faster)
let entities: &[Entity] = world.extend(vec![
    (Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }),
    (Position { x: 1.0, y: 1.0 }, Velocity { dx: 0.0, dy: 0.0 }),
    (Position { x: 2.0, y: 2.0 }, Velocity { dx: 0.0, dy: 0.0 }),
]);

You can access entities via entries. Entries allow you to query an entity to find out what types of components are attached to it, to get component references, or to add and remove components.

// entries return `None` if the entity does not exist
if let Some(mut entry) = world.entry(entity) {
    // access information about the entity's archetype
    println!("{:?} has {:?}", entity, entry.archetype().layout().component_types());

    // add an extra component
    entry.add_component(12f32);

    // access the entity's components, returns `None` if the entity does not have the component
    assert_eq!(entry.get_component::<f32>().unwrap(), &12f32);
}

Queries

Entries are not the most convenient or performant way to search or bulk-access a world. Queries allow for high performance and expressive iteration through the entities in a world.

// you define a query be declaring what components you want to find, and how you will access them
let mut query = <&Position>::query();

// you can then iterate through the components found in the world
for position in query.iter(&world) {
    println!("{:?}", position);
}

You can search for entities which have all of a set of components.

// construct a query from a "view tuple"
let mut query = <(&Velocity, &mut Position)>::query();

// this time we have &Velocity and &mut Position
for (velocity, position) in query.iter_mut(&mut world) {
    position.x += velocity.x;
    position.y += velocity.y;
}

You can augment a basic query with additional filters. For example, you can choose to exclude entities which also have a certain component, or only include entities for which a certain component has changed since the last time the query ran (this filtering is conservative and coarse-grained)

// you can use boolean expressions when adding filters
let mut query = <(&Velocity, &mut Position)>::query()
    .filter(!component::<Ignore>() & maybe_changed::<Position>());

for (velocity, position) in query.iter_mut(&mut world) {
    position.x += velocity.dx;
    position.y += velocity.dy;
}

There is much more than can be done with queries. See the module documentation for more information.

Systems

You may have noticed that when we wanted to write to a component, we needed to use iter_mut to iterate through our query. But perhaps your application wants to be able to process different components on different entities, perhaps even at the same time in parallel? While it is possible to do this manually (see World::split), this is very difficult to do when the different pieces of the application don't know what components each other need, or might or might not even have conflicting access requirements.

Systems and the Schedule automates this process, and can even schedule work at a more granular level than you can otherwise do manually. A system is a unit of work. Each system is defined as a function which is provided access to queries and shared resources. These systems can then be appended to a schedule, which is a linear sequence of systems, ordered by when side effects (such as writes to components) should be observed. The schedule will automatically parallelize the execution of all systems whilst maintaining the apparent order of execution from the perspective of each system.

// a system fn which loops through Position and Velocity components, and reads the Time shared resource
// the #[system] macro generates a fn called update_positions_system() which will construct our system
#[system(for_each)]
fn update_positions(pos: &mut Position, vel: &Velocity, #[resource] time: &Time) {
    pos.x += vel.dx * time.elapsed_seconds;
    pos.y += vel.dy * time.elapsed_seconds;
}

// construct a schedule (you should do this on init)
let mut schedule = Schedule::builder()
    .add_system(update_positions_system())
    .build();

// run our schedule (you should do this each update)
schedule.execute(&mut world, &mut resources);

See the systems module and the system proc macro for more information.

Feature Flags

Legion provides a few feature flags:

  • parallel - Enables parallel iterators and parallel schedule execution via the rayon library. Enabled by default.
  • extended-tuple-impls - Extends the maximum size of view and component tuples from 8 to 24, at the cost of increased compile times. Off by default.
  • serialize - Enables the serde serialization module and associated functionality. Enabled by default.
  • crossbeam-events - Implements the EventSender trait for crossbeam Sender channels, allowing them to be used for event subscriptions. Enabled by default.

WASM

Legion runs with parallelism on by default, which is not currently supported by Web Assembly as it runs single-threaded. Therefore, to build for WASM, ensure you set default-features = false in Cargo.toml. Additionally, if you want to use the serialize feature, you must enable either the stdweb or wasm-bindgen features, which will be proxied through to the uuid crate. See the uuid crate for more information.

legion = { version = "*", default-features = false, features = ["wasm-bindgen"] }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].