Who uses the new input package ? ( I use the legacy Input class )

Hi guyz !!!

I just tested the new input package ( i got mouse keyb and gamepad )…
It took me no more than 2 hours to unsinstall it and rollback to the old input system !

Honestly ( this is my very own opinion ) i think this package is a shitty input obfuscator just unable to deal with inputs of a std gamepad.
It seems to be able to handle everything in the world except the HMI connected on your PC !
And above beeing an input messer making things non-understandable, this awfull thing is not even written in a fast and efficient C++ lib !!! It’s c# classes editable in U3D !!!

Since now 15 years, U3D proved it was a serious and great tool << for making things >>. I sincerely this input package will be the only exception !

And you ? what do you think about it ?
And what do you finally use ?

Personnally i go on using the good-old-and-simple legacy input system :wink:

Happy unitying !

1 Like

I use the old input system. I don’t like the documentation and the implementation of the new input system. But if I were to make a mobile game that had a mostly static display and I wanted to keep polling and energy usage to a minimum then I may be tempted to use the new input system.

The new documentation format that Unity has moved to seems like it was written by a machine for machines.

2 Likes

honestly the way old input worked was a nightmare when you started adding custom assets that liked to mess all the configuration in that ancient tree menu.

but if the current input can’t work with your devices I guess you are stuck with the old one

2 Likes

Hi @pitibonom
I am curious to hear more details on your experience. Which gamepad did you try to use with the InputSystem?
Which parts did you consider especially hard to understand?

1 Like

Did you try the Samples in the package? Those are very instructive!

For better or worse, the Input System has no less than four ways to hook into input events: SendMessage, BroadcastMessage, Unity Events and C# events with C# class generation. Plus the manual coding style - if you attempted to do that I’m sorry that you took the hardest route of them all.

SendMessage or C# events are the way to go. The former is dead easy. You use one of the predefined input mapping (ie WASD controls) and everything works out of the box. You just add the OnMove, OnJump, etc callbacks of the same name to any script on the same object has the PlayerInput component on it and off you go. This works with mouse + keyboard, any gamepad or joystick, pens and even touch.

If you need a little more control over input C# events provide you that control by allowing you to also respond to started, performed and cancelled events. With that, you can implement your own timed “hold button” and things like that. Plus the generated C# interface provide the added benefit that you will never ever have an input event that is either not implemented, or stops working because you refactor-renamed it.

The main con about the new Input System is that it DOES require more effort to understand it, and the many ways to do the same thing WILL be confusing initially. But after that, any time you want to add a new action and hook it up with various device inputs, it’s just going to be a breeze compared to legacy Input.

So rather than complain after the fact and spend two hours rolling everything back, why didn’t you come here while you were struggling? We could have pointed you in the right direction. :wink:

Also, whether C# or C++ doesn’t really matter performance-wise. How much time do you think is spent in receiving an input and passing it along? Plus you can write high-performing code in C# as well, even without Burst.

1 Like

@CodeSmile and @MerklRita :slight_smile:

Of course i tried the samples ! who do you take me for ??? :stuck_out_tongue:
ahahahah I’m sorry if i were too provocative but please would you allow me some recent history ?

… About the reason why i choosed U3D instead of others, 15 years ago…
After installing U3D for a try and running the ‘Island demo’, it took me 1 day to recover from the shock. This was so beautifull, so fast, so performing so easy !!! :open_mouth:

THIS is the trojan horse of U3D: make amazing things easily accessible to bumb ppl like me.
Oh i confess i tried load of other sexy ladies but i always came bact to unity :wink:

Of course when you dig under the varnish, nothing is simple but the dive is progressive and pretty bearable for the old ( and rumbly ) man i’m. And step by step ( just like as i do with blender ) i learn things for taming the beast: Unity3D.

But here come shitty ‘customers’ ( i quote the word as my apps are all free :stuck_out_tongue: ) who say: << what your shitty app that don’t handle gamepad HMI ??? >>… Okay easy ! I know U3D developped an advanced Input package… ahahah that will be too easy !
And here comes the pain :open_mouth:
I found something roughly integrated, handled with c# ( eg:no perf ) with assets here and there, with nothing about it in project settings and with the << OK-I create a key binding but what are all those choices for my SIMPLE key input ? >>

I’m sorry to say that the ‘inspector’ for input is out of friendly criterias. What should i choose for detecting a keydown on the “G” key ? It is all but obvious and this is what made me remove the new input system.
Now i handle my joypad with the good’ol’ input system and it works like a charm :smiley:

