Open Xrayez opened 4 years ago
Is anyone working on this already?
@amoriqbal As far as I know, nobody is currently working on implementing this.
Keep in mind exposing import functionality in export templates will likely increase their size noticeably, which can be problematic for mobile/web platforms.
For those interested, since it seems that this FP has been declined for good, I've made a C++ module that allows for importing resources at runtime via GDScript for my game, which can be found here. Feel free to use the code in tabletop_importer.cpp
as inspiration.
It's worth noting that the C++ module alone won't work in a build with tools=no
, since the importing code is in the editor. This is where I also made a custom fork of Godot which essentially just has the above module, as well as macros to make sure that the engine compiles with tools=no
with the importing code, without any of the other editor code (so the final executable isn't massive).
@drwhut I've looked up the module you linked and even tested it out, also added to a list of community Godot modules in goostengine/godot-modules#4 which can be compiled for testing purposes (build artifacts for editor are also uploaded), thanks. ๐
Looking at the source, this demonstrates the issue with having to add dedicated importers and expose corresponding methods for each recognized resource type.
That said, the way I see it, a GDScript import()
method would be good to add, but I still think that it should be possible to use the ResourceLoader
to do this under the hood with load()
, we don't really want to pollute the global scope: #1590, and this could just be narrowed down to implementation details which could be disabled at compile-time without even exposing any other additional APIs for this.
It's worth noting that the C++ module alone won't work in a build with
tools=no
, since the importing code is in the editor. This is where I also made a custom fork of Godot which essentially just has the above module, as well as macros to make sure that the engine compiles withtools=no
with the importing code, without any of the other editor code (so the final executable isn't massive).
Yes, so I guess the most feasible way to implement this proposal is through adding build options, like scons use_importers=yes
. As Calinou said, I'm afraid Godot won't allow to bloat its binary size for mobile and web. But I think that usually, those platforms don't even need run-time import capabilities anyways.
Considering the fact that this is not what every game will need, nonetheless it's impossible to make this work with GDScript nor GDNative, since we need low-level access to resource importer API which is only accessible via modules, and also requires some core modifications.
it seems that this FP has been declined for good
That doesn't seem to be optimistic! With enough of support, I hope anything is possible. ๐
I mean, see the number of feature requests and issues I linked in the proposal.
Otherwise, yeah perhaps Godot is not the right tool for this, but it seems like a low-hanging fruit to implement, it's just a matter of finding a way to expose existing functionality in the engine to make this work in a general-purpose way.
Perhaps I'd work on this myself given approval of core developers, else maybe this can be implemented in a fork/extension. ๐
Looking at the source, this demonstrates the issue with having to add dedicated importers and expose corresponding methods for each recognized resource type.
This is one of the challenges with implementing this feature - you need to instance the importer singletons if they haven't been instanced already (e.g. in a release build). In some cases, I've noticed there are also different importers for the same resource. For example, the .obj
resource has one importer which creates an array mesh, and another that creates a mesh instance similar to other scene importers.
It's worth noting that the C++ module alone won't work in a build with
tools=no
, since the importing code is in the editor. This is where I also made a custom fork of Godot which essentially just has the above module, as well as macros to make sure that the engine compiles withtools=no
with the importing code, without any of the other editor code (so the final executable isn't massive).Yes, so I guess the most feasible way to implement this proposal is through adding build options, like
scons use_importers=yes
. As Calinou said, I'm afraid Godot won't allow to bloat its binary size for mobile and web. But I think that usually, those platforms don't even need run-time import capabilities anyways.
That's probably the best way to go about it, and based on what I had to do to get it working for release builds, this shouldn't be too difficult to do if you know your way around SCons.
it seems that this FP has been declined for good
That doesn't seem to be optimistic! With enough of support, I hope anything is possible. sweat_smile
I mean, see the number of feature requests and issues I linked in the proposal.
Otherwise, yeah perhaps Godot is not the right tool for this, but it seems like a low-hanging fruit to implement, it's just a matter of finding a way to expose existing functionality in the engine to make this work in a general-purpose way.
Haha, while I do agree that this would be a very handy feature to have (as you said, the functionality is already there, it's just exposing it to GDScript), I'm hesitant to say that this would be useful to a majority of developers. For most developers, this functionality is already implemented statically with .pck
files.
That's just my opinion though. It's really up to the developers to see whether this is worth implementing.
This is one of the challenges with implementing this feature - you need to instance the importer singletons if they haven't been instanced already (e.g. in a release build).
Possibly have to refactor this logic into a dedicated register_import_types()
, currently all importers initialization is hardcoded in EditorNode
constructor, looking at the source.
For instance, the existing ResourceImporterWAV
would be useful for #732.
I've noticed there are also different importers for the same resource.
Yeah, when we talk about importing images for example, then there are numerous ways to import as Image
, Texture
, BitMap
if you go into the Import
tab. I think it would be just a matter of providing an additional parameter, like import(Dictionary options)
or something along those lines.
Haha, while I do agree that this would be a very handy feature to have (as you said, the functionality is already there, it's just exposing it to GDScript), I'm hesitant to say that this would be useful to a majority of developers. For most developers, this functionality is already implemented statically with
.pck
files.
I dunno, I think this is where the engine could really shine and has a good potential, it's just that none of the existing core developers really dig into the UGC/modding capabilities with Godot currently, that's all. It's a matter of creating enough demand and awareness.
Also, regarding increased binary sizes, I think it's not that much code which needs to be exposed out of the box currently, I speculate that it would only add up like 3MB to export templates. In any case, depending on my motivation, I'll see whether that's actually the case, but it should be quite possible for Godot to provide such customization level at build-time, at least, so the actual custom non-editor resource importing feature can be implemented outside of Godot more easily without having to patch the source for that.
I support this proposal, though we need to get @reduz onboard with this as he designed the import system (and thereby its limitations).
For a concrete example of use case, have a look at https://github.com/Gianclgar/GDScriptAudioImport This is a GDScript script that can load WAV and OGG files at runtime, and thus needs to replicate the logic that the importer would do in the editor.
For OGG it's "simple enough", like the hacks that users currently have to do to load PNGs at runtime: https://github.com/Gianclgar/GDScriptAudioImport/blob/master/GDScriptAudioImport.gd#L114-L118
But for WAV it requires a full reimplementation of the header parsing already done in the engine: https://github.com/Gianclgar/GDScriptAudioImport/blob/56c8d70f8aa4da3ee0d498497c61e583208a515b/GDScriptAudioImport.gd#L42-L111
Here's a quick Music Player that I made to help https://store.steampowered.com/app/1369320/Virtual_Cottage/ developers to include runtime loading of user-provided music tracks: Music Player.zip
I only handled OGG as it's easy enough from parsing the file as raw data, but for WAV I'd have to do the same as https://github.com/Gianclgar/GDScriptAudioImport
IMO that's a use case that we need to support out of the box, so importers should be available at runtime - at least for the most common data formats like PNG, JPG, OGG, WAV, and possibly MP3 if #85 is implemented. This may not be possible/relevant for formats like glTF or Collada, which are full scene formats.
This would also be useful for #1362, as import functionality doesn't have to be tied to editor instance:
So better idea is to add new flag e.g. --import-only which would import files and after that just close Godot. It would be great if the editor wasn't even running.
For the reference, we discussed this a few days ago with @reduz and @Calinou, see logs here: https://freenode.logbot.info/godotengine-devel/20201020#c5530593-c5531175
A key distinction made during this chat is between import (which should stay an editor-specific process) and loading resources (which should be made as easy as possible at runtime). So we wouldn't add ways to import resources and use the imported versions with ResourceLoader at runtime, but there should be APIs for any relevant resource type to load them at runtime (as is already possible - by jumping through a few hoops - for images and sounds).
For more complex resources, @reduz suggests adding a feature to be able to export an imported resource (i.e. while in the editor) to a single file (bundling all dependencies) that could be loaded at runtime. This needs its own proposal for further discussion though.
Yeah, as I said, @reduz likely doesn't dig into UGC with Godot ๐.
Quoting you, @akien-mga:
Akien: reduz: that only helps for the use case where you (the dev) have the resource beforehand. The main use case that motivates the above proposal is loading user-provided content, like letting users load their own music or pictures
For more complex resources, @reduz suggests adding a feature to be able to export an imported resource (i.e. while in the editor) to a single file (bundling all dependencies) that could be loaded at runtime. This needs its own proposal for further discussion though.
Yeah, not useful for this proposal at all, and certainly not useful for me. ๐
The idea is that you should just be able to import a new resource with import(path)
. This will store the imported resource at user://
directory (such resources won't be packed), which then can be loaded normally with load(path)
. This would solve the collision mentioned by @reduz, so really this could be implemented as a parallel system to ResourceLoader
.
The module provided by @drwhut in https://github.com/drwhut/open_tabletop_godot_module does something similar, but it's not general-purpose enough, because importers have to be instantiated manually for this, and of course required some core modifications to build scripts.
That said, for now this is modules territory, it seems. But I'm not sure what minimal core functionality is required to facilitate implementing this proposal via modules yet. For now, I'm limited to Image.load()
.
At the very least, my recommendation/suggestion to developers is that common resources like images and audio should have loaders implemented in classes, and the import process can just reuse those loading methods just like with the current Image.load()
.
The reason why Image.load()
exists in the first place is because there are different kinds of loaders for each image format registered in the engine, and that's handled by ImageLoader
internally, so I think we've just got lucky enough such a thing exists and exposed to scripting currently. ๐
According to my reading of the logs, Reduz has rejected runtime import and export code.
Since this is the case, and I want to use my glTF module to runtime load glb files. I'm not sure what to do.
I'm presuming that gltf2 export and import at runtime will be rejected.
Since this is my requirement. Here are some workarounds:
API:
Ref<EditorSceneImporterFBX> import_fbx;
import_fbx.instance();
ResourceRuntimeImporterScene::get_singleton()->add_runtime_importer(import_fbx);
image_loader_svg = memnew(ImageLoaderSVG);
ImageRuntimeLoader::add_image_runtime_format_loader(image_loader_svg);
resource_format_saver_crypto.instance();
ResourceRuntimeSaver::add_resource_runtime_format_saver(resource_format_saver_crypto);
ResourceRuntimeSaver::save(path, resource, flags)
ResourceRuntimeLoader::load(path, original_path, type_hint, no_cache, error);
May be converted to use any system that can compile c++ code to intermediary binary code to executed at runtime on any architecture.
Edited:
A loader for TSCN, TRES, STEX is not an acceptable route.
So what I want to see is the ability to mark resources to be exported as certain file types... textures - png, bmp, gif, tiff, jpeg models - gltf, obj other things - json, ini, cfg
Then when the editor versions of the resources are created in code they automatedly populate themselves and are ready to be used.
An ideal use for this would have a game json which contains all your object's json files which contains paths to images, models, scripts and other nested json files
Looking at this, it seems like it would be a good use case for #2063 since the whole idea is to make it possible outside the editor, but also conditionally remove it from mobile/web games that might not want the bloat.
Just to add another use case to this proposal.
When dealing with systems like OpenVR and OpenXR we often obtain assets from these systems for things like controller meshes, headsets and various trackers. As the assets in question are dependent on the hardware in use by the player and this hardware may not even have existed when the game was created having the VR system provide these assets is of utmost importance to immersion of the player.
If importing new assets is only possible during development and not during runtime we have a gap in functionality. OpenXR for instance will provide fully articulated assets for controllers as a GLTF resource (GLB). Important here as well is that these assets are provided in binary form in memory and not in file form. See: https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_controller_model
The ideal setup I see is that the import logic itself becomes part of the normal runtime and only has saving the converted resources in .import
and the subsequent exporting logic be part of the editor code. This would simply be an extra check to see if a converted resource already exists when loading, and saving the converted resource after the import is run when used in editor while the core import process is shared between runtime and editor versions.
When loading asset source files in runtime this will incur a performance penalty as all the conversions need to be performed but when assets are imported during development optimized formats can be used. Best of both worlds solution while removing the need to duplicate code.
For me, I really wish can import audio file at runtime, other game engines like UE and Unity all can do this. If I can load mp3 at runtime, I can create my MusicApp, I like. BTW, Now almost image formats can load at runtime, PERFECT!
I'd love to use godot to make desktop apps, it's pretty killer already, but the really inflexible import system kinda breaks that.
Couldn't the importer code be compiled 'twice', once for use in the editor, linked in, and then also broken out as modules, which could be used by games/apps if they so choose? They could be scoped differently in GD script as well.
I think the core of the problem that the author of this proposal exposes here is already solvable by current Godot. I am working on a similar project that wants to make possible for users/players to make their own user-generated-content for my game. and I have an idea on how to tackle it, though I haven't reached that point yet. There is ProjectSettings.load_resource_pack
that allows loading additional and arbitrary resources. Users/Players can use the standard editor and a project template provided by the developer to create their own resource packs that may be loaded at runtime by the game. There are, however, some issues with this path:
Is it desirable to solve some of these issues in core Godot? It'd be nice to have discoverable res:// content at runtime in the exported game. Or, instead, optionally have loaded resource packs have their own namespace.
By the way, I don't think editor functionality should be exposed to Godot projects. Not only it's likely it won't be a perfect match for every or most games, it may also shackle the engine to provide the current API and behavior indefinitely and leave much less room to innovate. Interested parties should make an external module that exposes similar editor features for games.
[0] https://github.com/godotengine/godot/issues/7845 [1] https://godotengine.org/asset-library/asset/96
@lyuma was able to port my gltf module to gdnative in 3.x. He can comment on that design.
Users/Players can use the standard editor and a project template provided by the developer to create their own resource packs that may be loaded at runtime by the game.
The core idea behind this proposal is that users don't need to be programmers/modders to learn and use developer-provided tools, so this is not an option for me personally. In fact, users might not even be interested to create the content themselves: it may be just an arbitrary image they have from which level geometry could be created, or a song from which a gameplay may be procedurally generated backed up by the mood of the song, etc.
2. Discoverability is difficult because of 1.. A possible solution is to have a resource list file in the root of the pack to help the game discover the game content. However, this is tricky to do because of the next point.
Yep, it's a separate problem which I hope could be solved in a straightforward way, see another proposal of mine: #1212.
3. Every single file/resource is put into the same namespace. This means, user-generated-content not only may conflict with the game data, it also means that every additional resource path must be unique.
4. Use of game core scripts by user resources is tricky. To avoid having users attach scripts to resources and nodes, I have added custom modules with new types for users to build their packs with. By the way, how do C# scripts work in additional resource packs? This is still an unknown to me.
This could probably be handled by #2689 proposal. ๐
Of course, every above point can be solved by third-parties given enough time and resources. But the question is whether Godot could provide those tools without having to fight with the engine internals, and be maintained at first-party level. So far, the lead developer does not seem to approve any of these ideas, or provide alternatives that don't really help the limitations presented here, and I respect the decision, but as I said, it's really something which could probably make Godot even better tool in this regard.
So, yeah, you'll likely be a happier person coming up with in-house solutions to solve those problems at the moment.
Users/Players can use the standard editor and a project template provided by the developer to create their own resource packs that may be loaded at runtime by the game.
The core idea behind this proposal is that users don't need to be programmers/modders to learn and use developer-provided tools, so this is not an option for me personally. In fact, users might not even be interested to create the content themselves: it may be just an arbitrary image they have from which level geometry could be created, or a song from which a gameplay may be procedurally generated backed up by the mood of the song, etc.
I know and I failed to address this point. Or points, I would argue. In the approach my project has, users don't have to program anything. The only skill they have to train is to import and build scene trees. That and building a package file. So I think it programming isn't a necessary skill in general. Even if there is something to learn or train about, without coding, users that love a game manage to do things that they would have otherwise never have considered doing before for modding sake. The other point this proposal makes is loading some specific types of resources at runtime, like images and audio and 3D geometry. I entirely support that, I definitely have uses for that too in my project. This though, might be doable with GDNative addons. In fewer words, I think the scope of this proposal is too broad and it could be more agreeable with more focused problems and solutions.
Besides, I think the use of the word "import" should be changed to "load". By "import" I understand the process of converting a resource to a space-efficient and fast-loading format for use of a well-defined game project. Stand-alone user content, i.e., single files outside of a game package, isn't imported, it's loaded. And thus, you might desire to skip Godot's special package formats, like images that can be compressed and stored in an upload efficient format. It might be better to load a GLTF scene straight from disk to a scene tree and graphics memory without importing to an intermediate format.
That is the point I missed to say. To import is to store in an intermediate area for quick loading. At runtime, the benefits of importing are likely gone. So the exposure of Godot's importers to games is likely to be of little use in some cases, if not most.
Yep, it's a separate problem which I hope could be solved in a straightforward way, see another proposal of mine: #1212. This could probably be handled by #2689 proposal. slightly_smiling_face
These are nice proposals and they have my thumbs up but, I don't count on them having some kind of resolution any time soon :sweat_smile:
Of course, every above point can be solved by third-parties given enough time and resources. But the question is whether Godot could provide those tools without having to fight with the engine internals, and be maintained at first-party level. So far, the lead developer does not seem to approve any of these ideas, or provide alternatives that don't really help the limitations presented here, and I respect the decision, but as I said, it's really something which could probably make Godot even better tool in this regard.
So, yeah, you'll likely be a happier person coming up with in-house solutions to solve those problems at the moment.
@Xrayez
I'm afraid Godot won't allow to bloat its binary size for mobile and web. But I think that usually, those platforms don't even need run-time import capabilities anyways.
I'd like to say I most definitely use and need run-time import capabilities on mobile. In my game I need to be able to load photos I have in storage. But music could be a obvious use case for mobile too. There are so many situations in games and apps where this would be great to have an easy way to use external resources, but currently it's a gigantic pain, especially on mobile.
I think I wasted a month trying to find a method that works on both Android and Windows (however only in GLES2). I got so frustrated I could not even bring myself to write an issue after I finally found the one method that worked, because I just wanted to be done with it. We really need something simple that works cross platform to load external resources. Not just desktop.
News update.
The core team has allow for importing glTF2 files at run-time (in exported projects, without extra PCK files).
I'll throw my vote into the "dynamically loading assets at run-time is a crucial feature" hat. My new games are all client/server multiplayer, and need the ability for the server to dynamically upload assets to the client, and for the client to be able to load them into the scene upon receipt of the assets.
To be clear, I don't need the data transfer as part of the engine. I can handle that myself (and already have that capability in my server). What I need is for Godot to be able to dynamically load resources from anywhere within the user:// path (where my server uploads get written to), whether those resources were built into the game or not. That includes models, images, sounds, etc. All resources Godot recognizes need to be dynamically loadable from the core engine.
I've been spending the last couple of days trying to make sense of imports and resources and pck files, and I think this thread sums up most of my desires.
I would love if PCKPacker could be used at runtime to build (and write to disk) pck files that contain imported versions of their assets. This way, on future runs of the game, loading that pck would mean being able to access the most efficient representation of these assets.
My use case is something like:
user://
directory (ie. persisted on disk)#3
while maximizing for runtime efficiency of reading that data (my understanding is that imported assets would take care of this)#4
at runtime (ie. programmatically trigger the import pipeline through GDScript)One problem is the desire from the other maintainers to not compile the code for the importers in game templates. That has an easy solution, use the editor as the game template.
Hope that gives you an approach.
Thanks @fire , that makes sense. For my specific case, I'm worried less about the export size of the engine/editor and more about abstracting this import process (and having to even open the editor UI) from the player of the game.
Maybe I'll have to follow this other proposal for running imports through the CLI? https://github.com/godotengine/godot-proposals/issues/1362
I am currently in the process of making a game that will allow modding, so far I can work around the quirks by loading images with Image.Load and not using .wav files (I don't want to parse the header). However I have yet to find a way to load true type fonts directly from an external file system.
It's sad to see that this was not fixed for godot 4.0. This really limits godot for making games with mod support or tools. I do hope this gets picked up in one of the future godot 4.x releases.
However I have yet to find a way to load true type fonts directly from an external file system.
You can use system fonts in Godot 4. Since this involves loading fonts at runtime, it's likely that this can be extracted into a standalone way to load arbitrary fonts (even if they aren't in the system folders).
You can use system fonts in Godot 4. Since this involves loading fonts at runtime, it's likely that this can be extracted into a standalone way to load arbitrary fonts (even if they aren't in the system folders).
That is certainly an improvement, but for my usecase where I want to use steam workshop to provide mods it does not work (without extracting the functionality as you said). I can work around it since I use C#. I can load the font with a C# library, convert it to an image, then load the image in godot and make a bitmap font from it.
But it really is a hassle that you have to figure out per asset type (and also per file type in some cases, .wav files for example) how to import them into the engine. I dropped .wav support now because of the effort of parsing the header myself.
I am quite experienced with godot and programming in general and I find it very time consuming to figure out how to import this stuff. I can only imagine how difficult this would be for someone less experienced. I think making either a ResourceLoader.LoadExternal or just hiding it inside ResourceLoader.Load would be nice. If binary size is a problem then providing a setting to choose if this functionality is included or not could be a solution. I think the main motivator for such a change would be to make it easier for people to allow modding of their games.
You can use system fonts in Godot 4. Since this involves loading fonts at runtime, it's likely that this can be extracted into a standalone way to load arbitrary fonts (even if they aren't in the system folders).
That is certainly an improvement, but for my usecase where I want to use steam workshop to provide mods it does not work (without extracting the functionality as you said). I can work around it since I use C#. I can load the font with a C# library, convert it to an image, then load the image in godot and make a bitmap font from it.
But it really is a hassle that you have to figure out per asset type (and also per file type in some cases, .wav files for example) how to import them into the engine. I dropped .wav support now because of the effort of parsing the header myself.
I am quite experienced with godot and programming in general and I find it very time consuming to figure out how to import this stuff. I can only imagine how difficult this would be for someone less experienced. I think making either a ResourceLoader.LoadExternal or just hiding it inside ResourceLoader.Load would be nice. If binary size is a problem then providing a setting to choose if this functionality is included or not could be a solution. I think the main motivator for such a change would be to make it easier for people to allow modding of their games.
I wonder how RPG in a box achieved this. In the FAQ it claims everything is built on top of Godot so I guess somehow this is doable? I'm asking cause I'm on the same boat. At this stage I'm considering to checkout the engine/editor source code and start stripping and changing whatever I don't need and transform it to a very specialized editor for my own game.
With the recent Unity fiasco.. I REALLY would love to see another engine able to load models from either a file at runtime or a URL directly. A local file would be acceptable as I could use C# to natively download to file and then load it from disk. This would allow for dynamic games, virtual worlds and game mods.
First of all, I'd like to point out that Godot .scn or .res files can be used at runtime as a native runtime format alternative to .pck. Godot is very capable of loading these native Resource formats, and by their nature, they will cover all file types Godot supports. .res is the format I am currently using in the V-Sekai project, though we of course will keep our eyes on the gltf ecosystem as the set of supported gltf extensions is continuously growing such as the recently added physics support.
(Side note: If there is concern about UGC security, I have GDScript code which can pretty efficiently validate a resource file for embedded scripts which is one of the bigger dangers: https://gist.github.com/lyuma/8de4620a402d565b86e1287150c8fb31 Some Resources such as PackedScene, Animation, AnimationNodeStateMachineTransition and so on will need additional validation after being loaded to ensure they don't reference unwanted properties / classes, since those properties/classes are technically binary/strings within the PackedScene resource.)
Regarding WAV file import, they contain raw PCM data and should be pretty simple to load at runtime from script if needed. - this is an example from python, but given that it uses only struct
it there are GDScript equivalents for everything that sample code does.
Font loading at runtime is already supported by instantiating a FontFile instance and assigning the raw contents of the .ttf file into its data
property. I think there's certainly a documentation shortcoming because it's not obvious that this is possible, but creating a FontFile instance is basically all the editor-time font importer does. - the preload step can also be done if you want, but my understanding is preloading is optional. Godot has a FontServer whose responsibility is to dynamically fetch glyphs from the font.
I do think it would be cool to see some equivalent of the import system for runtime, but doing so would be a major overhaul to how the entire import system works. I'm trying to point out that there are already ways to load most of asset formats described in this thread at runtime, just not through a single unified API.
@thephox1982 Re: "I REALLY would love to see another engine able to load models from either a file at runtime or a URL directly" - my understanding is the way Godot works in this regard is actually fairly similar to how other engines (such as Unity) work. The heavy lifting is intended to be done by the editor-time import process, and the runtime engine is slimmed down to only support specific formats. Thus, I'd suspect similar issues to exist in other engines, beyond the basic set of runtime supported formats.
Finally, I want to summarize what I think is one of the points of confusion in this thread.
The title of the proposal reads "Allow to import and load external assets at run-time ... without extra PCK files" I think it is worth breaking this down into both sub-pieces, since there are really two separate issues here.
load external assets at run-time. I'd say this is already possible today in 4.0+ for most formats: though the code needed is format-by-format. If there are specific asset formats you are having trouble with, feel free to ask about those specific formats.
import external assets at run-time. This is a valid proposal to make. Godot's Import system has a lot of features to it including a settings GUI, post processing, compression/baking, and some of those post-processing features are not trivial to do at run-time. Imported assets can reference other assets by file-path, so designing this system to work at runtime would require a file system structure similar to a Godot project, with a .godot temporary directory, some way to store imported file references (.import files) and so on. This is a major feature which would need to be designed, planned and implemented, since the entire import system at present is very dependent on this very editor-specific project filesystem infrastructure.
I suspect most of the usecases you are asking for can be covered by the load external assets at run-time case, which should be doable today on Godot 4.x versions. A runtime import system would certainly be easier to use, but does not exist at present.
Sorry for the long-winded comment: it's just my way of writing. I'm also always available by DM or on the #asset-pipeline channel on Godot Contributors Rocket Chat if you want to discuss these types of issues with me directly or with others working on the asset pipeline.
@lyuma As for me personally, if I could load a fbx or gltf/glb from disk directly, this is frankly all I would need and of course either JPG/PNG file for the material, etc. The use case is a dynamic virtual world with user contributed content, which I have working in Unity but I'm looking to move away from Unity. If there are ways of doing this with Godot, I have yet to find a concise answer, example, or documentation that explains how it can be achieved.
Honestly, the locked down methods game engines still employ in 2023 seems baffling and archaic and a move toward allowing dynamic worlds both as static games and virtual world based games is the natural next step in gaming evolution, but we keep getting held back and instead we need to write our own engines from scratch to achieve these use cases.
As for the having to re-write importing system and such to allow for this, I'd personally would just make a separate importing system for runtime and have it as a module users of Godot could enable/install if they need it. This is sort of how it is in Unity, Unity doesn't natively support loading raw assets from disk or web server, but by purchasing an asset someone else made, I was able to get the ability to do just that.
I mainly just want to escape confines of greedy corporations where they can just change their ToS and begin charging new fees on a whim and other such things, so I'm looking for a new engine that can at LEAST be able to load from files I download via C# to file or better yet directly from a web server without having to first use C# to download the file and then load it.
Alternatively, if I could make a script that accepts a file via editor code that then packages up a Godot file that can then be sent to game clients and loaded, that would also work!
As for me personally, if I could load a fbx or gltf/glb from disk directly, this is frankly all I would need and of course either JPG/PNG file for the material, etc.
Godot 4.0 and later can load glTF scenes at run-time, including from exported projects. Documentation is currently missing, but it is technically feasible.
Edit: Documentation was added by https://github.com/godotengine/godot-docs/pull/8363 and https://github.com/godotengine/godot-demo-projects/pull/993.
As for the having to re-write importing system and such to allow for this, I'd personally would just make a separate importing system for runtime and have it as a module users of Godot could enable/install if they need it.
This is pretty much the solution I came up with for my game - this is my custom module that includes a function to import specific file formats at runtime almost exactly how the editor would (the function being TabletopImporter::import
). It does however require you to compile the engine yourself, and if you want the functionality in release builds of your game, some tweaks are needed across the engine to make it work. There are more details in the module's README if you're interested!
Godot 4.2 adds functionality to load OGG files by path. It would be ideal to do the same for all other audio formats and then have a unified interface to load them as AudioStream.
AudioStream.LoadFromFile(path) -> AudioStream
AudioStreamMP3.LoadFromFile(path) -> AudioStreamMP3
AudioStreamOggVorbis.LoadFromFile(path) -> AudioStreamOggVorbis
AudioStreamWav.LoadFromFile(path) -> AudioStreamWav
Edit: Honestly it would even be better if godot could just load non imported files and just manage the complexity for us and have it work transparently.
GD.Load<AudioStream>(path) -> AudioStream
To get around this obscene limitation, and to avoid rewriting my entire project I have simply resorted to shipping the editor and the entirety of my project, instead of a binary and packed files.
I have no idea why I would have to go and rewrite what the editor does, just so that the output binary can loose load files. The editor functionality and the runtime functionality should be 1:1.
Had I of known of this limitation in advance, I would have likely not used godot at all. But now I'm at the finish line, staring at a brick wall, because my game doesn't function outside the editor. Bravo!
I have no idea why I would have to go and rewrite what the editor does, just so that the output binary can loose load files. The editor functionality and the runtime functionality should be 1:1.
In addition to PCK files, Godot supports many ways of saving/loading various standard file types at run-time: https://docs.godotengine.org/en/latest/tutorials/io/runtime_file_loading_and_saving.html
The above page was written for Godot 4.2, but Godot 4.1 supports all features listed there except run-time SVG and Oggย Vorbis loading โย if you need those right now, use 4.2.beta4.
In addition to PCK files, Godot supports many ways of saving/loading various standard file types at run-time: https://docs.godotengine.org/en/latest/tutorials/io/runtime_file_loading_and_saving.html
Oh wow, you can do so much more with vanilla GDScript in 4.2 than you can with 3.5 :open_mouth: I just want to confirm, do all of these functions mentioned in the documentation still work in release
builds of the engine?
Also, I've noticed that there are not any functions for .obj
and .dae
3D model formats - are these formats planned to be added in the future at all? If not, that's totally OK, I'm more than happy to write custom importers for them if it means I no longer need to maintain a custom fork of the engine!
I just want to confirm, do all of these functions mentioned in the documentation still work in release builds of the engine?
Yes, I've tested the demo project with a release export template. The examples/
folder in the demo has a .gdignore
, so none of the files inside are imported in the project.
Also, I've noticed that there are not any functions for .obj and .dae 3D model formats - are these formats planned to be added in the future at all? If not, that's totally OK, I'm more than happy to write custom importers for them if it means I no longer need to maintain a custom fork of the engine!
This should be tracked in its own proposal (like for audio). Personally, I think being able to load OBJ at runtime makes some sense (since it provides individual meshes as opposed to scenes), but Collada is a dead-end format nowadays (nearly everyone has moved to glTF).
That said, even OBJ remains a less optimal format than glTF for meshes, because glTF can be a binary format which compresses better and loads faster (for complex meshes). This would be another reason to encourage users to use glTF, also because you can save glTF at runtime with Godot (while runtime OBJ support would likely be read-only).
I have no idea why I would have to go and rewrite what the editor does, just so that the output binary can loose load files. The editor functionality and the runtime functionality should be 1:1.
In addition to PCK files, Godot supports many ways of saving/loading various standard file types at run-time: https://docs.godotengine.org/en/latest/tutorials/io/runtime_file_loading_and_saving.html
The above page was written for Godot 4.2, but Godot 4.1 supports all features listed there except run-time SVG and Ogg Vorbis loading โ if you need those right now, use 4.2.beta4.
The issue remains that I would have to rewrite everything instead of just having load and preload work as expected. As I understand this is due to a reliance on the import files, which can not be generated by the exported binaries?
Instead I am just shipping the editor, and setting the path argument to the project directory. Now load and preload work as expected, except the audience is stuck with debug, which if I understand correctly is slower.
The issue remains that I would have to rewrite everything instead of just having load and preload work as expected. As I understand this is due to a reliance on the import files, which can not be generated by the exported binaries?
I think this will remain the case for the foreseeable future. load()
and preload()
aren't designed to work with arbitrary files on the filesystem โย they handle many Godot-specific things, such as its resource file types, resource translation remaps, reading import settings from the .import
file. In contrast, none of this is relevant when loading standard file types, which is why different methods are used for this.
To clarify, runtime resource loading should not be used to load files that are part of the project. You should keep using load()
and preload()
for those.
Because Load
and Preload
accept paths as input parameters, it is not clear that they are not meant to be used in runtime to load assets outside the project.
If I recall properly, they even returned null instead of failing / logging an error on the console mentioning that they don't support files outside the project.
It was even more confusing after that because the exported binary was able to load files outside the project that were copy pasted outside the project thus still having the .import files besides them. (while loading audio files at runtime).
--
On a totally different note, it was weird to not be able to not be able to stream audio file from disc while playing.
AudioStreamOggVorbis.LoadFromFile(path) -> AudioStreamOggVorbis
read the whole contents of the file before being able to play it.
My usecase required reading a 24h sound file which took a bit to load ๐คฃ
Runtime loading of Ogg Vorbis used to work in Godot 3, it seems like it just got "optimized away" at some point. I need it for loading from external ZIP files and user-generated content.
... So I have cludged it together as a messy little GDExtension and submitted it to the Asset Library.
https://github.com/Yukitty/godot-runtime-ogg-vorbis https://godotengine.org/asset-library/asset/9877
Runtime loading of Ogg Vorbis used to work in Godot 3, it seems like it just got "optimized away" at some point. I need it for loading from external ZIP files and user-generated content.
This is already available out of the box in 4.2 and later: https://docs.godotengine.org/en/latest/tutorials/io/runtime_file_loading_and_saving.html#audio-video-files
... ah. ๐คฆ๐ผโโ๏ธ I appear to have checked the asset library, checked proposals, checked (open) pull requests, aaand somehow forgot to check the current development version. It's already implemented exactly where and how I was wanting it. ๐
Five years later, it's impossible to export a game that has .ogv video without dancing around =)
@gibloor Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.
The issue you're mentioning is also unrelated: you need to add *.ogv
to your non-resource export filter. You should be able to load such files at runtime in an exported project as well, even if they're stored in user://
: https://docs.godotengine.org/en/latest/tutorials/io/runtime_file_loading_and_saving.html#audio-video-files
Describe the project you are working on:
A game with user-generated content (and less of a modding support). Mostly related to godotengine/godot#17848. Also Goost - Godot Engine extension, where some stuff gets exposed in non-editor builds.
Describe the problem or limitation you are having in your project:
See very useful discussion which illustrates the problem at godotengine/godot#17748.
Godot requires that most files must be first imported into a project (converted from various file formats to
Resource
s, such as*.png
toTexture
) before they can be used in a game, and this works well for games which don't require dynamic loading of assets.The export process involves packing all of the previously imported assets into a special
*.pck
file which is then unpacked upon running a particular game.The problem comes when you want to give a player an ability to load external assets which are not part of the original game, without creating additional tools to make
*.pck
files to be used by a player, because players are not developers, and there has to be an intuitive way to load external assets within a game itself. See also limitations at #1212.Loading imported resources requires you to use
load()
orResourceLoader.load()
. Loading non-imported, external resources require you to replicate the import process at run-time first (which is already done in the editor), and then store a reference to the loaded resource somewhere for it to be accessed later, so it's not possible to useload()
for those resources, because they were not actually imported, but created at run-time instead.This in turn leads to various confusions and misuse like with
Image.load()
andResourceLoader.load()
.See also related issues and other proposals:
Marginally related:
Describe the feature / enhancement and how it helps to overcome the problem or limitation:
I suggest to add a way to seamlessly
load()
external resources by first importing them if they are outside of theres://
path, likeuser://
or any other system path.Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
The crude logic is the following:
for imported resources (inside
res://
), look whether a particular file was previously imported. If yes, then just fetch the resource withload()
.for external resources (outside of
res://
), we know that they are not imported, so import a file first using the same mechanism as in the editor, and thenload()
it normally.Alternatively, perhaps
ResourceImporter
and correspondingimport()
GDScript method could be added (or exposed), to allow users to import external resources at run-time first, if this proves to be easier to implement and/or maintain.I understand that a lot of importers are tied to the editor, so this likely needs a rewrite/refactor, or adding a build option to allow those importers to be available in
release
builds, at the very least.If this enhancement will not be used often, can it be worked around with a few lines of script?:
Currently, you have to use
File
and variousload()
,load_from_file()
,load_from_buffer()
exposed methods scattered in various classes likeImage
,AudioStreamSample
to replicate the import process to some degree (difficult to account for various peculiarities inherent to parsing files), so none of those existing methods provide a way to import those resources exactly like in the editor.Is there a reason why this should be core and not an add-on in the asset library?:
I believe one has to rewrite/adapt the
ResourceLoader
and the import mechanism for this to work, which is pretty core.I believe implementing this proposal could solve a lot of reported issues, and even some specific loading functions could be unexposed that way.