Open passivestar opened 1 month ago
You can't copy a character controller into a newly created project, drop a character prefab into the scene and start playing. Even a simple character controller might require a lot of different actions (jumping, sprinting, crouching, interacting, etc) and there's no straightforward recognized way to add those bindings into a project from your character controller asset
If it's an EditorPlugin, it can create input actions in its _enter_tree()
method (just like it can create/modify project settings and autoloads). They can be removed in _exit_tree()
if they are equal to the default value too.
However, there's a bug which makes input actions added by @tool
scripts not appear in the Project Settings: https://github.com/godotengine/godot/issues/44776
In short, it's possible for editor plugins to perform automated setup so that they work out of the box. A lot of editor plugins currently don't do this, but they could once the above bug is fixed :slightly_smiling_face:
@Calinou <tangent>
Editor plugins are awkward. They need plugin.cfg
. They need to be enabled. They need to be in a specific folder. I just want to copy files. I may have 100 different reusable components stored locally that I want to be able to drag and drop into my project. Some of them may not even have any scripts in them (i.e a scene with only a pre-configured Environment node that I want to reuse in different projects). If some of them are plugins I need to consciously remember that and drag them into the addons
folder instead. I want a player controller and an environment to be in the same UX realm and have the same workflow. Editor plugins create unnecessary complexity and UX friction out of thin air. More often than not there isn't any value in "enabling" things that you copy into your project (for a character controller any setup is avoidable if godot was to adopt unity's approach where there's no global input bus, only individual input components referencing input map resources)
IMO plugins need to serve the purpose of allowing you to package an asset into a nice box with a description on it (in plugin.cfg
) for the ease of distribution (and potentially a list of dependencies if godot gets support for them in the future). But the plugin system shouldn't affect how your asset itself works </tangent>
😄
More often than not there isn't any value in "enabling" things that you copy into your project (for a character controller any setup is avoidable if godot was to adopt unity's approach where there's no global input bus, only individual input components referencing input map resources)
It sounds like there should be a way for newly installed editor plugins to be automatically enabled then. :slightly_smiling_face:
This can be done for addons installed from the asset library, but also for new addons detected on the project filesystem after the editor window gains focus (so it works with manually copied folders).
It works like this in most other programs where plugins are enabled as soon as you install them (web browsers, code editors/IDEs, etc).
I think I had a PR for this at some point (for the asset library at least), but I can't find it right now.
It sounds like there should be a way for newly installed editor plugins to be automatically enabled then. 🙂
Absolutely! And also make plugin.cfg
optional and make it work from any directory and we will have reinvented unity's approach (where plugins are detected by their class alone) :D
My point initially was that plugin system shouldn't be necessary for something like a character controller at all. It doesn't even make sense semantically. EditorPlugin
class API is all about extending editor's functionality (adding docks, custom import handlers, custom debugger stuff, inspectors, etc). A character controller is not a plugin. It's an asset 🙂
I also ran into this. My workaround involves reading the actions from a folder.
var folder_path := (get_script() as Script).resource_path.get_base_dir()
func _load_input_actions() -> bool:
var result := false
var input_folder_path := folder_path.path_join("input")
for folder in DirAccess.get_directories_at(input_folder_path):
var action_path := input_folder_path.path_join(folder)
var events:Array[InputEvent] = []
for file in DirAccess.get_files_at(action_path):
var input_event := load(action_path.path_join(file)) as InputEvent
if input_event != null:
var duplicated:InputEvent = input_event.duplicate()
if duplicated != null:
events.append(duplicated)
var dict := Dictionary( {"deadzone" : 0.5 , "events": events } )
result = _write_project_setting("input/" + folder, dict) or result
return result
func _write_project_setting(setting_name:String, value:Variant) -> bool:
var already_exists := ProjectSettings.has_setting(setting_name)
if already_exists:
var found:Variant = ProjectSettings.get_setting(setting_name)
if typeof(found) == TYPE_DICTIONARY and typeof(value) == TYPE_DICTIONARY:
var value_dictionary:Dictionary = value
var found_dictionary:Dictionary = found
for key:Variant in value_dictionary.keys():
if found_dictionary.has(key):
continue
found_dictionary[key] = value_dictionary[key]
value = found_dictionary
if str(found) == str(value):
return false
ProjectSettings.set_setting(setting_name, value)
return true
I use the return value to know if need to call ProjectSettings.save()
and EditorInterface.restart_editor(true)
.
Addendum: By the way, in Unreal "Enhanced Input" system, input actions are also files.
Describe the project you are working on
A reusable first person character controller
Describe the problem or limitation you are having in your project
Input map is currently a part of the project's
.godot
fileYou can't copy a character controller into a newly created project, drop a character prefab into the scene and start playing. Even a simple character controller might require a lot of different actions (jumping, sprinting, crouching, interacting, etc) and there's no straightforward recognized way to add those bindings into a project from your character controller asset
Describe the feature / enhancement and how it helps to overcome the problem or limitation
In Unity input bindings are resources (scriptable objects). This feature is essential when distributing character controllers on the asset store because it allows an asset developer to provide default bindings with the asset. This allows users to quickly test a controller without any manual setup. Users can also use the default bindings file as a template for their own bindings - they can easily be copied and modified (this is a bit different from a config file https://github.com/godotengine/godot-proposals/issues/423 because if bindings are a resource they can be easily edited in inspector)
Without it users would have to refer to the asset's manual to find out the names of actions that need to be bound, which is a lot of unnecessary friction
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Implementation details are up for discussion, I suppose project would need to support referencing a bindings resource through a path or a uid. It could also be a list of resources instead of a single resource to support a more modular and non-destructive approach to bindings (in that case bindings from the latter resources would have higher priority in case of action name conflicts). Project settings Input Map tab UI would need to be changed to support showing the list of bindings resources and editing them from there for convenience
It's also worth mentioning that in Unity's Input System those bindings aren't global at all, they are recognized from any
PlayerInput
component. I think this idea is worth exploring as well, because this approach has been working pretty well for Godot (i.e LightmapGI is a node unlike in other engines). It's more flexible, it's easier to reason about and it allows for a more predictable scripting API. Of course if we do this we'll need to consider UX and make sure everything still works out of the box as you'd expect. Managing complexity can be a challenge, but I believe it's possible to create an input system that is both easy to use and doesn't compromise on flexibility/extensibility if you need itIf this enhancement will not be used often, can it be worked around with a few lines of script?
To work around this limitation I made a couple of resources and added some logic to the player controller script to load actions from them:
This exposes a "button" on the character controller, that, when clicked, adds predefined input actions from a custom resource into the project file
The problems are:
@tool
which means you need to guard every functionAll of this can be avoided if Godot ships with a less rigid input binding system
Is there a reason why this should be core and not an add-on in the asset library?
The point of this is to reduce complexity when setting up a controller in a new project. Having to download an asset for an input system would defeat the purpose (Unity's input system is a separate package that needs to be downloaded and people aren't super happy about that)
It's also worth mentioning that Godot doesn't have any support for dependencies. Which means that when a user downloads your character controller, you'd need to show a message asking to manually download an input system dependency just to be able to see a character running around and jumping on the screen, which doesn't sound great to say the least. Ideally your asset should ship with all of the code required to use it, at least when it's something as simple as a character controller