{"id":13503968,"url":"https://github.com/amethyst/legion","last_synced_at":"2025-12-12T11:40:27.693Z","repository":{"id":39166051,"uuid":"174642569","full_name":"amethyst/legion","owner":"amethyst","description":"High performance Rust ECS library","archived":false,"fork":false,"pushed_at":"2021-12-30T19:05:52.000Z","size":2475,"stargazers_count":1669,"open_issues_count":95,"forks_count":134,"subscribers_count":36,"default_branch":"master","last_synced_at":"2025-05-07T11:51:33.504Z","etag":null,"topics":["ecs","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amethyst.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":["https://amethyst.rs/donate"],"open_collective":"amethyst"}},"created_at":"2019-03-09T03:17:06.000Z","updated_at":"2025-05-06T08:19:36.000Z","dependencies_parsed_at":"2022-07-20T00:02:07.845Z","dependency_job_id":null,"html_url":"https://github.com/amethyst/legion","commit_stats":null,"previous_names":["tomgillen/legion"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amethyst%2Flegion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amethyst%2Flegion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amethyst%2Flegion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amethyst%2Flegion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amethyst","download_url":"https://codeload.github.com/amethyst/legion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254149957,"owners_count":22022851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecs","rust"],"created_at":"2024-07-31T23:00:51.283Z","updated_at":"2025-12-12T11:40:22.284Z","avatar_url":"https://github.com/amethyst.png","language":"Rust","readme":"\u003cimg src=\"docs/book/splash.png\" alt=\"Legion ECS\" /\u003e\n\n[![Build Status][build_img]][build_lnk] [![Crates.io][crates_img]][crates_lnk] [![Docs.rs][doc_img]][doc_lnk]\n\n[build_img]: https://github.com/TomGillen/legion/workflows/CI/badge.svg\n[build_lnk]: https://github.com/TomGillen/legion/actions\n[crates_img]: https://img.shields.io/crates/v/legion.svg\n[crates_lnk]: https://crates.io/crates/legion\n[doc_img]: https://docs.rs/legion/badge.svg\n[doc_lnk]: https://docs.rs/legion\n\nLegion aims to be a feature rich high performance [Entity component system](https://en.wikipedia.org/wiki/Entity_component_system) (ECS) library for Rust game projects with minimal boilerplate.\n\n## Getting Started\n\n### Worlds\n\n[Worlds](https://docs.rs/legion/latest/legion/world/struct.World.html) are collections of [entities](https://docs.rs/legion/latest/legion/struct.Entity.html), where each entity can have an arbitrary collection of [components](https://docs.rs/legion/latest/legion/storage/trait.Component.html) attached.\n\n```rust\nuse legion::*;\nlet world = World::default();\n```\n\nEntities 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.\n\n```rust\n// a component is any type that is 'static, sized, send and sync\n#[derive(Clone, Copy, Debug, PartialEq)]\nstruct Position {\n    x: f32,\n    y: f32,\n}\n#[derive(Clone, Copy, Debug, PartialEq)]\nstruct Velocity {\n    dx: f32,\n    dy: f32,\n}\n\n// push a component tuple into the world to create an entity\nlet entity: Entity = world.push((Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }));\n\n// or extend via an IntoIterator of tuples to add many at once (this is faster)\nlet entities: \u0026[Entity] = world.extend(vec![\n    (Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }),\n    (Position { x: 1.0, y: 1.0 }, Velocity { dx: 0.0, dy: 0.0 }),\n    (Position { x: 2.0, y: 2.0 }, Velocity { dx: 0.0, dy: 0.0 }),\n]);\n```\n\nYou can access entities via [entries](https://docs.rs/legion/latest/legion/world/struct.Entry.html). 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.\n\n```rust\n// entries return `None` if the entity does not exist\nif let Some(mut entry) = world.entry(entity) {\n    // access information about the entity's archetype\n    println!(\"{:?} has {:?}\", entity, entry.archetype().layout().component_types());\n\n    // add an extra component\n    entry.add_component(12f32);\n\n    // access the entity's components, returns `None` if the entity does not have the component\n    assert_eq!(entry.get_component::\u003cf32\u003e().unwrap(), \u002612f32);\n}\n```\n\n### Queries\n\nEntries are not the most convenient or performant way to search or bulk-access a world. [Queries](https://docs.rs/legion/latest/legion/query/index.html) allow for high performance and expressive iteration through the entities in a world.\n\n```rust\n// you define a query be declaring what components you want to find, and how you will access them\nlet mut query = \u003c\u0026Position\u003e::query();\n\n// you can then iterate through the components found in the world\nfor position in query.iter(\u0026world) {\n    println!(\"{:?}\", position);\n}\n```\n\nYou can search for entities which have all of a set of components.\n\n```rust\n// construct a query from a \"view tuple\"\nlet mut query = \u003c(\u0026Velocity, \u0026mut Position)\u003e::query();\n\n// this time we have \u0026Velocity and \u0026mut Position\nfor (velocity, position) in query.iter_mut(\u0026mut world) {\n    position.x += velocity.x;\n    position.y += velocity.y;\n}\n```\n\nYou 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)\n\n```rust\n// you can use boolean expressions when adding filters\nlet mut query = \u003c(\u0026Velocity, \u0026mut Position)\u003e::query()\n    .filter(!component::\u003cIgnore\u003e() \u0026 maybe_changed::\u003cPosition\u003e());\n\nfor (velocity, position) in query.iter_mut(\u0026mut world) {\n    position.x += velocity.dx;\n    position.y += velocity.dy;\n}\n```\n\nThere is much more than can be done with queries. See the [module documentation](https://docs.rs/legion/latest/legion/query/index.html) for more information.\n\n### Systems\n\nYou 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](https://docs.rs/legion/latest/legion/world/struct.World.html#method.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.\n\n[Systems](https://docs.rs/legion/latest/legion/systems/index.html) and the [Schedule](https://docs.rs/legion/latest/legion/struct.Schedule.html) 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](https://docs.rs/legion/latest/legion/struct.Resources.html). 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.\n\n```rust\n// a system fn which loops through Position and Velocity components, and reads the Time shared resource\n// the #[system] macro generates a fn called update_positions_system() which will construct our system\n#[system(for_each)]\nfn update_positions(pos: \u0026mut Position, vel: \u0026Velocity, #[resource] time: \u0026Time) {\n    pos.x += vel.dx * time.elapsed_seconds;\n    pos.y += vel.dy * time.elapsed_seconds;\n}\n\n// construct a schedule (you should do this on init)\nlet mut schedule = Schedule::builder()\n    .add_system(update_positions_system())\n    .build();\n\n// run our schedule (you should do this each update)\nschedule.execute(\u0026mut world, \u0026mut resources);\n```\n\nSee the [systems module](https://docs.rs/legion/latest/legion/systems/index.html) and the [system proc macro](https://docs.rs/legion/latest/legion/attr.system.html) for more information.\n\n## Feature Flags\n\nLegion provides a few feature flags:  \n\n* `parallel` - Enables parallel iterators and parallel schedule execution via the rayon library. Enabled by default.\n* `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.\n* `serialize` - Enables the serde serialization module and associated functionality. Enabled by default.\n* `crossbeam-events` - Implements the `EventSender` trait for crossbeam `Sender` channels, allowing them to be used for event subscriptions. Enabled by default.\n\n## WASM\n\nLegion 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](https://github.com/uuid-rs/uuid#dependencies) for more information.\n\n```toml\nlegion = { version = \"*\", default-features = false, features = [\"wasm-bindgen\"] }\n```\n","funding_links":["https://amethyst.rs/donate","https://opencollective.com/amethyst"],"categories":["Libraries","Rust","Libraries \u0026 Frameworks:","库 Libraries","[ECS Libraries](#contents)"],"sub_categories":["Game development","ECS","游戏开发 Game development"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famethyst%2Flegion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famethyst%2Flegion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famethyst%2Flegion/lists"}