godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.07k stars 68 forks source link

Add support for resource remaps based on feature tags #10051

Open allenwp opened 4 days ago

allenwp commented 4 days ago

Describe the project you are working on

A game that needs to display different controller diagrams based on the export's expected controller. This proposal also has a variety of other porting applications.

Describe the problem or limitation you are having in your project

There is no built-in functionality to help remap resources based on which export I am targeting. Here are some examples of when I want to remap resources:

I have written a blog post that describes a number of challenges and solutions to porting games with the Godot engine. This post covers a number of topics that are related to the topics addressed in this proposal.

This proposal stems from a discussion (#5189) and is one of two proposals that aim to improve porting efficiency and user experience. The other proposal is #10034.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The resource remaps functionality will appear similar to the existing localization remaps functionality. It will behave differently because it will be based off of feature tags and remapping will be done at the time of export.

Mockup of resource remaps view

Here are a few important things to note about this design:

1) The new Resource Remap view is implemented almost identically to the existing Localization Remaps view. 2) Overrides are implemented with similar behaviour to project settings overrides: the first override in the list that matches a feature tag in the export will be chosen when exporting the project. If no overrides match any feature tags in the export, no overrides will be used. 3) Arrow buttons enable easily changing priority of remaps. This is especially valuable in Android exports that may share some, but not all feature tags. For example, a meta_quest could be positioned higher to take precedence over a mobile feature tag on this list. 4) Resource Remaps are added to project settings because these are similar to Localization Remaps, which already exist in the Project Settings. Having these two remaps in the same part of the editor makes this new feature easier to find.

Excluding Resources

When a project is exported, only one resource in the resource remap group should be exported and all others should be excluded. This can allow the user to reduce the app size of a mobile export by remapping a high quality music file to a low quality music file. This is especially valuable because it is not reasonable to include a full MP3 encoder in the Godot editor, so having separately encoded MP3 files is necessary.

I suspect this behaviour could lead to user-error if a user doesn't realize that one of their resources is a part of a resource remap group. To mitigate this, icons could be added in the file system views to denote that resources are a part of a resource remap group.

Mockup of adding icons to the file system dock

Interaction with Localization Remaps

Localization remapping should be performed after this resource remapping. This is natural because the resource remapping happens at export time and localization remapping must happen at runtime.

When performing resource remapping on localized resources, the root resource that is used in localization remapping should also be used as the root for resource remapping. I believe this is obvious and natural.

Implementation Details

I expect this feature can be implemented using the same plumbing that is used to support textures with different compression formats, such as astc for mobile exports and bptc for PC exports. I have not looked into this futher, so I might be somewhat wrong about this assumption.

Potential Problems

I'm assuming that resource remapping is already well established in the engine for localization remaps, so I don't expect any new problems. That said, because this remap is happening at export time, there could be new issues that come up.

Specifically, care would need to be taken with the "Export selected scenes/resources (and dependencies)" feature. I'm not sure exactly how this proposal would interact with determining dependencies.

I am not certain if remapping packed scenes is actually a good idea because it might fight against the possibility for packed scene refactoring tools in the future... But again, since remapping packed scenes already exists for localization, I believe this ship has already sailed.

Other Rational

If this enhancement will not be used often, can it be worked around with a few lines of script?

Currently, this sort of functionality could be implemented with scripting, but this process can be very intrusive to an established project, such as a game that has already shipped with a single initial export. This makes the scripting method prone to introducing bugs during the porting process:

var controller_diagram_scene: Resource

func _init() -> void:
  if OS.has_feature("mobile"):
    controller_diagram_scene = load("res://touch_screen_controller.tscn")
  else:
    controller_diagram_scene = load("res://xbox_controller.tscn")

func _ready() -> void:
  var instance = controller_diagram_scene.instantiate()
  add_child(instance)

Is there a reason why this should be core and not an add-on in the asset library?

This functionality would be used often by projects that are ported to new platform, so it may make sense to have this as a core feature.

RandomShaper commented 3 days ago

I think this makes a lot of sense. When you are targeting very different devices, it's a very natural thing to do. I remember when back in time you'd bundle HD vs. non-HD assets for mobile games.

allenwp commented 3 days ago

I think this makes a lot of sense. When you are targeting very different devices, it's a very natural thing to do. I remember when back in time you'd bundle HD vs. non-HD assets for mobile games.

I remember that too! HD and non-HD assets were a very problematic approach because it would cause asset duplication, similar to code duplication. An art bug could creep into one image file that would not exist in the other, so it could only be found on certain devices. Usually this would be because the HD version was updated, but the non-HD was forgotten or something like that.

For this reason, the engine should do as much generation of asset variants as possible, as described in #10034. The only cases where the engine shouldn’t handle this sort of thing is when it’s not reasonable, such as in the case of needing to bundle an entire MP3 encoder and provide a full import interface for tweaking its parameters.

KoBeWi commented 3 days ago

You can achieve this with EditorExportPlugin. It allows you to customize resources based on feature tags (though it still requires extra code like in your example; you can however handle it automatically with a custom loading method).

allenwp commented 3 days ago

You can achieve this with EditorExportPlugin. It allows you to customize resources based on feature tags (though it still requires extra code like in your example; you can however handle it automatically with a custom loading method).

Thanks! Sometime in the near-ish future I’ll give this a try and update this proposal and my blog post. Maybe just a good asset library addon is all that’s needed…