Search Unity

Rewired - Advanced Input for Unity

Discussion in 'Assets and Asset Store' started by guavaman, Sep 25, 2014.

  1. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    109
    Oh my... it's even worse than I though then.
    Thanks for the valuable insight!
     
  2. YoyoMario

    YoyoMario

    Joined:
    Apr 8, 2013
    Posts:
    12
    Hello,
    I've been struggling with setting up rewired for quiet some time, is there a way you can teamviewer me for some assistance?
     
  3. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    No, sorry. I do not provide live personal instruction support.

    There is extensive documentation that is provided for you:
    http://guavaman.com/rewired/docs

    There is also a quick start:
    https://guavaman.com/projects/rewired/docs/QuickStart.html

    And a 1-hour long overview video:


    I can answer individual questions about issues.
     
  4. adrianadrian

    adrianadrian

    Joined:
    Mar 8, 2015
    Posts:
    7
    Does Rewired support the use of iphone as a controller for AppleTV / Mac?
     
  5. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    adrianadrian likes this.
  6. jason_yak

    jason_yak

    Joined:
    Aug 25, 2016
    Posts:
    269
    Hi there,

    I was just wondering if you've come across these errors before. We've recently updated to 2019.2.3 up from 2019.1.8, and same time updated Rewired to 1.1.27.3 - so I'm not sure on the cause, but when I open our project we now get these two errors:

    Error: Could not load signature of Rewired.Editor.ComponentControls.TouchInteractableEditor:GenerateInteractableAnimatorContoller due to: Could not load file or assembly 'UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>

    Error: Could not load signature of Rewired.ComponentControls.Effects.TouchInteractableTransitioner:get_transitionColorTint due to: Could not load file or assembly 'UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>

    Any ideas? should I try and reinstall? thanks.
     
  7. jason_yak

    jason_yak

    Joined:
    Aug 25, 2016
    Posts:
    269
    (^ I don't know how, but that's kind of appropriate that a sad emoji appears next to the word null haha?!)
     
    guavaman likes this.
  8. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    See the notice at the top of the documentation:
    https://guavaman.com/projects/rewired/docs/
     
  9. jason_yak

    jason_yak

    Joined:
    Aug 25, 2016
    Posts:
    269
    Thanks, we do seem to be seeing these messages more often than described though. But if they are cosmetic as you say we'll ignore them. Thanks.
     
  10. paatz04

    paatz04

    Joined:
    Aug 1, 2013
    Posts:
    35
    Setting UnityEngine.tvOS.Remote.allowExitToHome = true; has no effect for me. Is there anything else that needs to be done to get this to work ?
    Do you have some documentation on how to get the siri remote to not act like a cursor, this used to be the default behaviour out of the box before hooking up Rewired. Thanks!
     
  11. jason_yak

    jason_yak

    Joined:
    Aug 25, 2016
    Posts:
    269
    guavaman likes this.
  12. paatz04

    paatz04

    Joined:
    Aug 1, 2013
    Posts:
    35
    Oh thanks! This workaround does the trick for now.
     
  13. facundogalella

    facundogalella

    Joined:
    Mar 5, 2016
    Posts:
    47
  14. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    I don't understand your question.

    All versions of Unity give you to option to choose the input system in use in the Player settings. It must be set to "Input Manager" and not "Input System".
     
  15. facundogalella

    facundogalella

    Joined:
    Mar 5, 2016
    Posts:
    47
    My apologies, I've checking the info. I understood that the trouble was with the Input Manager of latest releases.
     
  16. Revolutionary_Concepts

    Revolutionary_Concepts

    Joined:
    Oct 30, 2016
    Posts:
    3
    Hey Guavaman, love your work. Quick question for you or anyone who's tried this - any insights on whether we can utilise tilt controls when using the PS4/Xbox Controllers with iOS13 via Rewired. Technically assuming you support access to the gyro controls which I believe ya do, and iOS see's these controllers via bluetooth, it should all just work ya?
    Thanks!
     
  17. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    As a Joystick, no. It's not going to work:
    https://guavaman.com/projects/rewired/docs/Troubleshooting.html#ios-xbox-ps4-controllers

    When using the Tilt Control Touch Control, very unlikely. If Unity pipes the DS4 gyro into UnityEngine.Input, the touch control would pick it up that way. Otherwise, no, you cannot access it through the DS4.

    It's highly unlikely Apple even exposes the DS4's gyro through their API. No other MFI controller supports gyro as far as I know and Apple's not going to add gyro control to their API just for the DS4. Apple does not provide general a HID input device API and therefore you cannot use any controllers on iOS but those they support. There's no way you will ever be able to support the DS4 gyro if they don't explicitly add support for it or add a general HID device API which is extremely unlikely to ever happen.

    Every single input API is different and every single platform is different and require completely different code paths and explicit support for features. DS4 special feature support in Rewired only works in Windows Standalone using Raw Input and OSX using Rewired's native library.
     
    Last edited: Sep 3, 2019
  18. Revolutionary_Concepts

    Revolutionary_Concepts

    Joined:
    Oct 30, 2016
    Posts:
    3
    Thanks for taking the time to give such a detailed reply. That's all we needed to know.
    Cheers!
     
  19. unity_7moAds8QlnETMw

    unity_7moAds8QlnETMw

    Joined:
    Aug 28, 2019
    Posts:
    8
    Hey @guavaman
    We're having an issue with how tvOS (Apple TV) handles controllers.
    We're preparing a game when at one point it can be operated by 2 players (P1 and P2) for a local play session.
    We're successfully connecting 2 MFI controllers (SteelSeries Nimbus which are recognised properly with hardwareTypeGuid of "3d919cfa-468e-49f4-bce9-f6c43f2e7e62") to the AppleTV, but strange things happen on connecting/disconnecting.

    The steps are as follows:
    - the Siri Remote is connected first (but we prevent the assignment from script for this one)
    - we connect the first MFI controller (let's call it C1) and it's auto-assigned properly to P1 (we use the ReInput.controllers.AutoAssignJoystick(joy) from code)
    - then we connect the second MFI controller (let's call it C2)
    - instead of assigning the C2 to P2, all other controllers gets disconnected first (Siri Remote and C1)
    - then C2 is connected (and assigned to P1 as it no longer has any connected controllers)
    - then both previously connected controllers gets reconnected (Siri Remote is not assigned by code as before and C1 ends up assigned for P2)

    Esentially, causing the controlers to switch players (the former primary C1 controller ends up assigned to P2 and the secondary C2 ends up assigned to P1). Also, all the reconnected controllers have different deviceInstanceGUID, so they're not reassigned to the previous owners/players.
    As a note, it's worth mentioning, that secondary connected controller C2 is always reconnected first (and in this way preserves as primary controller) and the first connected controller C1 always remains as secondary (except the situation, when we disconnect C2 altogheter leaving us with only C1 - then it gets reassigned to P0 properly). This behaviour preserves in a game session. If on another play we switch the order of connecting the controller the outcome is the same (the secondly connected controller always gets reconnected first later).
    Also, I don't know if it's related, but when connected, both lights on the controllers are indicating that they're connected to the first player (the first of the foriziontal lights is on).
    We're using the same autoassignment settings and code on other platforms (Android/AndroidTV nad iOS) and it works fine there (there is no disconnection/reconnection to begin with).

    We would love any kind of guidance with this, so thanks in advance. If You need any more info, just let me know. ;)

    Specification info:
    Unity v. 2018.1.6f1
    Rewired v. 1.1.26.0
    MFI Controllers SteelSeries Nimbus
     
  20. IsaacMR

    IsaacMR

    Joined:
    Apr 30, 2013
    Posts:
    2
    Hello,

    my company has purchased Rewired for Switch and I have question: What is the value of the hardwareName property for the Pro Controller (Full key) of the Switch?

    Thank you
     
  21. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    First, is Joystick Auto-Assignment enabled or disabled?

    Are you calling
    ReInput.controllers.AutoAssignJoystick(joy) to assign C2 to P2? Or are you letting this assignment happen automatically through Joystick Auto-Assignment?


    This sentence is very confusing. I need more clarification about exactly what you're doing and what you're saying Rewired is doing:

    "all other controllers gets disconnected first (Siri Remote and C1)"

    Are you saying you are not disconnecting these controllers physically but are receiving disconnection events from Rewired at the time you are attaching C2?

    If you are saying you are receiving disconnection events from controllers that are still connected to the system simply by connecting another controller then this is very likely not Rewired doing it but Unity's input system causing it underneath Rewired and it is not able to correct for it. If you look at the documentation, you will see that Unity's input system is used as the source of input on iOS and tvOS:
    https://guavaman.com/projects/rewired/docs/Overview.html#tested-platforms

    1. UnityEngine.Input.GetJoystickNames is the only way to tell what controllers are attached.
    2. UnityEngine.Input.GetJoystickNames returns an array of string names, one for each controller.
    3. It SHOULD return an array with blank entries where no controllers are attached.
    4. When a controller is re-connected, it SHOULD appear in the same slot in the array it was before if there is a way to do this on the current platform. (Not possible on all platforms.)
    4. It SHOULD NOT reorder joystick names when you attach a new controller.

    I say "SHOULD" above because there have historically been big problems and inconsistencies across platforms in the behavior of the array returned by GetJoystickNames. Platforms that have in the past reordered joystick names when reconnecting joysticks (which have since been fixed by Unity) are impossible to always make Player-Joystick assignments work correctly on disconnect/reconnect. This is because you have absolutely no way to differentiate two identical joysticks apart from the array index in GetJoystickNames. You cannot get a path/guid/identifier that will tell you which Nimbus is which when multiple are connected apart from its order in the GetJoystickNames array.

    Rewired already tries its best to correct for this with its own matching system, but it is impossible in the case of re-ordering joysticks where multiple identical joysticks are used when UnityEngine.Input is the source.

    I am not aware if joysticks get reordered by Unity on iOS/tvOS. They shouldn't. They never did in the past, but it's possible something has changed either in Unity or iOS/tvOS or both.

    Joystick.deviceInstanceGUID on UnityEngine.Input dependent platforms is created from the string name of the controller along with the index in the array returned by Input.GetJoystickNames. What you are saying indicates to me that indeed, UnityEngine.Input on iOS is now re-ordering joystick entries upon connection of a controller. Because if it weren't, the deviceInstanceGUID would not be changing. The only other possible way the GUID could change is if the string name is changing. What version of tvOS are you testing on? Do you happen to be using tvOS13 beta?

    What you are seeing is that C2 is being inserted above C1 in the array list, possibly taking its place. I would wager this is due to iOS/tvOS itself changing the order of the devices.

    This adds to my suspicion that iOS/tvOS underneath may be responsible, is inserting C2 above C1, Unity isn't able to detect that and so C2 takes the place of C1 in the GetJoystickNames array, cascading up. Rewired cannot know this is happening because both Nimbus controllers have the exact same string name.

    However there are a couple of symptoms I'm seeing that don't quite line up how I would expect it to behave in this scenario:

    1. Why is the Joystick.deviceInstanceGuid not matching? If my theory is correct, C2 should be showing up with the same deviceInstanceGuid as C1 had before because it took its place in the list. The only way this would not happen is if C2 ended up being added to the list BEFORE even the Siri Remote, in which case its index would now be 0 where it was 1 before and the GUID would be different.

    2. You should never be receiving a controller disconnect event from Rewired for the Apple Remote or C1 under any scenario if they weren't disconnected. Even if they show up in the GetJoystickNames array under a different index (something is inserted, etc), Rewired will still find them and re-associate them with the Joysticks it has already created before and knew were connected in the previous frame before the list changed. The only possible way I can see this happening is if the GetJoystickNames list is initially returning them as actually disconnected and no longer in the list, but then adding them back to the list a frame or more later. The telltale sign of this would be that all joysticks get disconnected and stay disconnected for about a second, then all the joysticks appear again, now out of order.

    Essentially, my best guess is some behavior has changed in Unity and/or iOS/tvOS causing this breakage. Based on how I know this system works and its limitations, this very well may not be a fixable problem. Rewired's UnityEngine.Input-dependent platform controller handling as been as solid as it can possibly get for years as you can see by the Android builds (uses the exact same code as the iOS build). If what I believe is happening really is happening, then there is no possible solution other than to replace UnityEngine.Input with a native library which I have done many times before on many platforms, but is not a quick or easy task, especially if you have to be supporting many versions of iOS/tvOS.

    Your answers to my above questions will help me narrow the cause down.

    Here's something you can test:
    Build Rewired/DevTools/JoystickElementIdentifier to tvOS. You will be able to see the list of joysticks returned by Unity's Input.GetJoystickNames. You will be able to see if there are blank entries and how the joysticks re-order when you connect/disconnect things. Let me know what you find on the current version of iOS/tvOS you are testing with. You will also be able to see if some of all of the joysticks disappear when you connect C2 for a second.
     
    Last edited: Sep 3, 2019
  22. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    Why do you want the string name? It's better to use the GUID to do any sort of matching, not the string name:
    https://guavaman.com/projects/rewired/docs/HowTos.html#identifying-recognized-controllers

    String names can also be found in the CSV file in the link.

    The only case where using the string name is useful for matching is iOS to handle glyphs on Xbox and DS4 controllers on iOS13.
     
    Last edited: Sep 3, 2019
    IsaacMR likes this.
  23. IsaacMR

    IsaacMR

    Joined:
    Apr 30, 2013
    Posts:
    2
    Thank you very much, I will use the GUID to identify the devices and not the name. Thanks for the support and explanation.
     
  24. danbg

    danbg

    Joined:
    May 1, 2017
    Posts:
    6
    Hello guavaman, I wonder if you could help with an issue regarding using keyboards for a terminal game running in the background on a Windows 10 machine. I need to write in an inputfield without focus.

    I managed to get the keyboard work in the background using DirectInput source and unchecking "ignore Input When App Not in Focus", with
    Code (CSharp):
    1. if (ReInput.controllers.Keyboard.GetAnyButtonDown())
    but I don't know how to get the value of the key pressed.

    I tried using multiple
    Code (CSharp):
    1. if (ReInput.controllers.Keyboard.GetKeyDown(KeyCode.A)
    inside for every KeyCode, but that doesn't seem very efficient.

    I also tried to get access to the event called with GetAnyButtonDown() but I didn't manage to get it done. Do you have any tips to make this work? (I also tried Elringus/UnityRawInput but it doesn't work as good as Rewired) Thank you very much.
     
  25. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    That is the only possible way. What you think is inefficient is exactly what I would have to do internally if I provided some kind of event-based interface for you for direct access to key events. The Controller class is not directly tied to the low-level OS API and therefore cannot trigger events off of the low-level key event (which works differently on each input source anyway.)

    FYI, this is only going to be possible on Windows with Native Keyboard Handling enabled. No other platform supports native keyboard input and you won't be able to get any events when not in focus.

    Controller.GetAnyButtonDown literally loops through all the buttons on the Controller and checks the Down state just like you want to do. If you're concerned about efficiency, just check all the keys yourself so you know which one went down without having to iterate twice.
     
  26. aong152

    aong152

    Joined:
    Feb 12, 2014
    Posts:
    2
    Hi,

    I'm interested in using this plugin for reducing latency. My current approach is to run the game with vsync off, and running the game at 3000hz+, which is wasteful since i'm implementing a fast paced puzzle game where the gamestate updates only a few times per second. The game is intended to be tickless, with all events based on milliseconds rather than frames (e.g. blocks fall every x ms, which is completely untied from framerate, giving non 1/60 values)

    In your FAQ, you report:
    Ideally i could run the game at monitor_refresh_rate and then get the timestamps of all inputs in the frame before and process them to update the game state. This saves power while also giving minimal latency.

    Does stock Rewired perform any better than UnityInput?
    * e.g. at 60fps if i use Input.GetKeyDown() in Unity3D, will i receive input a few frames sooner in Rewired.GetKeyDown()?

    The plan is to ideally ship the game on Web / Native Win10 / Mac.
    I've done some testing on input delay, with a simple black screen -> white screen on input, and a 400fps camera.
    * Win10 -> 10ms
    * WebGL -> 50ms

    Would Rewired perform any better? I'll be doing some testing tonight...


    Licensing
    I'm planning on making an open source game; how does licensing work for that? Chuck the Rewired stuff in a git submodule with no pull rights, and then people who want to develop buy a license / use a trial license to get the dev environment up then pay for a license?
     
  27. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    No. Rewired will not significantly reduce latency vs Unity's input system. Rewired is frame-based, just like Unity. It does not provide queues of multiple input values that came over the last frame with timestamps.

    All platforms except Windows Standalone use UntyEngine.Input for keyboard and mouse input and will not be any different whatsoever from UnityEngine.Input:
    https://guavaman.com/projects/rewired/docs/Overview.html#tested-platforms

    I don't have any advice for you on this. Obviously, Rewired cannot be distributed. But since it doesn't solve the problem you're trying to solve, it's probably a moot point.
     
  28. aong152

    aong152

    Joined:
    Feb 12, 2014
    Posts:
    2
    Sorry, i'm using Joystick (not keyboard/mouse) in my tests; does Rewired reduce latency for any of those modes (since i read it reads directly from HID etc)

    That table says Native for a few things; I'm assuming Native is faster(?) than "Unity"? or is Native == Unity?
     
  29. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    This is a complex question that varies per device type, per input source used. The short answer, which I already gave you above, is that Rewired is not going to have significantly less latency than Unity's input system.

    Native is not necessarily any faster than Unity's input system. The only thing that causes latency in Unity is the frame time:
    1. Unity updates values at the beginning of the frame, once, before Update or FixedUpdate run.
    2. Values you consume in your scripts are as old as the time between the beginning of the frame and when you consume it.

    Rewired may or may not provide slightly newer values than Unity. It depends on a lot of things and everything works differently based on the platform, the input source(s) being used, the input device type, and even the individual joystick type used. But there is no scenario where it will be tremendously faster.

    Windows Standalone, Raw Input, Keyboard, Mouse, Joystick:
    Raw Input on Windows delivers messages at the beginning of the frame. This is essentially the same as Unity.

    Windows Standalone, XInput (XInput compatible joysticks only) and Direct Input:
    Devices are polled on a separate thread. Rewired samples the latest value at the beginning of Update, FixedUpdate, and/or OnGUI depending on your settings as opposed to once per frame. This means the latency may be slightly less depending on whether FixedUpdate ran in the frame one or multiple times. Assuming you're consuming input in Update, the reduction in latency is simply the length of time FixedUpdate took to execute.

    Every other platform and input source works differently. I won't go into all of them here. Hopefully you get the picture.
     
  30. danbg

    danbg

    Joined:
    May 1, 2017
    Posts:
    6
    Thank you, that was very helpful
     
  31. unity_7moAds8QlnETMw

    unity_7moAds8QlnETMw

    Joined:
    Aug 28, 2019
    Posts:
    8
    Firstly, thanks @guavaman for the extensive response. Here's more info on the issue:

    Let me just paste You the script that handles assignment on TVOS for us. Originally, it was intended to only dissallow autoassignment of the Siri Remote (we assign the "AppleTV2015Remote" hardware map to the script field), but when the strange connections/disconnections happen, we added much more logging to it (also enabled it on other platforms just to check how the controllers are connected/disconnected there).

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Rewired;
    4. using Rewired.Data.Mapping;
    5. #if UNITY_TVOS
    6. using UnityEngine.Apple.TV;
    7. #endif
    8.  
    9. public class TvOSJoystickAssigner : MonoBehaviour
    10. {
    11.     [SerializeField] private HardwareJoystickMap _remoteHardwareMap;
    12.  
    13. #if UNITY_TVOS || UNITY_IOS || UNITY_ANDROID
    14.     private void Awake()
    15.     {
    16. #if UNITY_TVOS
    17.         Remote.allowExitToHome = false;
    18.         ReInput.controllers.Keyboard.enabled = false;
    19. #endif
    20.  
    21.         ReInput.configuration.autoAssignJoysticks = false;
    22.  
    23.         Debug.LogFormat("[{0}] Start processing... number of assigned controllers at start: {1}", GetType().Name, ReInput.controllers.joystickCount);
    24.         foreach (var joy in ReInput.controllers.Joysticks)
    25.         {
    26.             Debug.LogFormat("[{0}] Unassigning joystick from all players: {1}", GetType().Name, GetJoyInfo(joy));
    27.             ReInput.controllers.RemoveJoystickFromAllPlayers(joy, true);
    28.  
    29.             AssignController(joy);
    30.         }
    31.  
    32.         ReInput.ControllerConnectedEvent += OnControllerConnected;
    33.         ReInput.ControllerPreDisconnectEvent += OnControllerDisconnecting;
    34.         ReInput.ControllerDisconnectedEvent += OnControllerDisconnected;
    35.     }
    36.  
    37.     private void OnDestroy()
    38.     {
    39.         ReInput.ControllerConnectedEvent -= OnControllerConnected;
    40.         ReInput.ControllerPreDisconnectEvent -= OnControllerDisconnecting;
    41.         ReInput.ControllerDisconnectedEvent -= OnControllerDisconnected;
    42.     }
    43.  
    44.     private void OnControllerConnected(ControllerStatusChangedEventArgs args)
    45.     {
    46.         if (args.controllerType != ControllerType.Joystick)
    47.         {
    48.             return;
    49.         }
    50.  
    51.         var joy = ReInput.controllers.GetJoystick(args.controllerId);
    52.         if(joy == null)
    53.         {
    54.             Debug.LogErrorFormat("[{0}] Couldn't find connected controller with id {1}!", GetType().Name, args.controllerId);
    55.             return;
    56.         }
    57.      
    58.         Debug.LogFormat("[{0}] Connected new controller: {1}", GetType().Name, GetJoyInfo(joy));
    59.         AssignController(joy);
    60.         Debug.Log(GetAssignmentInfo());
    61.     }
    62.  
    63.     private void OnControllerDisconnecting(ControllerStatusChangedEventArgs args)
    64.     {
    65.         if(args.controllerType != ControllerType.Joystick)
    66.         {
    67.             return;
    68.         }
    69.  
    70.         var joy = ReInput.controllers.GetJoystick(args.controllerId);
    71.         if (joy == null)
    72.         {
    73.             Debug.LogErrorFormat("[{0}] Couldn't find disconnecting controller with id {1}!", GetType().Name, args.controllerId);
    74.             return;
    75.         }
    76.  
    77.         Debug.LogFormat("[{0}] Disconnecting controller: {1}", GetType().Name, GetJoyInfo(joy));
    78.         Debug.Log(GetAssignmentInfo());
    79.     }
    80.  
    81.     private void OnControllerDisconnected(ControllerStatusChangedEventArgs args)
    82.     {
    83.         if (args.controllerType != ControllerType.Joystick)
    84.         {
    85.             return;
    86.         }
    87.  
    88.         var joy = ReInput.controllers.GetJoystick(args.controllerId);
    89.         if (joy == null)
    90.         {
    91.             Debug.LogErrorFormat("[{0}] Couldn't find disconnected controller with id {1}!", GetType().Name, args.controllerId);
    92.             return;
    93.         }
    94.  
    95.         Debug.LogFormat("[{0}] Controller disconnected: {1}", GetType().Name, GetJoyInfo(joy));
    96.         Debug.Log(GetAssignmentInfo());
    97.     }
    98.  
    99.     private void AssignController(Joystick joy)
    100.     {
    101.         Debug.LogFormat("[{0}] Processing joystick assign: {1}", GetType().Name, GetJoyInfo(joy));
    102.  
    103.         if (joy.hardwareTypeGuid == _remoteHardwareMap.Guid)
    104.         {
    105.             Debug.LogFormat("[{0}] Recognised the joy \"{1}\" as a restricted type and it was not assigned!", GetType().Name, joy.name);
    106.             return;
    107.         }
    108.  
    109.         Debug.LogFormat("[{0}] Joy \"{1}\" is not a restricted type - autoassigning!", GetType().Name, joy.name);
    110.         ReInput.controllers.AutoAssignJoystick(joy);
    111.     }
    112.  
    113.     private string GetAssignmentInfo()
    114.     {
    115.         var sb = new System.Text.StringBuilder();
    116.         sb.AppendFormat("[{0}] Joystick current assignment info:", GetType().Name);
    117.         sb.AppendLine();
    118.  
    119.         foreach (var player in ReInput.players.Players)
    120.         {
    121.             sb.AppendFormat("Player {0} ({1} assigned joysticks){2}", player.id, player.controllers.joystickCount, player.controllers.joystickCount > 0 ? ":" : ".");
    122.             sb.AppendLine();
    123.             foreach (var joy in player.controllers.Joysticks)
    124.             {
    125.                 sb.AppendFormat("- {0}", GetJoyInfo(joy));
    126.                 sb.AppendLine();
    127.             }
    128.         }
    129.         return sb.ToString();
    130.     }
    131.  
    132.     private string GetJoyInfo(Joystick joy)
    133.     {
    134.         return string.Format("name = \"{0}\", id = \"{1}\", hid = \"{2}\", sId = \"{3}\", uId = \"{4}\", hGUID = \"{5}\", dGUID = \"{6}\"", joy.name, joy.id, joy.hardwareIdentifier, joy.systemId, joy.unityId, joy.hardwareTypeGuid, joy.deviceInstanceGuid);
    135.     }
    136. #endif
    137. }
    138.  
    Esentially, yes, the controllers ARE disconnecting from Rewired without beign physically disconnected from the device. We checked a couple of scenarios using the Rewired/DevTools/JoystickElementIdentifier scene You've mentioned and the new controller (C2 in our example) DID change position to before Siri Remote (previously at position 0) and C1 (previously at position 1).
    We checked for both iOS and tvOS and we came to a conclusion, that the joystick handling looks exactly the same on those platform when no Siri Remote is in play (only 2 MFI controllers):
    - first controller gets connected C1 and gets assigned to P1
    - second controller gets connected C2 and gets assigned to P2
    - when we physically disconnect the C1 controller, it gets disconnected from P1, at the same time the C2 gets also disconnected and is reassigned to P1 (it's now at position 0 in the Unity.GetJoystickNames list)

    This last behaviour is probably to do with something the iOS/tvOS is doing to prevent empty spaces between the joys. When we disconnect the first controller, then the second controller takes it's place on Unity list. They also have a slightly different joystick names ex. "[extended,wireless] joystick 1 by Nimbus", that's probably why Rewired generates different deviceInstaceGUID for them?

    In this scenario iOS and tvOS works exactly the same, but when You add Siri Remote to the equation, it get's bad. Esentially, the remote ALWAYS is second in the joystick list, with the exception of it beign the only connected device (then is at pos 0).
    So it looked like this for example:
    upload_2019-9-6_12-42-1.png

    Ok, so if we know that's the Unity's Input.GetJoystickNames that's at fault here and Rewired simply not beign able to recognise the controllers properly, can You write to Unity on ours behalf and ask for a solution? You'd know better on how to descibe the issue at hand here and the behaviour You're expecting from GetJoystickNames.
    Also, do You need more info from us on the topic? A whole written down scenario and how the list changes during it or something?
    Just let me know. ;)
     
    Last edited: Sep 6, 2019
  32. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    When you unplug C1, does C2 still retain the correct name "[extended,wireless] joystick 2 by Nimbus" even though it is now in slot 0? If it does, then this can be handled. If this is changing because you unplugged C1, then that's a huge problem and there's no way I can possibly fix it. In that scenario, according to all the information I have available to me, you actually unplugged C2, not C1. This would explain what you're describing too. The C2 is not being disconnected and reassigned to P1. The identity of C2 is changing -- it became C1 as far as Rewired can tell -- so P1 is still holding the same Controller object whose physical source changed from C1 to C2 unbeknownst to it.

    It's been a long time since I worked with this platform so I'm going to have to go back and retest everything to do this.

    Edit: Looking through my code, this should all be working already, provided the "Joystick #" of the attached joysticks doesn't change when removing one beneath them. These things are already accounted for, including shifting indices. The full Unity name is used to identify the controller, which includes the Joy # which will prevent any cross ups assuming Unity doesn't change this Joy # embedded in the name when you unplug something. I'm going to have to get two more identical MFI controllers and do my own testing to find out exactly what is happening.

    There should never be a scenario where these controllers get disconnected and then reconnected. The only way this could happen is if they all disappeared from the GetJoystickNames list for a time and then reappeared. Did this happen ever?
     
    Last edited: Sep 8, 2019
  33. paatz04

    paatz04

    Joined:
    Aug 1, 2013
    Posts:
    35
    Getting 3 errors when starting up Unity 2019.2.3 - they don't seem to impact our game, but just wondering if there is a fix for this ?

    Error: Could not load signature of Rewired.ComponentControls.TouchJoystick:fzDacZbWZIuVvurOiSWEcMhUQvG due to: Could not load file or assembly 'UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type:<unknown type> member:(null) signature:<none>
     
  34. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    392
    It's a known issue but harmless:

    https://guavaman.com/projects/rewired/docs/Documentation.html

    https://guavaman.com/projects/rewired/docs/KnownIssues.html#assembly-errors-2019-2
     
    paatz04 and guavaman like this.
  35. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    @flashframe is right and it cannot be fixed by me because it's Unity's bug.
     
    paatz04 likes this.
  36. Morgrhim

    Morgrhim

    Joined:
    Jun 19, 2015
    Posts:
    7
    So, I'm working on a self contained Input Manager using Rewired and event-based inputs. In my mind, and for my game, it makes sense that the input system shouldn't care about what consumes the input, the consumers should be observing the input system.

    I'm having an odd.. not issue per se, but I think I'm not understanding something underlying here.

    If I have the following:

    Code (CSharp):
    1. public Action<InputActionEventData> OnHorizontalInput;
    2.  
    3. public void Init()
    4. {
    5.     // Init player stuff..
    6.  
    7.     player.AddInputEventDelegate(OnHorizontalInput, UpdateLoopType.Update, InputActionEvent.AxisActive, "Move Horizontal");
    8. }
    I get an error that an object does not exist, the error says it is my code, and gives me some gibberish call with a line 0, which is about the most unhelpful stack trace ever:



    Now, if I add an intermediate method:

    Code (CSharp):
    1. private void OnHorizontal(InputActionEventData obj)
    2. {
    3.     OnHorizontalInput?.Invoke(obj.GetAxis());
    4. }
    (The above also involves switch the Action to Action<float>)

    Everything works fine, no errors. No other changes to the code were made, just where the input was initally routed.

    So why is it that I can use a helper method, but not the delegate directly? It's not a huge deal, just curious.
     
  37. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    This call is made by the Rewired_Core.dll when it executes the event. The "gibberish" is Rewired's obfuscation, renaming internal methods which are of no consequence here anyway. It has no bearing because the error is not in that method, it's in the delegate it's trying to invoke -- the Player Input Event callback.

    I will change the method to log the Exception.InnerException instead if there is one.

    When it invoked the delegate (OnHorizontalInput), the delegate threw a null reference exception.

    As the error says, the exception is happening is your code in the callback. A null reference exception is being thrown in the code inside OnHorizontalInput. Put a try/catch statement inside OnHorizontalInput and see what it catches.

    Rewired can most definitely call direct delegates without you wrapping it in an intermediate method. I've never seen anyone do this before.
     
    Last edited: Sep 9, 2019
  38. unity_7moAds8QlnETMw

    unity_7moAds8QlnETMw

    Joined:
    Aug 28, 2019
    Posts:
    8
    Hey @guavaman
    We've prepared 2 test scenarios for You to analyze, so that You'll have a clear view on what's happening.
    I've wrote a script that puts the Input.GetJoystickNames info on the screen and logs it into the console each time that the values in the list changes. Also, all events from Rewired are logged as well (Connect, PreDisconnet and Disconnect) + after every event a full assignment info is printed to the log as well (which players has which controllers). I've prepared a sample scene with only the UI label to hold the onscreen Unity joystick info, Rewired Input Manager and the formentioned script.

    Here's the code for the script:
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using System.Text;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6. using Rewired;
    7.  
    8. public class JoystickTest : MonoBehaviour
    9. {
    10.     [SerializeField] private Text _outputText;
    11.  
    12.     private List<string> _previousNames;
    13.  
    14.     private void Start()
    15.     {
    16.         Debug.LogFormat("[{0}] Start processing...", GetType().Name);
    17.  
    18.         var joyInfo = GetUnityJoystickInfo();
    19.         _previousNames = Input.GetJoystickNames().ToList();
    20.         _outputText.text = joyInfo;
    21.         Debug.Log(joyInfo);
    22.  
    23.         Debug.Log(GetAssignmentInfo());
    24.  
    25.         ReInput.ControllerConnectedEvent += OnControllerConnected;
    26.         ReInput.ControllerPreDisconnectEvent += OnControllerDisconnecting;
    27.         ReInput.ControllerDisconnectedEvent += OnControllerDisconnected;
    28.     }
    29.  
    30.     private void OnDestroy()
    31.     {
    32.         ReInput.ControllerConnectedEvent -= OnControllerConnected;
    33.         ReInput.ControllerPreDisconnectEvent -= OnControllerDisconnecting;
    34.         ReInput.ControllerDisconnectedEvent -= OnControllerDisconnected;
    35.     }
    36.  
    37.     private void Update()
    38.     {
    39.         var names = Input.GetJoystickNames();
    40.         if(!names.SequenceEqual(_previousNames))
    41.         {
    42.             Debug.LogFormat("[{0}] Unity joystick list changed!", GetType().Name);
    43.             var joyInfo = GetUnityJoystickInfo();
    44.             _previousNames = names.ToList();
    45.             _outputText.text = joyInfo;
    46.             Debug.Log(joyInfo);
    47.         }
    48.     }
    49.  
    50.     private void OnControllerConnected(ControllerStatusChangedEventArgs args)
    51.     {
    52.         if (args.controllerType != ControllerType.Joystick)
    53.         {
    54.             return;
    55.         }
    56.  
    57.         Debug.LogFormat("[{0}] Connected new controller with id {1} (\"{2}\").", GetType().Name, args.controllerId, args.name);
    58.         Debug.Log(GetAssignmentInfo());
    59.     }
    60.  
    61.     private void OnControllerDisconnecting(ControllerStatusChangedEventArgs args)
    62.     {
    63.         if (args.controllerType != ControllerType.Joystick)
    64.         {
    65.             return;
    66.         }
    67.  
    68.         Debug.LogFormat("[{0}] Disconnecting controller with id {1} (\"{2}\").", GetType().Name, args.controllerId, args.name);
    69.         Debug.Log(GetAssignmentInfo());
    70.     }
    71.  
    72.     private void OnControllerDisconnected(ControllerStatusChangedEventArgs args)
    73.     {
    74.         if (args.controllerType != ControllerType.Joystick)
    75.         {
    76.             return;
    77.         }
    78.  
    79.         Debug.LogFormat("[{0}] Disconnected controller with id {1} (\"{2}\").", GetType().Name, args.controllerId, args.name);
    80.         Debug.Log(GetAssignmentInfo());
    81.     }
    82.  
    83.     private string GetAssignmentInfo()
    84.     {
    85.         var sb = new StringBuilder();
    86.         sb.AppendFormat("[{0}] Joystick current assignment info:", GetType().Name);
    87.         sb.AppendLine();
    88.  
    89.         foreach (var player in ReInput.players.Players)
    90.         {
    91.             sb.AppendFormat("Player {0} has {1} assigned joysticks{2}", player.id, player.controllers.joystickCount, player.controllers.joystickCount > 0 ? ":" : ".");
    92.             sb.AppendLine();
    93.             foreach (var joy in player.controllers.Joysticks)
    94.             {
    95.                 sb.AppendFormat("- {0}", GetJoyInfo(joy));
    96.                 sb.AppendLine();
    97.             }
    98.         }
    99.         return sb.ToString();
    100.     }
    101.  
    102.     private string GetJoyInfo(Joystick joy)
    103.     {
    104.         return string.Format("name = \"{0}\", id = \"{1}\", hid = \"{2}\", sId = \"{3}\", uId = \"{4}\", hGUID = \"{5}\", dGUID = \"{6}\"", joy.name, joy.id, joy.hardwareIdentifier, joy.systemId, joy.unityId, joy.hardwareTypeGuid, joy.deviceInstanceGuid);
    105.     }
    106.  
    107.     private string GetUnityJoystickInfo()
    108.     {
    109.         var names = Input.GetJoystickNames();
    110.  
    111.         var sb = new StringBuilder();
    112.         sb.AppendFormat("[{0}] {1} Unity joysticks available{2}", GetType().Name, names.Length, names.Length > 0 ? ":" : ".");
    113.         sb.AppendLine();
    114.  
    115.         for(var i = 0; i < names.Length; i++)
    116.         {
    117.             sb.AppendFormat("- [{0}] \"{1}\"", i, names[i]);
    118.             sb.AppendLine();
    119.         }
    120.         return sb.ToString();
    121.     }
    122. }
    We've conducted 2 test scenarios: one with Siri Remote connected at start and one without Siri remote ever connected. The joysticks are auto-assigned from start and the settings look like this:
    upload_2019-9-9_16-39-54.png

    We have 2 players, both included in the auto-assignment. We don't restrict any controller from assignment, so Remote is also assigned to the players. The screenshots from the zips show the Unity joystick list situation after each step scenario (they're numbered from 1-7).

    SCENARIO 1 (with Siri Remote connected at start):
    1. No MFI controller connected (only Siri Remote).
    2. Connect first MFI controller (C1).
    3. Connect second MFI controller (C2).
    4. Disconnect C1.
    5. Reconnect C1.
    6. Disconnect C2.
    7. Reconnect C2.

    The screenshots for this scenario and the log from the device can be found here: https://we.tl/t-NeH0wOZ9Vq

    SCENARIO 2 (without Siri Remote ever connected):
    1. No MFI controller connected.
    2. Connect first MFI controller (C1).
    3. Connect second MFI controller (C2).
    4. Disconnect C1.
    5. Reconnect C1.
    6. Disconnect C2.
    7. Reconnect C2.

    The screenshots for this scenario and the log from the device can be found here: https://we.tl/t-zv8evnSWb4

    From what I can tell, Unity does change both controller name and position in the first scenario when attaching the second MFI controller (that's where the Rewired disconnections kick in).
    As for the second scenario (without Siri) when You disconnect C1 at step 4, C2 takes it place in the list (exact same name and position), so there is no reassignment, but C2 is now generating input for the first player - I don't know if that's the desired behaviour.

    BONUS:
    You'll see that when Siri Remote is connected at start (scenario 1) it always tries to retain position 0 on Unity joystick list (when no other controllers are connected or just C1 is connected) or position 1 on Unity joystick list when C2 is connected. On the other hand, if You connect the remote AFTER You've connected both MFI controllers, it's added properly as the last least entry in the list and the whole thing behave similarly to scenario 2 (with the exception of Siri Remote adding itself at the bottom of the Unity joystick list after connection).

    Hope that'll teel You all the info You need. Thanks for checking it out.
     
  39. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    Thanks. The screenshots are helpful and verify my fears. Unity is both collapsing the array list and changing the encoded "Joystick #" to match. This makes this problem impossible for Rewired to fix. When C1 is unplugged, C2 literally becomes C1, so P1 starts using C2. Rewired cannot know the difference.

    I don't know where Unity gets its "Joystick #". It just matches the array index which makes it completely pointless information. I wonder if this is a recent bug. It would seem to me that the behavior on this platform SHOULD be:
    • Array is not collapsed when controllers are added/removed
    • Input Manager index matches array index
    • Joystick # reports the GameController frame work joystick number or player index.
    This is clearly not what's happening.

    Looking at the GameController API, Unity is probably simply copying the GCController array directly to the Input Manager array:

    https://developer.apple.com/documentation/gamecontroller/gccontroller/1458871-controllers

    Apple is probably collapsing the array themselves.

    Looking at the API, I could fix this with a custom native library IF the following is true:
    • When the CGController.controllers array is changed after removing or adding a controller, the GCController objects returned in the array are the same instance as before when one is disconnected so they can be compared to previously known instances.
    • If new instances are created each time, there is no possible way I can detect which controllers stayed connected and which controllers were disconnected.
    • One may be able to use the GCControllerPlayerIndex to maintain some sort of tracking if the instances are not reused.
    It looks like Unity is trying to maintain some kind of connection order history but failing to do it correctly. That's probably why they encoded the "Joystick #" in the first place. I don't know if this was broken all along or if it's a new bug they introduced in Unity.

    It would be worth testing the latest version of Unity 2018 to see if they fixed this. (I see you are on Unity v. 2018.1.6f1 which is quite old.) I would definitely report this issue to Unity if it still persists.
     
    Last edited: Sep 9, 2019
  40. PlayriseDigital

    PlayriseDigital

    Joined:
    Jan 20, 2015
    Posts:
    16
    We have actually moved up to 2018.4.8f1 (LTS) and the problem persists. :( Thanks for you support on this matter.
     
  41. mmvlad

    mmvlad

    Joined:
    Dec 31, 2014
    Posts:
    85
    Hello @guavaman
    I am trying to check if touch is over UI element but for some reason, it is not working. Do I need some special setup? I am using RewiredStandaloneInputModule.

    Code (CSharp):
    1. for (int i = 0; i < Input.touchCount; ++i)
    2.                 {
    3.                     var touch = Input.GetTouch(i);
    4.                     if (touch.phase == TouchPhase.Began && EventSystem.current.IsPointerOverGameObject(touch.fingerId))
    5.                     {
    6.                         Debug.Log("Over ui touch");
    7.                         return true;
    8.                     }
    9.                 }
     
  42. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    I've spent the last hour and a half testing everything over again and it works.
    1. What version of Rewired are you using?
    2. What platform are you building to?
    3. Are you using Unity Remote in the editor?
    4. Did you disable "Allow Touch Input" in the inspector or a script?
    IsPointerOverGameObject is a legacy method defined by Unity's PointerInputModule. It cannot take into account Rewired's multiple pointer support. It returns true if any pointer with that type id is over a GameObject.
     
  43. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    Then definitely file a bug report to Unity. The only way I can fix this is to make a native library for iOS/tvOS to remove UnityEngine.Input dependency. It's going to be quite a while before I can look into this.
     
  44. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    Rewired 1.1.28.0 is available for registered users to download now. To register for early access to updates, please contact me here. It will be released on the Unity Asset Store as soon as they approve the update.

    Please see Updating Rewired before updating:
    https://guavaman.com/projects/rewired/docs/Updating.html

    Release Notes:

    1.1.28.0:

    Changes:
    - Added Stadia platform plugin support.
    - Changed editor compilation system to work with "Recompile After Finished Playing" setting in Unity editor preferences.
    - iOS/tvOS: Controller.deviceInstanceGuid changed to more accurately identify controllers.
    - Changed callback/event exception logging to log the Exception.InnerException.

    API Changes:
    - ReInput.ControllerHelper.GetJoysticks now returns an empty array when no Joysticks are found instead of null.
    - ReInput.ControllerHelper.GetJoystickNames now returns an empty array when no Joysticks are found instead of null.
    - ReInput.ControllerHelper.GetCustomControllers now returns an empty array when no Custom Controllers are found instead of null.
    - ReInput.ControllerHelper.GetCustomControllerNames now returns an empty array when no Custom Controllers are found instead of null.

    Controller Definitions:
    - Added Stadia Gamepad.

    Bug Fixes:
    - Fixed Null Reference Exception in RewiredPointerInputModule.GetPointerData when called with create == false and no pointer data has been created.
    - Fixed Null Reference Exception in RewiredPointerInputModule when removing a mouse input source from a UI event callback.
     
    Last edited: Sep 11, 2019
    Bartolomeus755 likes this.
  45. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
  46. Seith

    Seith

    Joined:
    Nov 3, 2012
    Posts:
    715
    Hello @guavaman, I'm trying to simply change the action assigned to a gamepad button at run-time (remapping via code) and I can't seem to find a way to do that. I use the default template gamepad and for example I would like to change the "Fire" action from button A to button B.

    How would I go about doing that please?
     
  47. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    There are many examples included with Rewired that show you how to do all of this.

    https://guavaman.com/projects/rewired/docs/Examples.html#simple-control-remapping
    https://guavaman.com/projects/rewired/docs/Examples.html#simple-combined-keyboard-mouse-remapping
    https://guavaman.com/projects/rewired/docs/Examples.html#control-remapping-1
    https://guavaman.com/projects/rewired/docs/ControlMapper.html
    https://guavaman.com/projects/rewired/docs/InputMapper.html
     
    Seith likes this.
  48. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    392
    Hey having a small issue on iOS when using a bluetooth controller.

    1. Controller stick is held down. Rewired correctly reports axis value as 1.
    2. While still holding the controller stick, the application is exited using the home button (on device).
    3. Let go of controller stick.
    4. Resume application on device. Rewired continues to report axis value as 1 even though the axis is no longer held, presumably because it never received information that the stick was let go. This is fixed once the stick is moved again.

    I have tried disabling "Ignore Input When App Not In Focus" but didn't help.

    I know that controllers on iOS are not officially supported, so I just wondered if there is anything I can do to force Rewired to refresh that axis value when the application is resumed. Perhaps in Unity's OnApplicationPause event?

    Edit: Would disabling/reenabling the controller maps work? I'll try it.
     
  49. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,800
    Controllers definitely are supported on iOS.

    Nope. Rewired is 100% dependent on UnityEngine.Input for values on iOS. https://guavaman.com/projects/rewired/docs/Overview.html#tested-platforms

    UnityEngine.Input is polled every single frame for the values of all buttons and axes for all connected joysticks. If a value is getting stuck in Rewired, it's only because it's getting stuck in UnityEngine.Input. Rewired is never going to zero a value out that the underlying input system telling it is non-zero. Add this to the growing list of reasons why I have to make a native library on iOS.
     
  50. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    392
    Thanks, I presumed it was probably a Unity Input problem. I'll file a bug report and just live with it for now. It's an edge case.