Search Unity

InControl - input and cross platform controller support for Unity, made easy!

Discussion in 'Assets and Asset Store' started by pbhogan, Jul 18, 2014.

  1. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    I don't know how you'd do this with PlayMaker, but normally you'd want to iterate over InputManager.ActiveDevices (plural) and test for presses. Only checking the single ActiveDevice is not good since if one person is spamming buttons, it will stay the active device and interfere with detecting someone else pressing a button.
     
  2. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    3,527

    Can you write an example how to do this in c# ? I can then port it to playmaker
     
  3. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    I might do an example at some point, but it's not just a few lines of code and involves UI and a bunch of support boilerplate, but the pseudo code would be something like below for the UI you typically see on the Nintendo Switch (which I consider a good case study in how to do it right).



    Code (CSharp):
    1.  
    2. while waiting for players to join
    3.     for each device in InputManager.Devices
    4.         if device.LeftBumper.IsPressed and device.RightBumper.IsPressed
    5.             if device is assigned to any player slot
    6.                 assign device to first available player slot
    7.             else
    8.                 visually pulse player slot
    9.             end
    10.         end
    11.     end
    12.     for each player in players
    13.         if player.device.Action1.IsPressed
    14.             stop waiting for players to join
    15.         end
    16.     end
    17. end
    18.  
    In reality, it would be somewhat more complicated than this because you'd also want to use action sets instead of just devices and also handle controller disconnects during the process.
     
    Lars-Steenhoff likes this.
  4. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    3,527
    for each device in InputManager.Devices

    This is the part that I need the most, the UI and the pressing of the buttons I can all handle in playmaker.

    What I do now is check device index but as you mentioned in the manual thats not the right way
    This is the code for the playmaker action that I use to check if a control of the player was pressed.


    Code (CSharp):
    1. using UnityEngine;
    2. using InControl;
    3.  
    4.  
    5. namespace HutongGames.PlayMaker.Actions
    6. {
    7.     [ActionCategory( "InControl" )]
    8.     [Tooltip( "Sends an event when control state for a given device is pressed. Optionally store the control state in a bool variable." )]
    9.     public class InControlGetControlWasPressed : FsmStateAction
    10.     {
    11.         [Tooltip( "The index of the device (set to 0 to query the current active device)." )]
    12.         public FsmInt deviceIndex;
    13.        
    14.         public InputControlType control;
    15.  
    16.         [Tooltip( "The absolute value at which a control is considered pressed." )]
    17.         public FsmFloat stateThreshold;
    18.        
    19.         public FsmEvent sendEvent;
    20.  
    21.         [UIHint( UIHint.Variable )]
    22.         public FsmBool storeResult;
    23.        
    24.  
    25.         public override void Reset()
    26.         {
    27.             deviceIndex = null;
    28.             control = InputControlType.Action1;
    29.             stateThreshold = 0.5f;
    30.             sendEvent = null;
    31.             storeResult = null;
    32.         }
    33.  
    34.  
    35.         public override void OnEnter()
    36.         {
    37.         }
    38.  
    39.  
    40.         public override void OnUpdate()
    41.         {          
    42.             var inputControl = Device.GetControl( control );
    43.             inputControl.StateThreshold = stateThreshold.Value;
    44.  
    45.             if (!storeResult.IsNone)
    46.             {
    47.                 storeResult.Value = inputControl.WasPressed;
    48.             }
    49.  
    50.             if (inputControl.WasPressed)
    51.             {
    52.                 Fsm.Event( sendEvent );              
    53.             }
    54.         }
    55.  
    56.  
    57.         InputDevice Device
    58.         {
    59.             get
    60.             {
    61.                 return deviceIndex.Value > 0 ? InputManager.Devices[deviceIndex.Value - 1] : InputManager.ActiveDevice;
    62.             }
    63.         }
    64.     }
    65. }
     
  5. OJDee

    OJDee

    Joined:
    Feb 11, 2014
    Posts:
    64
    Hi,

    Wondering what the best way to achieve camera movement using mouse only when right button pressed.

    Ideally I would like a PlayerTwoAxisAction to be bound to right stick and mouse movement, but not sure how to get the right button modifier in there?

    Don't want to wrap the movement code with an if statement based on right button held down as that will interfere with joystick case...


    Also, how to have different sensitivity for a single binding - ie more sensitive wehn moving view with mouse than when moving view with a stick?

    Anyone? Seems like a pretty common use case.. @pbhogan ?

    Thanks
     
    Last edited: Feb 23, 2021
  6. lazylukey

    lazylukey

    Joined:
    May 26, 2017
    Posts:
    36
    Hi @pbhogan we actually resolved this error in a very simple way. We added `
    if (applicationHasQuit) return;` to OnSceneWasLoaded in InControlManager.cs just after the
    IsNotTheSingleton check
     
  7. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    Great—I'll make that change to the next release too.
     
  8. Slashbot64

    Slashbot64

    Joined:
    Jun 15, 2020
    Posts:
    326
    Any advantage this this over just using the new input manager? is there any example scene for rebinding controls in ugui?
     
  9. hangar

    hangar

    Joined:
    Feb 1, 2013
    Posts:
    21
    GetAppleGlyphNameForControl doesn't seem to be working at all on tvOS. Is there a way we can work around?
     
  10. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    Are you testing on tvOS 14? It requires at least that version to work. But I'll test it and see if maybe something else is missing. I've only really tested it on macOS and iOS.
     
  11. eddyspaghetti

    eddyspaghetti

    Joined:
    Aug 7, 2013
    Posts:
    5
    Unfortunately, I'm adding my name to the list of folks running into crashes with the Native dll. Our game released on less than 2 weeks ago, and we've gotten two reports of crashing on startup (both Windows). One user had a USB pedal attached to the system, while another reports having no peripherals other than keyboard and mouse. The crash logs look pretty much identical in both cases.

    In case it helps, both users had been able to run the game initially, but after their first time playing, they started getting crashes immediately on startup and can no longer start the game. Manually deleting the native dll fixed the first user - waiting to hear back from the second, but I suspect it'll fix it. Working on a build with native support disabled so I can get users up and running.

    InControl version 1.7.1, Unity version 2019.3.15f1

    Stack Trace of Crashed Thread 6204:
    ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 00007FFD383E22B3)
    0x00007FFD383E22B3 (InControlNative) (function-name not available)
    0x00007FFD45B77034 (KERNEL32) BaseThreadInitThunk
    0x00007FFD467E2651 (ntdll) RtlUserThreadStart
     
  12. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    You are running a very old version of InControl. Please upgrade before posting crash reports that may already have been fixed.
     
  13. eddyspaghetti

    eddyspaghetti

    Joined:
    Aug 7, 2013
    Posts:
    5
    Sorry - looking through this thread, it seemed like it was the same, or at least related to crashes others reported in newer versions of the dll (as recently as Feb 15). I considered upgrading, but it seemed unrelated to any of the fixes mentioned in the release notes of subsequent versions. Upgrading any part of a project is never risk-free - especially with a released multi-platform product - so I try not to do upgrade unless I'm pretty sure it will solve a problem.

    Anyway, the crash wasn't listed as a known issue, and I was hoping that the information provided would be useful to either you (the developer), or others who experience the issue. Sorry if it's a distraction.
     
  14. cloverme

    cloverme

    Joined:
    Apr 6, 2018
    Posts:
    198
    I see there's an incontrol mapping for the scroll wheel for a mouse, how do you use it?
     
  15. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
    @pbhogan We're having some issues with the switch pro controller using v1.8.3. As soon as the game starts, it appears that random inputs are being pressed even though no input on the controller is physically pressed. Have you seen this issue before?

    Thank you!
     
  16. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    action.AddDefaultBinding( Mouse.PositiveZ );
    action.AddDefaultBinding( Mouse.NegativeZ );

    And you can adjust the scale of the scroll wheel movement by setting MouseBindingSource.ScaleZ
     
  17. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    The pro controller currently does not work when connected over USB, and I've heard reports of random inputs when Steam is running in the background. Could that be it? I'm looking into adding proper support for it when used wired.
     
    atrivedi7 likes this.
  18. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    There have been several fixes and tweaks added to the native plugin, although they're not always mentioned in patch notes, or it may not be clear it's a fix for a crash. One fix was for devices that declared an excessively high number of buttons (hundreds) which caused a crash, for example.

    Currently there are two known reasons for crashes with the native plugin. One is foot pedals that all seem to be cheap variants of the same thing that uses specific software that causes a crash. I've never been able to reproduce the problem with one of those pedals, and at this point it may even have been fixed by other changes, but it comes up every now and then. Or at least it did until a while ago. But usually with older versions.

    The other has to do with Steam and reinitializing the plugin after launch which seems to confuse whatever hooks steam has into the OS. The fix, and general best practice anyway, is to have the InControl manager set to Do Not Destroy On Load and have it live for the lifetime of the application. You can still have it in every scene for development and it'll automatically detect duplicates loaded in and destroy them before they initialize.

    Beyond that, no other known crashes are known with the latest version (1.8.4). But if you come across a specific device that causes a crash, I'd love to know about it especially if you can give me the exact model. Unfortunately, crash dumps are mostly useless because I can't fix it even if I know the exact API call unless I reproduce it with the hardware present. Usually, the bug is much more subtle like the device reports some garbage information or I need to exclude a certain hardware product ID from some calls.
     
  19. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
    Thank you for the quick response! We await that update :)

    I was able to stop the random input only the first time when turning off steam. When I turned it back on and off again, it still did random input. Very strange, indeed.
     
  20. hangar

    hangar

    Joined:
    Feb 1, 2013
    Posts:
    21
    Nevermind, somehow it seems to work now. It wasn't a version issue, as I'm on 14.4. tvOS has been very flakey for me... sometimes it fails to log into gamecenter, and then it just silently stopped working for a while. If I run into the issue again and find a lead, I'll let you know.
     
  21. WryMim

    WryMim

    Joined:
    Mar 16, 2019
    Posts:
    69
    Hello. Tell me how to get the PRESS AND RELEASE of any buttons? (universal for keyboard and joystick), similar to:
    Code (CSharp):
    1. if (InControl.InputManager.AnyKeyIsPressed)
    But WasReleased
     
  22. hangar

    hangar

    Joined:
    Feb 1, 2013
    Posts:
    21
    OK, I'm having issues again with GetAppleGlyphNameForControl but now on macOS. Can you confirm that it's implemented on macOS? (I know there's differences between UIKit and AppKit.) We tried a bunch of controllers, but Native.GetAnalogGlyphName and Native.GetButtonGlyphName are returning 0 size.
     
  23. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,341
    Hi, thanks for making InControl, great Asset!

    I was wondering if there is a simple way to allow UI navigation with the DPad and thus made this little script:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.UI;
    4.  
    5. public class DPadSelectionForUI : MonoBehaviour
    6. {
    7.     public bool DoNotDestroyOnLoad = true;
    8.  
    9.     public void Awake()
    10.     {
    11.         if (DoNotDestroyOnLoad)
    12.         {
    13.             DontDestroyOnLoad(this);
    14.         }
    15.     }
    16.  
    17.     public void LateUpdate()
    18.     {
    19.         if (InControl.InputManager.ActiveDevice.DeviceClass == InControl.InputDeviceClass.Controller && InControl.InputManager.ActiveDevice.DPad.IsPressed)
    20.         {
    21.             var currenctSelected = EventSystem.current.currentSelectedGameObject;
    22.             if (currenctSelected != null)
    23.             {
    24.                 var selectable = currenctSelected.GetComponent<Selectable>();
    25.                 if (selectable != null)
    26.                 {
    27.                     Selectable newSelection = null;
    28.                     if (InControl.InputManager.ActiveDevice.DPad.Left.WasPressed || InControl.InputManager.ActiveDevice.DPad.Left.WasRepeated)
    29.                     {
    30.                         newSelection = selectable.FindSelectableOnLeft();
    31.                     }
    32.                     else if (InControl.InputManager.ActiveDevice.DPad.Right.WasPressed || InControl.InputManager.ActiveDevice.DPad.Right.WasRepeated)
    33.                     {
    34.                         newSelection = selectable.FindSelectableOnRight();
    35.                     }
    36.                     else if (InControl.InputManager.ActiveDevice.DPad.Up.WasPressed || InControl.InputManager.ActiveDevice.DPad.Up.WasRepeated)
    37.                     {
    38.                         newSelection = selectable.FindSelectableOnUp();
    39.                     }
    40.                     else if (InControl.InputManager.ActiveDevice.DPad.Down.WasPressed || InControl.InputManager.ActiveDevice.DPad.Down.WasRepeated)
    41.                     {
    42.                         newSelection = selectable.FindSelectableOnDown();
    43.                     }
    44.                     if (newSelection != null)
    45.                     {
    46.                         EventSystem.current.SetSelectedGameObject(newSelection.gameObject);
    47.                     }
    48.                 }
    49.             }
    50.         }
    51.     }
    52. }
    The script works just fine.
    A minor thing though: I would like to reduce the time (delay) it takes to start repeating while keeping a button pressed. Is there a config for that? I do not use native nor InputX. Thanks.
     
  24. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
    Would you expect switch pro controller to work on Mac over bluetooth? We are currently seeing issues with this setup as well. Even if we enable steaminput, we are getting no inputs from the controller wired or wirelessly (whereas on windows over a wired connection, if we enable steainput, we do get the controller to work).

    Thanks in advance!
     
  25. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,561
    I really like InControl and I have used it in my last 2 games.

    On my new game in Unity 2019.4.24 Im using InControl 1.8.4 for IOS with Xcode 11 on MAcOS Mojave 10.14.6 and I get this error when I build in Xcode

    Undefined symbols for architecture arm64:
    "_OBJC_CLASS_$_GCColor", referenced from:
    objc-class-ref in InControlNative.a(mfi_device.o)
    ld: symbol(s) not found for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)​
     
  26. Vagabond_

    Vagabond_

    Joined:
    Aug 26, 2014
    Posts:
    1,148
    Hey @pbhogan,

    i am trying to add support for Thrustmaster and Logitech wheels for a racing game... i am using the new Input System now, but it's seems impossible for me to that... i have a couple of questions:

    1. Can InControl work if we have the Input System package installed or they will fight each other ?
    2. If 1 is fine, is there a way to add support for different steering wheels using InControl ?

    The problem i have is that with the IS, it returns a normalized vector for Sticks (Vector2 value) and i can't find a way to bind to the so called child controls which get values from 0 to 1 which is weird as the vector2 they compose seems to be normalized !

    Do you think it would be easy to add steering wheels support using InControl ?

    Thanks !
     
  27. paulcodemonkey

    paulcodemonkey

    Joined:
    Oct 11, 2016
    Posts:
    15
    Hi @pbhogan

    Thanks for continuing to support this asset.

    I'd like to read the dedicated direction buttons on the new Apple TV remote.

    Not sure if the tvOS native library needs updating or I just need some new mappings in AppleTVRemoteUnityProfile.cs.

    Any advice appreciated.

    InControl 1.8.4, Unity 2020.3.3f1, tvOS 14.6

    (I have one of the new remotes if I can help with any debugging.)
     
  28. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    1. Prior to 1.8.4, as long as you had Project Settings > Player > Active Input Handling set to Both, InControl would continue to work fine and would simply ignore the new input system. As of 1.8.4, InControl will try to detect when you have the new input system package installed and will try to use it rather than the old input system.

    2. Using the new input system, InControl currently only supports gamepads, and will use it for mouse and keyboard input too.

    I don't particularly recommend using the new input system with InControl. You might as well just use the new input system by itself and save the additional processing overhead. But some find InControl's API easier to use so it has been a requested feature.

    As dar as what you mentioned about Sticks from the new input system, I don't really know what they're doing with their mappings and some of them might well not make sense. For obvious reasons, I don't use Unity's input system.

    All that said, InControl isn't really great at supporting racing wheels and things other than gamepads either. More specifically, not many, if any, mapping profiles exist. You probably could create mapping profiles for such devices through InControl's input handling rather than with the new input system installed.

    Adding support for controllers involves having them physically present to create and test the mappings. This is one of the reasons InControl doesn't have many profiles because these devices are usually very expensive and fairly niche.

    You can create the profile yourself if you like. It’s not very hard but takes a little bit of manual trial and error.

    First, you’ll want to fire up the TestInputManager scene on device (or run it in the Unity editor for desktop systems). The controller should come up as an unknown controller if InControl doesn’t support it and will list a bunch of analogs and buttons. Fiddling with the controls will show you which inputs respond as which buttons and analogs.

    Then copy one of the profiles in InControl/Source/Unity/DeviceProfiles and adjust it accordingly. Other than the button/analog mappings, you have to make sure the supported platforms property has the right string in it and the joystick names property should have the name as it appears to Unity in GetJoystickNames(). This also shows up in TestInputManager.

    Similarly, if you want to add support for the native input module, the profiles are located in InControl/Source/Native/DeviceProfiles although the device matching is usually based on vendor ID and product ID values instead of names. Just look at one of the other native profiles and you’ll see what I mean. These will also show up on screen.

    If you have full working profiles, you are welcome to send it to me for official inclusion in the package.
     
  29. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    I just got a new Apple TV myself. I'll have to take a look and see what the situation is there. But I haven't had a chance to look into it at all yet and I'm currently doing some major renovations in native plugin. So look out for a fix for this in an update.

    If you want to look into it a bit yourself, try disabling that profile (comment it all out) and then see if those buttons respond at all in the TestInputManager scene when it comes up as an unknown controller.
     
  30. dr4

    dr4

    Joined:
    Jan 14, 2015
    Posts:
    108
    Hi @pbhogan ,

    for the last 4 hours I have been trying to rebind my keys at runtime, no success so far, I tried the code lines of the section http://www.gallantgames.com/pages/incontrol-rebinding-at-runtime but no matter what I do
    Code (CSharp):
    1. ListenForBinding
    does nothing, I get no error whatsoever, it just doesn't do anything and does not produce any output, so far I have this code (tried many different variants), I get the correct action and just silence after that (if it wasn't because of the Debug.Log output I would think it is dead)

    Code (CSharp):
    1.     void ReplaceKeyTest()
    2.     {
    3.         Debug.Log("starting");
    4.         currentAction = gamePadConfiguration.GetPlayerActionByName("Attack");
    5.         Debug.Log(currentAction.Name);
    6.         ListenForBindingHelper(currentAction);
    7.     }


    Code (CSharp):
    1.     void ListenForBindingHelper(PlayerAction playerAction)
    2.     {
    3.         BindingSource originalBinding = null;
    4.  
    5.         playerAction.Owner.ListenOptions.IncludeKeys = true;
    6.         playerAction.Owner.ListenOptions.IncludeMouseButtons = true;
    7.         playerAction.Owner.ListenOptions.IncludeControllers = true;
    8.  
    9.  
    10.         Debug.Log("makind sure that it is not null:");
    11.         Debug.Log(playerAction.Owner.ListenOptions);
    12.  
    13.         // add my own callbacks, so i can deal with how i want the binding added.
    14.         playerAction.Owner.ListenOptions.OnBindingFound = (action, binding) =>
    15.         {
    16.             Debug.Log("Binding found... " + binding.DeviceName + ":" + binding.Name + " - " + action.Name);
    17.             if (binding == new KeyBindingSource(Key.Escape))
    18.             {
    19.                 Debug.Log("esc pressed, stop listening" );
    20.  
    21.                 action.StopListeningForBinding();
    22.                 return false;
    23.             }
    24.             Debug.Log("replaced binding");
    25.  
    26.             action.ReplaceBinding(originalBinding, binding);
    27.  
    28.             // action.InsertBindingAt(bindingIndex, binding);
    29.  
    30.  
    31.             action.StopListeningForBinding();
    32.  
    33.             return false;
    34.         };
    35.  
    36.         Debug.Log("listening for bindings");
    37.         playerAction.ListenForBinding();
    38.     }
     
    Last edited: Jul 11, 2021
  31. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    I don't see anything obviously wrong. Does the bindings example in the Examples folder work for you?

    Does input from InControl work outside of this? You have the InControl manager in the scene, you're getting devices showing up in InputManager.Devices, things like InputManager.ActiveDevice.Action1 works, etc?
     
  32. dr4

    dr4

    Joined:
    Jan 14, 2015
    Posts:
    108
    Thanks for answering @pbhogan ,

    I wasn't aware of that example scene, that script works fine even in my scene, but my own script with my player actions wouldn't work even using an exact copy of the example script (with my PlayerActions)) , after a few hours I think that I finally understand why, basically the example script uses the player actions as such:


    Code (CSharp):
    1. public static PlayerActions CreateWithDefaultBindings()
    2.         {
    3.             var playerActions = new PlayerActions();
    4.             ...
    5.             return playerActions;
    6.         }
    in my case I'm using my player actions as a static object:

    Code (CSharp):
    1.  
    2.        private static GamepadConfiguration gamepadConfiguration;
    3.  
    4.         public static void BindKeys()
    5.         {
    6.             gamepadConfiguration = new GamepadConfiguration();
    7.  
    8.             #region Menu actions
    9.  
    10.             gamepadConfiguration.Pause.AddDefaultBinding(Key.Escape);
    11.             gamepadConfiguration.Pause.AddDefaultBinding(InputControlType.Command);
    12.  
    13.            ...
    14. }
    15.  
    then I'm using all my static objects like this:
    Code (CSharp):
    1.         public static bool GetPauseKey()
    2.         {
    3.             return gamepadConfiguration.Pause.WasPressed;
    4.         }
    5.  
    6.            ...
    7.  
    8.            if (GetPauseKey())
    9.             {
    10.                 PauseAndResumeGame();
    11.             }
    so basically InControl really seems to dislike having player actions as an static object, but it also give no errors or warnings about it:
    upload_2021-7-12_21-57-44.png

    upload_2021-7-12_21-58-3.png

    I have to add that I have been using it for 2 years now like this and this is the first issue I have
     

    Attached Files:

    Last edited: Jul 12, 2021
  33. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    You should be able to use it as a static variable, but you have to instantiate the object AFTER InControl is setup or it can't properly initialize and connect to InputManager.

    You can use the InputManager.OnSetup callback to call it at the right time, or just make sure the script calling BindKeys() (or whatever is doing new GamepadConfiguration();) happens after InControlManager is initialized. That's why I recommend putting InControlManager really early, if not first, in the script execution order.
     
  34. dr4

    dr4

    Joined:
    Jan 14, 2015
    Posts:
    108
    I will try that, thank you for your time!
     
  35. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
  36. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    It should work on Windows if the game has XInput enabled in the InControl configuration. At that point, any XInput compatible controller would work (and all Microsoft Xbox controllers are).

    InControl actually has two XInput settings, but the one I recommend is turning on Native Input and the XInput setting within that. This is the default when setting up InControl today. But older games may predate these defaults, or may have turned it off.

    Since macOS Catalina, Xbox 360 controllers are not supported on macOS anymore as the only existing third-party driver stopped working and Apple only supports a limited set of controllers through their Game Controller framework (https://support.apple.com/en-us/HT210414).

    Okay, all that said, as I recall, genuine Microsoft Xbox 360 controllers don't connect wirelessly to PCs, except for one model with a wireless USB adapter which I have and tested with (although admittedly it's been a while since I last have). If this is some third-party controller, all bets are off unless it's PC & XInput compatible.
     
    atrivedi7 likes this.
  37. andrewspencer_unity

    andrewspencer_unity

    Joined:
    Feb 19, 2019
    Posts:
    4
    @pbhogan how are you meant to add custom device profiles to InControl?
    I've made a profile for SteelSeries Stratus Duo since that's not currently supported, but I'm not sure how to add it to the customDeviceProfiles list. It works when just adding the class name to the UnityInputDeviceProfileList but that's not a great solution.
     
  38. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    This is automated. If you create either a Unity or Native profile properly, there are editor scripts that will automatically regenerate the profile lists.

    For Unity profiles it must inherit from InputDeviceProfile and have the [UnityInputDeviceProfile] attribute:

    Code (CSharp):
    1. [Preserve, UnityInputDeviceProfile]
    2. public class MyCustomDeviceWindowsUnityProfile : InputDeviceProfile { ... }
    For Native profiles it must inherit from InputDeviceProfile and have the [NativeInputDeviceProfile] attribute:

    Code (CSharp):
    1. [Preserve, NativeInputDeviceProfile]
    2. public class MyCustomDeviceWindowsNativeProfile : InputDeviceProfile { ... }
    You should also add the [Preserve] attribute also so they don't get stripped out in IL2CPP builds.

    If you want to see the details, the editor scripts are in Editor/UnityProfileListGenerator.cs and Editor/NativeProfileListGenerator.cs

    If the editor scripts are not picking up your profiles, then it's probably not visible to the InControl assembly. Drop it in the appropriate profiles folder, or add an assembly reference to the InControl assembly definition.

    It sounds like you only made a Unity profile. I'd recommend making a Native profile too, and use Native Input in general. The mappings will most likely be quite different from the Unity profile, so it's not just a matter of copying them over.

    You're welcome to send me working profiles to include in future releases so you don't have to worry about doing anything manually to future upgrades.
     
    andrewspencer_unity likes this.
  39. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
    I reached out to the person having the issue and they said both controllers they've tried are genuine and indeed work on other games. Is there anyway you'd be able to confirm on your end again that a wireless 360 control should still work?

    Also, should I only be turning on ONE of the xinput options. That is, if I have it turned ON in the Native Settings, should I turn it OFF in standalone XInput Settings?

    Thank you!
     
  40. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    Sure, I'll test the controller again—assuming I can find it in one of my tubs of controllers. ;)

    You can just leave both XInput settings turned on. If native input is enabled, it's going to use XInput inside the native plugin and not use the other one. If you turn native input off, it'll fall back to unity input together with the managed xinput plugin.
     
    atrivedi7 likes this.
  41. andrewspencer_unity

    andrewspencer_unity

    Joined:
    Feb 19, 2019
    Posts:
    4
    @pbhogan
    Right, I didn't realise it did that automatically. All good.
     
  42. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    I found and tested the controller. It works correctly. I tested in all configurations with native input on and off, xinput on and off. Everything behaved as expected.

    This is the Xbox 360 wireless controller I have shown below and you can see the wireless adapter. The second image is as reported by DirectInput (native input on + XInput off). With XInput on it would simply show up as an "XInput Controller" as the XInput API does not identify what the underlying controller is.



     
    atrivedi7 likes this.
  43. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    92
    @pbhogan thank you so much for confirming that!
     
  44. lazylukey

    lazylukey

    Joined:
    May 26, 2017
    Posts:
    36
    @pbhogan Hi again! We recently upgraded InControl from v1.8.3 to v1.8.6. We have noticed that there is a serious GC alloc issue every frame (0.7 Kb) being generated by UnityMouseProvider::SafeGetMouseButton(). The `catch` there is catching the following exception:

    System.ArgumentException: Invalid mouse button index.
    at (wrapper managed-to-native) UnityEngine.Input.GetMouseButton(int)
    at InControl.UnityMouseProvider.SafeGetMouseButton (System.Int32 button) [0x00002] in E:\Workspace\Devour\Assets\InControl\Source\Mouse\UnityMouseProvider.cs:91
    UnityEngine.Debug:LogError (object)
    InControl.UnityMouseProvider:SafeGetMouseButton (int) (at Assets/InControl/Source/Mouse/UnityMouseProvider.cs:94)
    InControl.UnityMouseProvider:Update () (at Assets/InControl/Source/Mouse/UnityMouseProvider.cs:69)
    InControl.InputManager:UpdateInternal () (at Assets/InControl/Source/InputManager.cs:280)
    InControl.InputManager:OnLevelWasLoaded () (at Assets/InControl/Source/InputManager.cs:401)
    InControl.InControlManager:OnSceneWasLoaded (UnityEngine.SceneManagement.Scene,UnityEngine.SceneManagement.LoadSceneMode) (at Assets/InControl/Source/Components/InControlManager.cs:188)
    UnityEngine.SceneManagement.SceneManager:Internal_SceneLoaded (UnityEngine.SceneManagement.Scene,UnityEngine.SceneManagement.LoadSceneMode)

    In the Update() loop it looks like the root cause of the issue is that you are now querying button pressed for a large number of buttons from the mouse that may or may not exist. This issue does not exist in v1.8.3

    Edit: I'll also add that removing SafeGetMouseButton for indexes 7 and 8 resolves the issue on Windows 10
     
    Last edited: Sep 8, 2021
  45. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    Thanks—I became aware of the issue a few days ago. I'll have a fix out soon. In the meantime, you are correct that removing those two calls is a good fix until then.

    Edit UnityMouseProvider.cs and comment out lines 69 & 70:
    // buttonPressed[(int) Mouse.Button8] = SafeGetMouseButton( 7 );
    // buttonPressed[(int) Mouse.Button9] = SafeGetMouseButton( 8 );

    The final fix will basically be this with an additional guard and some deprecations to the enums involved.
     
  46. tintingaroo

    tintingaroo

    Joined:
    Sep 16, 2021
    Posts:
    1
    Here's something I discovered when trying to mod Hollow Knight to fix some issues players were encountering:

    At InControl > InputManager.cs > AttachDevice(), below InputManager.AssertIsSetup(), I inserted:
    Code (CSharp):
    1. if (inputDevice.isUnknown){return;}
    It prevents unknown devices from attaching, therefore player control can't be blocked due to an unknown device having focus.

    - Players won't have to disconnect wheels/pedals/HOTAS for gamepad to work
    - Series X controller players won't find they lose/gain control (Series X controller is detected as two devices, one known the other unknown)
    - Players can use an unknown gamepad with any controller emulator (not just those that employ e.g. HIDGuardian to hide their gamepad) and not lose/gain control. (Steam Input on Windows will hide the gamepad but not on Mac or Linux.)

    Only situation I'm thinking to not include this is if you handle unknown devices and make them usable.

    Hope that helps you developer folk! o/
     
    Last edited: Oct 6, 2021
  47. WildcardMoo

    WildcardMoo

    Joined:
    Aug 28, 2020
    Posts:
    19
    I just started working with InControl, and I love every aspect for it, except for one thing, that frankly baffles me.
    When rebinding controls, which also includes removing bindings from actions, I want to be able to output directly afterwards what the new bindings are. This does not seem to be possible at the moment.

    Action.RemoveBinding(At) does not remove the binding straight away, according to the tooltip to allow iteration over the binding collection. Which sounds like a really strange design choice, considering that's a basic issue with collections that can be solved easily by simply using a for loop instead of a foreach loop - I assume there's a deeper reason for this design choice that I just can't see yet.

    So instead, RemoveBinding(At) modifies a regularBindings collection (actually, only RemoveBindings does that, At does not) and sets a BoundTo property to null. All that is then applied to the actual Bindings collection at the next tick.

    My problem is now, that I want to be able to see (and output) what bindings are currently active, directly after removing one (which seems like a pretty standard thing to do). But Bindings still contains the removed binding, and regularBindings is not accessible from outside. I also can't trigger UpdateBindings manually to make sure the Bindings collection is being updated.

    The only way I see is for me to change your code so that BoundTo on the BindingSource is public. I can then ignore all Bindings that have BoundTo==null. Easy workaround, solves my problem, easily maintained, but I'm still almost certain there's an easier way and I'm missing it.
     
    Last edited: Nov 18, 2021
  48. WildcardMoo

    WildcardMoo

    Joined:
    Aug 28, 2020
    Posts:
    19
    And one more issue. I have an action that has two default bindings: A keyboard binding and a controller binding to the "left command key" (the "view" button on an xbox controller).

    This works perfectly fine. The "left command key" does trigger my action via InControl.

    However, when I query the Bindings collection, this binding does not show up. Furthermore, when I look at the DefaultBindings, I see it is not valid (IsValid = false).

    But again, it is actually taking input for the "SwitchFireMode" action.

    The controller is switched on the entire time.

    What is happening here?
     

    Attached Files:

  49. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    The reason is actually quite simple... you could be iterating over Bindings while requesting changes. It is unsafe for InControl to pull the rug out from under you and modify the collection while you might be using it, thus leaving your iterator/index potentially invalid. So, instead, InControl makes the changes later when you can't be accessing it.

    I suppose it would be possible to have a method you can call to ask InControl to commit changes with a pinky-promise that you aren't currently using the collection or holding onto any iterators/indices. But I prefer to avoid adding things that could be easily misused.

    The correct approach is to respond to the rebinding process or bindings changes by using callbacks to update UI or other state. Take a look at the BindingsMenu example in the examples folder, primarily BindingButton.cs.

    Probably the most useful if you're not responding to the binding listening process itself is to use action.OnBindingsChanged as that will fire after any changes to bindings on the action.
     
    WildcardMoo likes this.
  50. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    384
    Oops! This is a bug.

    To fix, edit Utility.cs:

    Code (CSharp):
    1.  
    2. internal static bool TargetIsStandard( InputControlType target )
    3. {
    4.     return (target >= InputControlType.LeftStickUp && target <= InputControlType.Action12) ||
    5.            (target >= InputControlType.Command && target <= InputControlType.RightCommand);
    6. }
    7.  
    I'll get this fix in the next update.
     
    WildcardMoo likes this.