Sincerely, i’m sorry if i shocked or bothered your mind. I have to say ( and it’s not for my defense but just to warn you of my sometimes stupid expectations ) that i’m an old dev who worked for ages on aeronautics HMI. Those ones MUST be intuitively understood by pilots ( as pilots have no time to loose on interpreting things when in an emergency situation ) and i often consider things from this point of view, wich is almost always out of topic.
So… I’m sorry i shaked you with my stupid words… :slight_smile:

Be sure i’l have a peek at this new input system when i have time to learn !

@MerklRita : I didn’t feel things were hard to understand :wink: I just had no time for learning things and digging in a new ‘better’ way of handling inputs. On and the gamepad… errrr It’s not mine ( i have none and sincerely i don’t know how ppl can play a game with this :stuck_out_tongue: ) but it is… a Saitek ( probably chinese ) pad…

@CodeSmile my whole app is based on a messenging system and it is just awesome :smiley: and fast !!!
Even if you say that c# in unity is the same as c++ compiled-and-optimized libs, i’m not sure you’re right. Did you try to handle LOD with a C# script ( pretty easy to white ) on a per-object-manner ?
I did.
And be sure the perf at using U3D LODs handlings is more than 20x faster :wink: ( this is just one example :stuck_out_tongue: )

Thanks a lot all for your answers and… Happy unitying ! :smiley:

still using old, its just so much easier to setup (well no need setup at all).
but then again, i mostly use just basic WASD+mouse features from code directly.

i would use new input system:

  • if its ready to use (no need to define any standard stuff when doing quick tests, without installing extra package or switching input system manually)
  • if its not slower (used to be bad for performance, several frames delayed… maybe it has been improved since early days?)
  • if the UI would be easier to use, its not intuitive (i’ve seen people using g0dot input system, seemed easier to setup? no need to click tens of different things)
  • if using it from code is simple and short
1 Like

So you complained about it, but then say “oh I didn’t have the time to learn it properly anyway”? What a complete waste of time post then.

So some rando third party controller from a company that hasn’t made gamepads for nearly a decade now? Not surprising it wasn’t picked up. That’s generally how it’s always been with crap knock off controllers.

Also no one calls it ‘U3D’ any\more. It’s just Unity.

New Input System for a while now comes with a default WASD Fire Jump etc preset together with a secondary UI mapping for UI navigation. And this mapping works for keyboard+mouse, gamepads, joysticks, pens and touch input, with the usual device specific considerations of course (ie mouse look is delta movement, gamepad look is absolute direction).

Never experienced this. Either that used to be a bug (several frames of delay for input? come on!?!), or people have been using it totally incorrectly no thanks to the lack of documentation. It’s still not one of the most well-documented packages, leaving so many questions unanswered.

I think it’s not the UI but the concepts that are confusing. You now have maps and actions and devices and input values and what not. But once you get that, it’s easy to add a new action that maps well to all supported devices. Plus that kind of work is so rarely needed, I mean how often do you change how a given button or axis is set up?

Uhm … you mean like this?

void OnMove(InputValue v)
{
    moveDir = v.Read<Vector2>();
}

That’s what it reads like if you use PlayerInput and SendMessage (details may be incorrect, I pulled this code from memory). However, as is often the case, tutorial authors tend to work with the worst kind of setting up input system, like holding fields for each action and acquiring it in Awake by string and then assigning a delegate to the performed event. :roll_eyes:

1 Like

@pitibonom I understand it feels like a lot of effort to switch. It’s not only that you are used to the “good old way” of using input handling in your projects, it is also about the effort it takes to learn how to use the InputSystem package in general. The learning curve is higher, especially when it comes to simple input like a key down event (like you mentioned).
This is valuable feedback, and will be considered.
I hope you will get to try the InputSystem package in one of your future projects, maybe the project-wide actions (a pre-made action asset) will help you to get you started more easily.
I am curious to hear your feedback!

I just had to swtich because of the issues the old system was giving me on a game that supports kb, gamepad and steeringwheels. If it wasn´t for the steering there would be no need to switch.

Do I find the new system a conptraption or and endless rabithole? kinda. YET. I present you a way to switch smoothly

Build a singleton script that receives all the input. You can process all the inputs in there, and from other scripts just read theese input values.

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using System.Linq;

