Hi. I'm quite new to Rust, but am an experienced developer. (Primarily a game developer.) I have been doing daily rust study and practice for a few weeks. After spending some time just reading The Book, my approach was to write a lot of very small tests to just try out different features and discover what kind of knots I would find myself tangled up in. These tangles were pretty common, but I generally found a way around them by shifting my thinking. I have since moved on to trying to implement a few system that I would generally use for any kind of game development. These are systems I've written many times in various games and languages in the past, so I am quite familiar with how to implement them in languages without a single ownership rule.
The system I am having trouble on right now is that of a Spatial Hash. In my initial implementation I have a HashMap with tuple keys representing 2D chunks of the world and the entities in that region: 'HashMap<(i32, i32), Vec>' As entities move around the world, they must let the map know they have changed position, and if they have crossed the boundary from one cell to another, they must be moved from the Vector they are in to the other.
So far, I have that part working fine. The map owns the entities, and mutable references can be obtained from the Hash for use by the program. For the kinds of simulations I want to be able to do, entities will use the spatial hash to find out which entities that are nearby, and interact with them. Since entities need to be able to hold "references" to each other, something Rust does not allow, I plan to store these references as ids (simple numeric id generated uniquely for each entity that is created.)
The problem I now have is to find an efficient way to locate a particular entity based on its ID. For example, I have an entity with the id 42
, and I want to get a mutable reference to it. Just as an example, say one entity holds the id of another entity it is chasing (maybe it wants to eat this other entity). To be able to find out where that entity is currently located, it must use its id
to obtain a (possibly mutable) reference to that entity.
In another language I might have another lookup containing references to the entities by id, or simply hold a direct reference to the entity I am interested in, but in Rust this is impossible. I can't think of any other way to locate the Entites than to iterate through every cell until I find it, which pretty much defeats the purpose of using a spacial hash in the first place.
I know that I may be missing some important techniques in Rust that I just haven't learned about. I have been advised to look at RefCell as a way of solving some of my difficulties. So my question basically is this: what kinds of techniques can I use in Rust to handle situations where many entities must have the ability to know about and refer to one another in a dynamic way (as you would expect in a simulation or game.)
Holding references to "dead" entities is certainly a problem I have encountered in game development before. In GC languages, where we can simply hold a direct reference to other entities, it is generally safe to just have a "dead" flag or something similar. If entities are being pooled, we can use other validation techniques such as generation_id
to confirm that the entity is still in the same lifecycle as it was the last time we looked at it. These kinds of tricks (which are not always elegant I will admit) are what I've come up with in those languages, but in Rust a new trick is needed. I just haven't come up with it yet. I'm hoping there is some magical Rustic technique that someone can enlighten me about. Thanks
PS I can post the code of my SpatialHash if anyone is interested, although it really is just a simple HashMap basically, and the problem is more a general question about "how to think" about these problems in Rust.