2 unstable releases
0.2.0 | Oct 24, 2020 |
---|---|
0.1.0 | Apr 12, 2020 |
#537 in Game dev
115KB
3K
SLoC
goggles
It's like a nice pair of specs, except much more uncomfortable and inconvenient
This crate is a heavily modified, stripped down version of the specs
ECS
library. It is less of a framework for doing a specific style of ECS as easily
as possible and more of a DIY library for doing ECS that allows you to adapt it
to your own needs.
goggles
may not be as straightforward to use as other ECS libraries, if
something like specs
or legion
already fits your needs then you should
probably use it.
The basic data structure design is nearly exactly the same as specs
, it uses
the same basic data structures that specs
does to store components and do
joins. Just like specs
, it stores components in separate storages and records
their presence with a hierarchal bitset type from hibitset
, and uses that same
hierarchal bitset to do joins.
On top of this, however, is a more minimal, piecemeal API than even what specs
provides. It is somewhat opinionated in what it removes: everything that I felt
was extraneous or magical, and only tries to handle what is very hard to do
otherwise or is unsafe, and mostly leaves the easier parts to the user to design
themselves.
The library contains a set of more or less independent parts, you can stop at whatever level of abstraction is appropriate:
-
The
par_seq
module is a completely independent way of setting up and running generic parallel and sequential systems. It can be compared toshred
, but it contains a much more genericSystem
trait, and does not include functionality for locking and reading resources. It simply allows you to define a set of resources inSystem
s, combine those systems usingPar
andSeq
, make sure that the result doesn't have resource conflicts, then run it. -
The
system_data
module defines aSystemData
trait for statically defined resources for thepar_seq
module, and provides aSystemData
implementation for tuples ofSystemData
. -
The
resource_set
module defines aResourceSet
which is similar to anAnyMap
with values stored in aRwLock
. Unlike a set ofRwLock
s though it doesn't ever block, instead it simply panics when aliasing rules are violated. It is designed so that you can use thepar_seq
module to build systems that operate over the defined resources. It also includes convenient types for defining and requesting read / write handles to resources which implementSystemData
, so they can be used in tuples like(Read<ResourceA>, Write<ResourceB>)
. It is very similar to theWorld
type inshred
. -
The
join
module contains a definition for aJoin
trait for data stored byu32
indexes and tracked by aBitSet
with fast, unsafe access. It provides the ability to iterate safely over aJoin
sequentially and in parallel, and provides means to join multipleJoin
instances together. It is similar to theJoin
trait inspecs
, but redesigned for a bit more safety. -
The
storage
module contains theRawStorage
trait as well as 3 useful implementations:VecStorage
,DenseVecStorage
, andHashMapStorage
. This is an abstract, unsafe trait for storing values associated with indexes. It is extremely similar to the equivalent functionality inspecs
. -
The
tracked
module contains aRawStorage
wrapper that keeps track of component changes. Unlikespecs
, this is pretty minimal and only optionally sets a flag in anAtomicBitSet
on mutable access. -
The
masked
module contains theMaskedStorage
struct which safely wraps aRawStorage
together with aBitSet
to keep track of which components are present.MaskedStorage
is also join-able. -
The
entity
module contains an atomic generational index allocator that also useshibitset
types to track which indexes are alive. It also allows you to join on the allocator to output liveEntity
's. -
The
world
module ties all of this together into something with a recognizable ECS API. If you want to understand how this works, or want to build your own abstractions instead of what's provided in this module, start here. Many of the changes tospecs
have been made so that theworld
module contains only safe code.
Here is an incomplete list of the important things removed from shred
and
specs
:
-
No automatic setup, you must insert / register all resource and component types.
-
No saving / loading support, you should handle this yourself.
-
No automatic system scheduling / dispatching / batching, you must design your execution strategy yourself with
par
andseq
and then it can be checked for conflicts at startup. -
No lazy updates, you probably want to handle this specifically for your application. There is not always a universally best way to do this.
And here is an incomplete list of the important changes from specs
for
functionality that is present in both this library and specs
:
-
Does not require T: Sync for mutable access to resources / components (only requires T: Send).
-
Redesigned Join trait for soundness and a bit more safety. There is an additional
IntoJoin
trait that allows you to participate in the convenient tuple join syntax without having to write unsafe code. -
Component
RawStorage
impls requireUnsafeCell
for soundness -
Component
RawStorage
impls always assume disjoint storages that are safe to iterate over in parallel. -
Simplified component modification tracking.
-
Removes some features of
specs
which are known to be unsound such as index component access through iterators. -
The individual parts of the library go out of their way to be more loosely coupled, sometimes at the cost of extra code or user convenience.
-
Nearly all of the internals are public in case you need to build a different abstraction.
Why does this exist?
I'd been working on a project for a while that used specs
proper, and I kept
needing to redesign small pieces of it. Much to specs
credit, it is already a
library that you can use in a very piecemeal, independent way, and that's
exactly what I did. At some point I looked up and realized that I only used
maybe a core 20% of what specs
provided, and that was around the time that I
started needing to use messy extension traits to go further. I decided to
re-implement the core part of specs
that I still used, package it up with some
of the other things I made that were more flexible (but arguably harder to use)
than what shred
/ specs
offered, and put it here.
Should I use this?
There's a good chance you don't need or want this crate. Still, if you find
yourself needing to break up specs
into its constituent parts and build your
own APIs on top of it, this is here if you need it.
Credit
This project is directly derived from specs
so most of the credit goes to
specs
' creators. Anything at all in this crate that is especially clever is
probably theirs.
License
This is derived from specs
, so similarly it is dual-licensed under Apache-2.0
/ MIT.
Dependencies
~1.6–2.2MB
~46K SLoC