public class NewInputSystem_Manager : MonoBehaviour
{
    public static NewInputSystem_Manager Instance;

 

 
    public PlayerInput pInput;
    public InputActionAsset actionAsset;

    [Space]
    [Space]
    public InputActionReference action_accel;
    public InputActionReference action_brake;
    public InputActionReference action_clutch;
    public InputActionReference action_steer;
    public InputActionReference action_steerStrong;
    public InputActionReference action_handbrake;

    public InputActionReference action_gearUp;
    public InputActionReference action_gearDown;

    public InputActionReference action_H_Gear_1;
    public InputActionReference action_H_Gear_2;
    public InputActionReference action_H_Gear_3;
    public InputActionReference action_H_Gear_4;
    public InputActionReference action_H_Gear_5;
    public InputActionReference action_H_Gear_6;
    public InputActionReference action_H_Gear_R;

    public InputActionReference action_changeCam;
    public InputActionReference action_CarReset;
    public InputActionReference action_Pause;
    
    public InputActionReference action_LightsOn;
    public InputActionReference action_StartEngine;
    public InputActionReference action_DebugInfo;

    public float Input_Accel;
    public float Input_Brake;
    public float Input_Clutch;
    public float Input_Steer;
    public float Input_SteerStrong ;
    public float Input_Handbrake;

    public bool Input_GearUp;
    public bool Input_GearDown;

    public bool Input_H_Gear_1;
    public bool Input_H_Gear_2;
    public bool Input_H_Gear_3;
    public bool Input_H_Gear_4;
    public bool Input_H_Gear_5;
    public bool Input_H_Gear_6;
    public bool Input_H_Gear_R;

    public bool Input_changeCam;
    public bool Input_CarReset;
    public bool Input_Pause;

    public bool Input_LightsOn;
    public bool Input_StartEngine;
    public bool Input_DebugInfo;


    [System.Serializable]
    public struct AxisConfig
    {
        public bool invert;
        public bool normalize;
        public float deadzone;  // Valor entre 0 y 1 (por ejemplo, 0.05 para una pequeña deadzone)

        // Constructor
        public AxisConfig(bool invert, bool normalize, float deadzone)
        {
            this.invert = invert;
            this.normalize = normalize;
            this.deadzone = deadzone;
        }
    }

    public AxisConfig accelConfig;
    public AxisConfig brakeConfig;
    public AxisConfig clutchConfig = new AxisConfig(false,true,0);
    public AxisConfig steerConfig;
    public AxisConfig handbrakeConfig;


    private void Start()
    {
        Instance = this;
    }

    

    
    void SetScheme(InputControlScheme Scheme)
    {

        Debug.Log(  "SCHEME RECEIVED = " + Scheme);

        /*
        for (int i = 0; i < actionAsset.controlSchemes.Count; i++)
        {
            Debug.Log($"[{i}] {actionAsset.controlSchemes[i].name}");
        }
        */

        // string SchemeName = Scheme.name;
        switch (Scheme.name)
        {
            case "Keyboard":
                pInput.SwitchCurrentControlScheme(Scheme.name);//, Keyboard.current
                break;

            case "Gamepad":
                pInput.SwitchCurrentControlScheme(Scheme.name  );//UnityEngine.InputSystem.Gamepad.current
                break;

            case "SteeringWheel":
                //InputDevice wheelDevice = default;
      
                // Lista de fabricantes y productos conocidos (logitech, thrustmaster, fanatec, moza, simucube, saitek)
                string[] knownManufacturers = { "Logitech", "Thrustmaster", "Fanatec", "MOZA", "Simucube", "Saitek", "Mad Catz" };
                string[] knownProducts = {
                            // Logitech (desde G25 hasta los más nuevos)
                            "G25", "G27", "G29", "G920", "G923", "G923 Racing Wheel", "G923", "Logitech G Pro Racing", 
        
                            // Thrustmaster
                            "T300", "T500", "T150", "TX", "T300 RS", "T300 Ferrari GTE", "T-GT",
                            "T-GT II", "T500 RS", "TS-PC Racer", "TS-XW Racer", "T150 Pro", "T80", "T150 Ferrari", "T-LCM",
                            "Thrustmaster T500RS",
        
                            // Fanatec
                            "DD1", "DD2", "Clubsport", "Clubsport V2", "Clubsport V2.5", "CSL Elite",
                            "Podium Racing Wheel", "CSL Elite Racing", "CSL DD", "Podium DD1", "Podium DD2", 
        
                            // MOZA
                            "R5", "R9", "R16",
        
                            // Simucube
                            "Simucube 2", "Simucube 2 Pro", "Simucube 2 Ultimate",

                            // Saitek (Mad Catz)
                            "R440", "R100", "Pro Racing Wheel", "Dual Force Racing Wheel", "Mad Catz Racing Wheel"
                        };

                // Buscar dispositivo compatible
                foreach (var device in InputSystem.devices)
                {
                    if (device.description.interfaceName.Contains("HID") || device.description.product.Contains("Wheel")) // Dispositivos HID
                    {
                        bool isKnownManufacturer = knownManufacturers.Any(m => device.description.manufacturer.Contains(m));
                        bool isKnownProduct = knownProducts.Any(p => device.description.product.Contains(p));

                        bool isGenericWheel = device.description.product.Contains("Wheel") || device.description.product.Contains("Joystick");

                        // Almacenamos el primer volante que coincida
                        if (isKnownManufacturer || isKnownProduct || isGenericWheel)
                        {
                            // Verificar que el dispositivo sea adecuado (en lugar de asignarlo directamente)

                            //wheelDevice = InputDevice.steeringWheel;

                            Debug.Log($"✅ Volante detectado: {UnityEngine.InputSystem.Joystick.current.description.manufacturer} - {UnityEngine.InputSystem.Joystick.current.description.product}");

                            pInput.SwitchCurrentControlScheme(Scheme.name, UnityEngine.InputSystem.Joystick.current);

                            return; // Termina la ejecución de la función después de encontrar un volante
                        }                 
                    }                    
                }
                return; // Termina la ejecución de la función después de encontrar un volante
        }

        // pInput.SwitchCurrentControlScheme(Scheme);
    }


