Coder Social home page Coder Social logo

Comments (6)

vmwxiong avatar vmwxiong commented on May 25, 2024 1

Speaking of sensible defaults, with regards to your component registration, you can just add some overloads which will handle default cases for you.

registerComponent(Counter); can automatically construct a default serializer and deserializer.
registerComponent(Counter, {serializer: ..., deserializer: ...}) would accept anything else, plus any other options you might want to add later on.

from sim-ecs.

minecrawler avatar minecrawler commented on May 25, 2024 1

Hi @vmwxiong , I added a prefab un-/loader, which uses the format from above. You can check out the code changes in a0352a0 and take a look at this prefab for a possible example. MenuButton would be a component in this case, and the object associated would contain the component's data. The prefab can be loaded using world.loadPrefab() (don't forget to maintain the world afterwards). The prefab could, of course, be written in JSON. The API takes an array of objects, so the JSON would have to be JSON.parsed before passing it, but I don't think that's a problem.

from sim-ecs.

vmwxiong avatar vmwxiong commented on May 25, 2024

Hmmm, another issue I'm seeing is that you are required to provide your own custom deserialization functions for each component. This adds some pretty significant overhead to creating a new component type, which you'll likely end up having dozens or hundreds of. It also introduces risk in modifications, since it becomes fairly easy for a developer to modify a component while forgetting to modify its custom deserializer.

I'd propose having some sensible defaults for deserialization. Take some opinionated stance on what components should look like, and use that as a starting point when saving/loading entities. After that, you can add hooks for more custom deserialization of specialized component types for more complex use cases that people might have.

from sim-ecs.

minecrawler avatar minecrawler commented on May 25, 2024

Hi @vmwxiong , thank you for your very good feedback. I think what you are pointing out is one of the missing pieces of the component life-cycle, one which I am currently trying to figure out myself.

I think you might want to have something like an in-line deserializer that lets a designer create an entity with an object literal or a piece of json.

The current save-format was developed with small file size in mind, the idea being that there would be a GUI-based editor later on which is used to create the entities. Having a second format, which is geared towards humans, might be a solution for people who are not tech-savvy and still want to quickly edit a text file. I like your second example, where a component's JSON representation might use the type name as key and the value delivers the component's data. It would be fairly easy to implement, too! I just have to think about the API changes needed. TSaveFormat would need to get compatibility and then IEntityBuilder could expose some method to import it the way it's done in your example:

const entity = world.buildEntity().fromObject({
  background: {},
  glyph: {},
  mineable: {},
  name: {},
  position_2d: {}
});

// or

const entity = world.buildEntity().fromJSON('{ ... }');

Maybe even with methods to import a whole bunch of entities stored in such a JSON file (in an array).

This adds some pretty significant overhead to creating a new component type, which you'll likely end up having dozens or hundreds of. It also introduces risk in modifications, since it becomes fairly easy for a developer to modify a component while forgetting to modify its custom deserializer.

Having default code here is very hard, because the ECS needs to instantiate an object with an generic type from a serialized representation and make sure that the type contract is honored. I am exploring the foundations of prototypes and types with this project myself, so I'd need time to find a good solution. If you have experience, I would be happy to get any hint, or even PR.

All in all, you are right. the current API is difficult to learn and use. I think about extending the current design (especially component registration) in a way which is minimal, so that a user can just register the constructor for data-only structs and the ECS will know how to handle that, but leave it up to the user if they actually also need a serializer and deserializer.

What do you think of the above ideas?

from sim-ecs.

vmwxiong avatar vmwxiong commented on May 25, 2024

The current save-format was developed with small file size in mind

Personally, I think this goal is a little unintuitive considering the size and complexity of a game that would bother implementing ECS. If it's important to you though, you could maybe make this entire framework more modular and implement things as extensions or add-ons, but that's quite a lot of work for something that may not end up being used in practical situations.

Maybe even with methods to import a whole bunch of entities stored in such a JSON file

Definitely a fan of this direction! Making things easy and practical to use off the shelf goes a long way. Even if you have capabilities to implement custom loading/saving, picking some reasonable, opinionated defaults can make it a lot more appealing to jump in and start using something like this. ECS isn't particularly complex on its own right, and there's a pretty low bar before someone just decides it's more work to integrate this than to run their own basic ECS solution.

Having default code here is very hard

I'm afraid I'm no typescript expert myself, so I'm probably of little help here, but I've found the Typescript discord to be immensely helpful in answering tricky, interesting problems around typing like this. Bet they'd be more than willing to lend a hand.

in a way which is minimal, so that a user can just register the constructor for data-only structs

Yes! Another great direction. Anything that makes every really dead simple to pick up and start is a great addition.

On a related note, I thought of another syntax that might work for entity building:

world.createEntity<Counter, Health, Inventory>({...}, {...}, {...});

Slightly less programmer-ese by removing the new() calls, but still allows for type checking each config. Certainly less than ideal for a designer to ever have to deal with though.
(Actually this probably doesn't work now that I think of it)

from sim-ecs.

minecrawler avatar minecrawler commented on May 25, 2024

Personally, I think this goal is a little unintuitive considering the size and complexity of a game that would bother implementing ECS.

I don't think that the format must be intuitive, since ideally no one will touch the raw data in there. On the other hand, having a world with thousands of entities with various components each could quickly blow up in file size, so I at least minimized the format overhead in a simple way. I was thinking about a binary format, too, but I don't see too much gain out of it right now (I would first need to get some other things in place). The format itself is at the moment not the top priority, until I get real feedback that it has to be improved :)

implement things as extensions or add-ons

I am not sure if a simple ECS would need an ecosystem like that. I guess it would be more confusing just to be able to change out the save format, so I would rather have it simple and opinionated. Which does not contradict having importers or exporters for human-readable data!

you can just add some overloads which will handle default cases for you.

My thoughts exactly! I will take this on next, since it is overly complex the way it is right now.

from sim-ecs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.