Search Unity

Rebinding Keys Isn't reflected in existing controlSchemes

Discussion in 'Input System' started by ZachariBarnes, Feb 15, 2020.

  1. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    From my experience, yes.
     
    Aksoq likes this.
  2. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    Hehe im gona keep working on my other things and have a look in a week or two, looks like plenty to go over thank you! Who needs keybinds anyway :p
     
  3. TheHungryHedgehog

    TheHungryHedgehog

    Joined:
    Jan 17, 2018
    Posts:
    1
    Wait if the generated Input Action C# doesn't work with interactive rebinds how is one supposed to get the rebound actions then? If the overrides only apply to the InputActionAsset, then how do I bind actions using the InputActionAsset? It only gives me arrays of action maps which aren't really suited for binding specific stuff to them unless I specifically remember in what order what action in what map is and never change the order etc..

    Is there anyway I can rebind actions dynamically at runtime while also using actionmapname.actionname.triggered etc to use the action in the code?
     
  4. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    At the moment, it looks like you need to use the PlayerInput component and wire stuff up in the inspector. At least then it all worked for me.
     
  5. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,315
    Was one year enough time for you?
     
  6. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    Im just hoping if we are patient the devs will drop us an awesome example scene
     
  7. jolix

    jolix

    Joined:
    May 22, 2016
    Posts:
    70
    Doing this does not refresh the functions that were assigned before the rebind, only the ones after!

    uiActions.Cancel.ApplyBindingOverride(0, Keyboard.current[Key.T].path);

    I tried 1.0.2 and 1.1.0-preview.3.
    The Input Debug window show it's correctly rebound, but the old keybind is active and the new keybind is not working at all.

    How do I rebind from code (not the interactive one)?

    EDIT: I found the problem!
    If you have "Generate C# Class" enabled, it will create a new InputActionAsset at runtime!! (Why is that needed? Really strange)
    That means that the InputActionAsset in the InputSystemUIInputModule is a different one.
    So you have to change the bindings twice, once for each asset.
    Very confusing, not gonna lie.
     
    Last edited: Mar 30, 2021
    Neiist and laurentlavigne like this.
  8. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    Due to this (and other issues) the generated C# classes are pretty much unusable. I was able to get everything I need for proper rebinding to work, but only when wiring everything up in the inspector.
     
    RogDolos and jolix like this.
  9. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Did I miss this "gotcha" in the documentation somewhere?
     
  10. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Actually, I've just been working through this myself, and it definitely can work using the generated C# classes.

    The catch is this:
    Despite the documentation calling it a "C# wrapper class", it does not "wrap" the asset itself but instead contains a completely separate, internal copy of its JSON content, and creates a whole new asset from this when instantiated. On top of seeming to be needlessly wasteful, this also means that any binding overrides which you apply to the original asset are effectively ignored, because that asset isn't actually being used by the so-called "wrapper".

    With that in mind, if you're using the generated C# then you need to apply the binding overrides individually on every single instance of the class, rather than just once on the underlying asset.

    Naively, having read that it was a "wrapper" class and noting that they could be enabled / disabled individually, each one of my own components which used input had its own instance of that object. Once I realised what was going on I made my own wrapper to provide singleton access, and rebind overrides are applied to that.

    Also, note: at some point recently the methods SaveBindingOverridesAsJson() and
    LoadBindingOverridesFromJson(json, removeExisting) were added, so all you need to do is stash that string in PlayerPrefs and re-apply it when you instantiate your stuff.


    Edit: @Rene-Damm, I'm curious. Why does it work like this?
     
    Last edited: Sep 17, 2021
    Neiist likes this.
  11. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    At first, it worked the other way round. It would simply reference the asset just like an
    InputActionReference
    does.

    Unfortunately, this presents a problem to the player build pipeline. An asset that is referenced purely from code and not from data needs to be forced into the build in some other way -- if indeed, it is actually used.

    So, we opted to instead make the generated class completely self-contained. Has upsides and downsides.

    (ATM it actually just embeds the JSON though that part is easily changed so it creates the actions through the API (which would be many times faster))

    So yeah, both the duplication of assets done by PlayerInput for multiple players as well as the implicit duplication of the asset happening by "Generate C# Class" lead to unwelcome surprises with rebinding. IMO this should be improved by making the rebinding apparatus "smarter" in determining which particular action to rebind.

    Aside from that, support for control schemes with "Generate C# Class" needs improvements.

    As for docs, we're currently working on improved docs for how to do rebinding, control schemes, and multiple players when using "Generate C# Class".
     
  12. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Thanks for getting back to me. :)

    Just how "smart" does the rebinding system need to be to find and modify arbitrary action data scattered throughout every single possible game configuration, including ones which are dynamic?

    At some point a human has to map actions to physical controls any which way. Is there some reason not to centralise that into one asset shared by all input functionality and which is always included in the build?


    I don't understand. This also needs solving for other stuff in Unity. And, to me, that seems like a simpler problem to approach where the solution will have better benefits to more people.

    I've hacked around it in my own stuff outside of this, on multiple projects. I know others who have done the same. You're making a mission critical system which impacts literally every Unity user and you're hacking around it, in ways that cause over-complication and "unwelcome surprises". And so I hacked around your hack, and your current lead solution is to make the underlying system more complex... All because there's no clean way to ensure an asset is in a build?

    Why isn't Unity solving that, once, for everyone?

    Who do we need to lobby to make that happen?

    I'm serious about that. It sounds like Unity missing the forest because of the trees.


    What problem is the generated class intended to solve? The manual says it's about convenience, but at this point I wish I'd just put InputActionReferences in my classes because that would in fact have been far more convenient. Name changes wouldn't break builds, remapping would be less hacky, and mostly for me that whole asset duplication thing... well, wouldn't have been a thing.
     
    Last edited: Sep 17, 2021
  13. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Don't think there's a need to cater to every possible setup. What's there allows you to manually direct it wherever you need it to go.

    Just think we need to also get back to having a single centralized place where input configuration sits. Just like in the old system. Including having some defaults sit there that lead to zero-setup input in an empty project.

    And then having that be able to cater to multiple players and things like "Generate C# Class". All the rebinding would have to do then is play nicely with that global configuration.

    But that's just thoughts. Not saying I have a fully formed solution in my head.

    A "yeah, graphically setting up input is nice and all but please, can I just do all the rest of my input in just code" use case. Aside from that, it's original intention was to get rid of string lookups.

    The fact the code generation approach got way more attention than it should have is basically historical. It popped up first. Good long while before PlayerInput. And there's about ten different ways into the system. IMO it's good for a system to have options but there also needs to be a clear and simple path to success. Amid the options, that part suffered quite a bit and we're only now starting to clean that up.
     
  14. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    I'm with you there. It just seems like this is heading away from that, rather than towards it.

    Perhaps I misunderstood what you meant by "making the rebinding apparatus smarter"? My interpretation was that instead of centralising things you were thinking about making the rebinding system better support having decentralised sets of actions.

    That's the impression I was under. To my mind, at least, InputActionReference does that pretty well. I know it means you need to have stuff in the Inspector, but one way or another that bit of configuration has to happen somewhere - it's a string or an Inspector property or it's something.

    Yeah, it strikes me as trying to be all things for all people, and struggling as a result.

    Aside from the hacky weirdness with the asset duplication, and the sleep-related input locking bug, mostly I think a real focus on documentation is needed. An input system having options is a good thing, especially since Unity is used in such versatile cases. What's really needed is a high-level overview of the different approaches you can take, and the pros and cons of each. Why would you use event based vs. polling input? Why would you use the generated class vs. InputActionReferences vs. putting InputActions directly on your objects?

    Personally, when I converted my game to use the new system, a quick-start guide for converting old-to-new rather than starting fro scratch would have been great. It's a great opportunity for a step-by-step guide, but even if the docs people don't have time for that, a page which explains the closest equivalent in the new system for the parts of the old one would be great. (This is what an action is. This is how you bind inputs in the UI. These are the ways to access an action, and how to poll for different types of input once you're there.)

    Also note that plenty of rookies do stuff by looking up tutorials and following steps. So quite a few beginners are going to get themselves into a mess when they mix approaches without even realising it.
     
  15. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Sorry, meant more the opposite. Making it easier for the rebind stuff to be aware of the actions that are there.

    Yup, pretty much the sum of it.

    Agreed, better docs is a big part of it. That and then simply making it easier to automatically end up on the right path.

    The migration page sort of does the equivalence thing but in a rather poor way. Agree that a proper "how to go from old to new" page in the docs is much needed.

    We are in the process of slowly overhauling our docs (stuff like this).
     
    angrypenguin likes this.
  16. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Yeah, that sounds good.

    Getting there is a challenge when there are multiple "right paths" and a highly varied audience, so I don't envy you that task!
     
  17. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Separately, may I ask why this isn't something which happens by default? A thing isn't finished until it's documented properly, and I get the impression that the people making stuff understand that.
     
  18. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    So, can we rebind yet :p I've honestly just ignored this problem for a good six month while doing other things. I did noticed the Input System is now out of preview? Really do like it mind, makes things so much easier to setup, well apart from the rebind xx
     
  19. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    For "Generate C# Class", rebinding will work as is with PerformInteractiveRebinding.

    Code (CSharp):
    1. // Start rebinding "fire" action.
    2. var fireAction = myActions["fire"];
    3. var rebind = fireAction.PerformInteractiveRebinding()
    4.     .Start();
    When used with the
    RebindActionUI
    , the action reference has to be updated manually ATM in order for it to rebind the correct action. For example:

    Code (CSharp):
    1. // Generated actions we're using.
    2. private MyActions m_Actions;
    3.  
    4. void OnEnable()
    5. {
    6.     var ui = GetComponent<RebindActionUI>();
    7.     var currentReference = ui.actionReference;
    8.     var actionName = currentReference.action.name;
    9.     ui.actionReference = InputActionReference.Create(m_Actions[actionName]);
    10. }
     
    pantang likes this.
  20. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    Thank you! I will have a play later on :D
     
  21. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    Yup im still stuck, I can't reference the RebindActionUI, what do I need to be using?
     
  22. RaoulWB

    RaoulWB

    Joined:
    Feb 9, 2014
    Posts:
    14
    For quite some time I've forgotten to link to this video here. It's a tutorial that uses the input rebinding sample we worked with. It effectively covers everything needed in a game.

    Hopefully it still helps someone!

     
  23. Tom163

    Tom163

    Joined:
    Nov 30, 2007
    Posts:
    1,290
    Why isn't this in the documentation? I'm not even asking why this example code isn't in the module itself as it should be, but why isn't it even in the docs? Honestly, guys, the InputSystem right now, with these issues, the unfinished documentation, etc. makes the impression it should be version 0.2 not 1.2
     
    udemyrootgames likes this.
  24. udemyrootgames

    udemyrootgames

    Joined:
    Aug 3, 2021
    Posts:
    15
    Any explanations on how to do PERSISTENT rebinding with C# generated script? Is it even possible?
     
  25. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    If I'm not misunderstanding what you want, it's this:
    It seems hacky to me, but also seems to be the officially intended workflow.
     
  26. udemyrootgames

    udemyrootgames

    Joined:
    Aug 3, 2021
    Posts:
    15
    That doesn't work when you use C# generated script approach.
     
  27. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Yes it does. I'm doing it, and I described how in another post here earlier.
     
  28. udemyrootgames

    udemyrootgames

    Joined:
    Aug 3, 2021
    Posts:
    15
    I can't make it work. Can you please post one example of how you managed to do it?
     
  29. nalex66

    nalex66

    Joined:
    Aug 26, 2022
    Posts:
    54
    I would also love to know how you made this work. I'm stuck on what you mean by "apply it individually to every instance of the class."

    I've been beating my head against this for a week, trying several different ways to switch XR locomotion to left-handed mode at runtime (for a user settings menu).
     
  30. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    What part about it can I make more clear?

    If you're using more than one instance, rebinds must be applued to each of them. They each have their own, independent copy of the bindings data.
     
  31. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,619
    Actually... here's advice that's probably better. Don't have multiple instances of the Input Actions object.

    I wrapped one in a Singleton and everything uses that. Only one place for rebinds, and no silly duplication of what should usually be the same data, unless you have local multiplayer or whatever.
     
    Last edited: Nov 11, 2022
  32. FiveDegrees

    FiveDegrees

    Joined:
    May 21, 2021
    Posts:
    1
    Has anyone found a non-messy solution to this yet?
     
  33. RaoulWB

    RaoulWB

    Joined:
    Feb 9, 2014
    Posts:
    14
    The video I posted here above might be most clean solution. That's what I've relied on for over a year now without it feeling hack-y in any way.
     
  34. LordTommy33

    LordTommy33

    Joined:
    Sep 12, 2017
    Posts:
    7
    Unfortunately this video doesn't show how it works across scene changes or if you don't somehow have a singleton style system setup. I know angrypenguin has mentioned this and I'm trying to implement it but I'm basically beating my head against a wall trying to figure out how the rebinding example actually works to do this.
     
  35. KostiaLiakhov

    KostiaLiakhov

    Joined:
    Mar 13, 2021
    Posts:
    13
    Any updates on this? I'm quite new and struggling to understand where this code should go :(

    Code (CSharp):
    1. // Generated actions we're using.
    2. private MyActions m_Actions;
    3. void OnEnable()
    4. {
    5.     var ui = GetComponent<RebindActionUI>();
    6.     var currentReference = ui.actionReference;
    7.     var actionName = currentReference.action.name;
    8.     ui.actionReference = InputActionReference.Create(m_Actions[actionName]);
    9. }
    Would really appreciate any examples/projects, have been struggling with this for days now