    private void Update()
    {
        /*
       Input_Accel     = action_accel.action.ReadValue<float>();
       Input_Brake = action_brake.action.ReadValue<float>();
       Input_Clutch = action_clutch.action.ReadValue<float>();
       Input_Handbrake = action_handbrake.action.ReadValue<float>();


       var device = InputSystem.GetDevice<Joystick>();  // o usa Gamepad si prefieres

       if (device != null)
       {
           // Si el dispositivo es un mando de PlayStation (DualSense)
           if (device.name.Contains("DualSense"))
           {
               // Lee el Vector2 completo del stick izquierdo
               Input_Steer = action_steer.action.ReadValue<Vector2>().x;
           }

           else Input_Steer = action_steer.action.ReadValue<float>();
       }

       else if( device == null || !device.name.Contains("DualSense"))     Input_Steer = action_steer.action.ReadValue<float>();
*/

        //STEERING INPUT
        //--------------------------------------------------------------------------------------
        var device = InputSystem.GetDevice<Joystick>();  // o usa Gamepad si prefieres

        if (device != null)
        {
            // Si el dispositivo es un mando de PlayStation (DualSense)
            if (device.name.Contains("DualSense"))
            {
                // Lee el Vector2 completo del stick izquierdo
                Input_Steer = action_steer.action.ReadValue<Vector2>().x;
            }

            else Input_Steer = action_steer.action.ReadValue<float>();
        }

        else if (device == null || !device.name.Contains("DualSense")) Input_Steer = action_steer.action.ReadValue<float>();

        //--------------------------------------------------------------------------------------
        

        Input_Accel = ProcessAxis(action_accel.action.ReadValue<float>(), accelConfig);  // Procesamos el acelerador
        Input_Brake     = ProcessAxis(action_brake.action.ReadValue<float>(), brakeConfig);  // Procesamos el freno
        Input_Clutch    = ProcessAxis(action_clutch.action.ReadValue<float>(), clutchConfig);  // Procesamos el clutch
        Input_Handbrake = ProcessAxis(action_handbrake.action.ReadValue<float>(), handbrakeConfig);  // Procesamos el freno de mano

        Input_SteerStrong = action_steerStrong.action.ReadValue<float>();

        Input_GearUp = action_gearUp.action.WasPressedThisFrame();
        Input_GearDown = action_gearDown.action.WasPressedThisFrame();

        Input_H_Gear_1 = action_H_Gear_1.action.WasPressedThisFrame();
        Input_H_Gear_2 = action_H_Gear_2.action.WasPressedThisFrame();
        Input_H_Gear_3 = action_H_Gear_3.action.WasPressedThisFrame();
        Input_H_Gear_4 = action_H_Gear_4.action.WasPressedThisFrame();
        Input_H_Gear_5 = action_H_Gear_5.action.WasPressedThisFrame();
        Input_H_Gear_6 = action_H_Gear_6.action.WasPressedThisFrame();
        Input_H_Gear_R = action_H_Gear_R.action.WasPressedThisFrame();

        Input_changeCam = action_changeCam.action.WasPressedThisFrame();
        Input_CarReset  = action_CarReset.action.WasPressedThisFrame();
        Input_Pause     = action_Pause.action.WasPressedThisFrame();

        Input_LightsOn      = action_LightsOn.action.WasPressedThisFrame();
        Input_StartEngine   = action_StartEngine.action.WasPressedThisFrame();
        Input_DebugInfo     = action_DebugInfo.action.WasPressedThisFrame();


        //Debug.Log("Input_H_Gear_R " + Input_H_Gear_R);
     }

 
     float ProcessAxis(float valueRaw, AxisConfig config)
    {
        float cleanValue = valueRaw;

            if (Mathf.Abs(valueRaw) < config.deadzone)
            {
                cleanValue = 0f;
            }

            if (config.normalize)         // Normaliza el valor si está activado, con soporte de inversión

            {
                cleanValue = NormalizeAxis(valueRaw, -1f, 1f, config.invert);
            }
            else if (config.invert)
            {
                cleanValue = -valueRaw;
            }

        return cleanValue;
    }

