Closed torkleyy closed 5 years ago
This takes a lot less time than a big framework like vnodes, plus in case you're still planning on that this change is fully compatible with that.
Is hot reloading relevant to this issue?
Regarding externally defined components and resources, the design I had in mind (with my lackluster knowledge of the internals of specs) was to declare components, resources and systems as a schema that would simply be codegened into Rust. It would be a different story for hot reloading, but I'm not sure it is relevant here.
Also we're not planning on using vnodes in Amethyst anymore as the overhead it introduces, as small as it is, would be too high to compete performance-wise. We have another design in mind that relies on direct FFI which should have the same advantages.
(cc @kabergstrom)
Is hot reloading relevant to this issue?
In that you need to separate into a dynamic library and that only works with this change, yes.
declare components, resources and systems as a schema that would simply be codegened into Rust. It would be a different story for hot reloading, but I'm not sure it is relevant here.
Yeah, that's just the same static approach we already have. Hot reloading doesn't work with that (without implementing what I do right now externally).
Okay. Then regarding hot reloading of components, resources and systems, here is what I had in mind:
DynamicSystemData
is.Vec<u8>
. Those Vec<u8>
would contain the raw data of the new components. Then, those components would be exposed to the scripting runtime through newly generated C headers corresponding to the component schema the user provided. That however will mean that TypeId can no longer be the only thing determining ResourceId, as those storages would share the same type but a different ID. But it does not seem unreasonable to have ResourceId become a (TypeId, InstanceId)
, at least from my uneducated point of view. Also, at the end of the execution, the dynamic component should be collapsed into a statically generated component to no longer need to store the data in a Vec<u8>
. The typical wokflow would be: create your components on the fly, do your testing with it, and if it's too slow then reboot the game. It seems reasonable to me, and besides I don't really expect it to be that slow, especially if you're only using it for logic creation.Vec<u8>
storage and moving the data inside around. Modifying a component in statically-collapsed state however is a bit trickier, but not that hard either. You need to replace all static instances of that component into a dynamic instance of the new component.Most of the aspects I mention above do not have to be handled by specs. This is the design I envision for Amethyst, so everything from schema to static collapsing would be handled by external tooling in the engine.
I think we're mostly d'accord here. What I'm currently adding is just a way to add e.g. multiple MaskedStorage<ScriptingComponent>
to the resources by allowing an identifier next to the type for the purpose of resource identification.
Ah that's fantastic then. I can't wait to see that in use, not only for scripting.
Update: the current SystemData
/ DynamicSystemData
/ Accessor
/ StaticAccessor
etc. stuff is already too complex. I want a simpler architecture, and the named resources addition I planned to propose today makes things worse. Thus, I'm changing my priority to creating a simpler, more consistent and more extendable API, also as a result of today's chat on #rust-gamedev.
What vnode overhead? It should only have the cost on initial access and loading time, once you store the reified node locally then all access is direct function calls without indirection or virtualization. I've never had an issue with performance about that?
Scripting compatibility of Specs is hard to do, and even harder to get right due to many type-safe interfaces. I don't think this is something we can provide in Specs 1.0 and I don't know if Specs can or should do this at all.
I'm closing this for now. If we come up with a solution for this, I don't think it can be in the stable Specs core.
So there are currently no plans to enable any kind of modding for a game built with specs? Isn't that one of the major benefits of an ECS architecture, that components and systems can be plugged into the engine without impacting existing code?
If I did want to do something like this, how might I proceed?
If I did want to do something like this, how might I proceed?
A usual inefficient fallback is make a new component that holds a map of names<->generic_script_data and let the scripting system process over that using whatever language it is.
I had considered that option, but I was hoping for a way to allow the insertion of native component storages at runtime.
The issue is that the World API depends on monomorphization, which is all resolved at compile time. However, it's just a hash map, so it could just take runtime-defined resource IDs. There's probably something I'm not thinking of, but I was assuming that everything the script might add will only be accessed by that script, so it doesn't necessarily need to be strongly typed.
We will still have scripting and system support. This issue just mean that it won't be managed by the specs library, but rather by amethyst itself.
I see. Is there a tracking issue for that or is it still being discussed?
Beautiful, thanks!
Support for scripting will be worked on for nitric, I've mainly closed this in order to make progress in stabilization.
Opening an issue because I want to get shred & Specs ready for scripting!
I'm currently working on named resources, there'll be a PR pretty soon. Then we can already write systems in Rust and compile them into a shared library. Next step will probably be exposing the Specs API via C.
cc @Moxinilian @jojolepro
I'm going to work on the PR and link it here once I'm done with it. In case you have any suggestions / want to help please comment ;)