Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.

    Read our full announcement for more information and let us know if you have any questions.

Question Radial aim control in 2D game for both mouse and gamepad

Discussion in 'Input System' started by EmmetOT, Jul 29, 2021.

  1. EmmetOT


    Apr 25, 2016
    I'm using the new input system and mostly liking it so far, however I'm trying to make a simple 2D shooter in which the player can aim in a radius around themselves.

    With mouse, this involves pointing at a position on screen, which is then translated into a direction relative to the player's position. With gamepad, it's simply the rotation of the right stick.

    For my input system workflow I like building it to a C# class and just using it with callbacks, or checking the actions in update.

    I can get one of the input schemes to work but not both. This is because the mouse input requires some degree of 'processing' but the gamepad input is essentially raw. I'm wondering what I have to do to make the input system produce the appropriate direction input for both schemes. I can see there's a 'radius' option for mouse input which seems like what I want, but it simply gives (0, 0).

    Here is the code I have for handling the input, which works correctly for the mouse input but obviously just gives nonsense for the gamepad.

    Code (CSharp):
    2.         // called from the update loop
    3.         private void UpdateAimInput()
    4.         {
    5.             Vector2 val = m_input.Player.Aim.ReadValue<Vector2>();
    6.             Vector2 target = Camera.main.ScreenToWorldPoint(new Vector3(val.x, val.y, -Camera.main.transform.position.z));
    8.             m_aimInput = (target - (Vector2)transform.position).normalized;
    9.         }
    Here are some solutions I'd expect:

    1) Maybe I'm using radius wrong? I can't find any documentation about this anywhere.
    2) If I had some way to differentiate the control source (mouse v gamepad) this would be a piece of cake. I can see there are ways, but they involve string comparisons and are specific to my brand of controller. For example,
    gives "Xbox Controller" which obviously isn't ideal.
    3) Maybe there's some way to write a custom processor in the input asset. This would be really useful.
  2. Radlas


    May 25, 2020
    Code (CSharp):
    2. var inputLookDir = inputActionLook.ReadValue<Vector2>();
    3.         if (playerInput.currentControlScheme.Equals("Gamepad"))
    4.             inputLookDir = inputLookDir.normalized;
    5.         else
    6.             inputLookDir = (inputLookDir - new Vector2(Screen.width/2, Screen.height/2)).normalized;
    Since reading a Gamepad Stick input will result in a Vector2 with values clamped between -1 and 1, and that's what I desired in my project, I do an additional processing step to convert the Position input of the mouse.
    I check the active control scheme, and if its not Gamepad, I convert the mouse position to a usable vector where the 0,0 is the center of the Screen.
  3. EmmetOT


    Apr 25, 2016
    Unfortunately, since I'm using a generated C# class, I have no access to "currentControlScheme". For some silly reason...

    Thanks for the help, though!
  4. badi-haki


    May 24, 2016
    Having the exact same issue, you ever find a solution?
  5. SMT5015


    Apr 5, 2021
    When you receive an InputAction.CallbackContext struct in your subscribed methods, it has a field "control" of type InputControl, which tells you from where the action was triggered. And it has a property "device" of type InputDevice. You can process input depending on the type of device, doing what you did if it was mouse and something else if it was gamepad or whatever.

    Or, since you probably don't want to compare types for such frequent action, you can retrieve a path for an InputBinding inside the action and use static class InputControlPath to check if it matches the control.
    Last edited: Feb 7, 2023