    float NormalizeAxis(float rawInput, float minValue = -1f, float maxValue = 1f, bool invert = false)
    {
        float normalizedValue = (rawInput - minValue) / (maxValue - minValue);         // Normaliza el valor del rawInput al rango [0,1]
           
        if (invert)// Si se requiere invertir, transformamos el rango [0,1] a [-1, 0] o viceversa
        {
            return normalizedValue * -1;// Si invertimos, el valor de [0, 1] se convierte en [-1, 0]
        }

        else
        {
            return normalizedValue;// Si no invertimos, el valor de [-1, 1] pasa a [0, 1]
        }
    }

}

You need to use the Player Input script of the system for it to work

Then, on your scripts use it like this:

for bools

            if (NewInputSystem_Manager.Instance.Input_H_Gear_1) car.HGearManager(1);

for floats

            RAWSteerInput =  NewInputSystem_Manager.Instance.Input_Steer ;

With an structure like this you can navigate the new input system without having to change your mind with the event approach, which honestly sucks, and the extended use of strings in such approach is a deathtrap whaiting for you at the worst moment.

The only issues I found so far, are the issue with the horizontal left analog in PS4-PS5 controllers, reads as vector 2 instead of float, may or may not be a bug, makes my code looks like shiet.

The major one may be that even is you switch schemes, it does not mute the other inputs from other schemes, it does allegedly prioritize the input hardware asigned to such scheme, in my experience, a noisy PS5 controlelr many times tries to get on top when using steering wheel. I find this a major limitation, nearly a bug. I can´t believe that 4-5 years later documentation is so poor on this scheme switching “feature”.

Other htan that I’m quite happy, has solved my input issues. But the path untill I got to this simple solution has been harsh.

I see your ~50 Input related fields and call you on that “deathtrap”. What are you referring to here?

If you use the SendMessage approach with PlayerInput, then that’s all handled internally for you. We know SendMessage shouldn’t be used for regular code but here, this is all neatly wrapped by Input System, there’s nothing that could go wrong. And it can be quite nice to have separate input handling scripts, like gameplay and UI, both responding to separate events.

If you really want to properly process individual Input events without SendMessage, then use the C# event approach with the automated class and interface generation. The latter provides you type safety and best possible speed while also getting access to the started and cancelled event types.

With your script you effectively created a wrapper for Input System, something that the Input System already does for you if you allow it to generate that wrapper class for you. :wink:
Maybe something to look into for the next project.

I was able to avoid the death trap by using this workflow, but all other workflows rely hevily on string paths. Those workflows are a tragedy whaiting to happen.

To be fair the string-based approach is just the one that gets parroted by every bad tutorial.

The approach of referencing InputActionReference assets should be the one that gets promoted the most. Additionally, I don’t think many people know you can also just serialize a InputAction, which has a fully-featured a property drawer for it and everything. It’s a good way to build your own ‘input assets’ if you have need of extending it.