Search Unity

Input Bug with Unity's 2019 Input System(Preview)

Discussion in 'Input System' started by Sky909, Oct 23, 2019.

  1. Sky909

    Sky909

    Joined:
    Oct 23, 2019
    Posts:
    6
    Hi everyone,

    I've decided to use the new version of Unity's Input System that utilizes Input Actions and Action Maps for my current game project and ran into a problem with my Inputs triggering twice or even multiple times with one buttons press. Although I can move my Character and perform the different actions with the buttons I've assigned, the functions that are automatically generated and needed for the Input Actions and the Interface are triggering multiple times on a button press (I've checked with breakpoints and Console outputs). I have tried different things like assigning Interactions to the different Actions in the Input Action interface, but the inputs still triggered multiple times.
    Here's the code I am currently using, I've also included a picture of the Input Action Manager with the currently assigned buttons:

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.InputSystem;
    6. public class ActionMapPC : MonoBehaviour, GeneralInput.IPlayerInputActions
    7. {
    8.     private GeneralInput controls;
    9.     [SerializeField]
    10.     private ActionMapCC actionMapCC;
    11.     private CharacterController charController;
    12.     Animator animator;
    13.     [SerializeField]
    14.     private float walkSpeed = 2;
    15.     [SerializeField]
    16.     private float runSpeed = 6;
    17.     bool running;
    18.     private Vector2 input;
    19.     float turnSmoothTime = 0.2f;
    20.     float turnSmoothVelocity;
    21.     float speedSmoothTime = 0.2f;
    22.     float speedSmoothVelocity;
    23.     float currentSpeed;
    24.     [SerializeField]
    25.     private float mass = 80;
    26.     private void Awake()
    27.     {
    28.         controls = new GeneralInput();
    29.         controls.PlayerInput.SetCallbacks(this);
    30.         charController = GetComponent<CharacterController>();
    31.         animator = GetComponentInChildren<Animator>();
    32.     }
    33.     private void OnEnable()
    34.     {
    35.         controls.PlayerInput.Enable();
    36.     }
    37.     private void OnDisable()
    38.     {
    39.         controls.PlayerInput.Disable();
    40.     }
    41.     public void OnMovement(InputAction.CallbackContext context)
    42.     {
    43.         input = context.ReadValue<Vector2>();
    44.         Debug.Log("trigger");
    45.     }
    46.     public void OnRun(InputAction.CallbackContext context)
    47.     {
    48.         float value = context.ReadValue<float>();
    49.         if (value == 1)
    50.         {
    51.             running = true;
    52.         }
    53.         else
    54.         {
    55.             running = false;
    56.         }
    57.     }
    58.     void Update()
    59.     {
    60.         Vector2 inputDir = input.normalized;
    61.         Vector3 inputDirWS = actionMapCC.MapInputToWorldSpace(inputDir);
    62.         if (inputDir != Vector2.zero)
    63.         {
    64.             float targetRotation = Mathf.Atan2(inputDirWS.x, inputDirWS.z) * Mathf.Rad2Deg;
    65.             transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, turnSmoothTime);
    66.         }
    67.         float targetSpeed = ((running) ? runSpeed : walkSpeed) * inputDir.magnitude;
    68.         currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, speedSmoothTime);
    69.         charController.SimpleMove(transform.forward * currentSpeed);
    70.         float animationSpeedPercent = ((running) ? 1 : .5f) * inputDir.magnitude;
    71.         animator.SetFloat("speedPercent", animationSpeedPercent, speedSmoothTime, Time.deltaTime);
    72.     }
    73.     private void OnControllerColliderHit(ControllerColliderHit hit)
    74.     {
    75.         if (hit.collider.attachedRigidbody == null)
    76.             return;
    77.         Vector3 moveDir = hit.moveDirection;
    78.         moveDir *= currentSpeed * mass;
    79.         Vector3 point = hit.point;
    80.         hit.collider.attachedRigidbody.AddForceAtPosition(moveDir, point, ForceMode.Force);
    81.     }
    82.  
    83. }
    84.  
    85.  
    For clarification the functions OnMovement() and OnRun() are triggering multiple times, these are functions generated by the Input Action Manager. This problem is also happening in other scripts where I use this type of Input.
    I hope I described my problem properly, I would be grateful if someone could help me to solve my problem.
     

    Attached Files:

  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    This is by design. When using SetCallbacks, each method will get hooked into all three callbacks, i.e. InputAction.started, InputAction.performed, and InputAction.canceled.

    In general, when an action starts it will trigger InputAction.started, followed by InputAction.performed. Then, for each subsequent value change, it will trigger InputAction.performed. When going back to default value, it will trigger InputAction.canceled. Thus you may see repeated callbacks in a frame.

    You can check the current action phase using InputAction.CallbackContext.phase.
     
  3. Sky909

    Sky909

    Joined:
    Oct 23, 2019
    Posts:
    6
    Okay thank you for the explanation, didn't know about the three callbacks.
    But how do I restrict it to one trigger? To clarify what i mean:
    If i want to increment a value with a button press it should go from 1 to 2. In the current state however, because of the two callbacks (action.started and action.performed) it increments twice and goes from 1 to 3.
     
  4. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Code (CSharp):
    1. public void OnMyAction(InputAction.CallbackContext context)
    2. {
    3.     if (context.performed)
    4.         ++m_Count;
    5. }
    In case you're binding to controls with values in the full [0..1] range rather than just being either on or off, put a Press interaction on the binding so it only performs once per press instead of once per value change.
     
  5. Sky909

    Sky909

    Joined:
    Oct 23, 2019
    Posts:
    6
    Thank you so much! I struggled a bit cause I didn't know about the different callbacks. It's working now :D
     
  6. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
  7. LexGear

    LexGear

    Joined:
    Sep 24, 2012
    Posts:
    11
    Hi! So I'm having the same issue, however, it's ONLY for player one. Every other people that joins in the button on their respective controllers only fires once. I for the life of me cannot figure this one out. I've been at it for 2 weeks now.
     
  8. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    What does the input debugger say about the player setup? It should list each user along with the associated devices. And also list global actions and their controls. Any chance there's both a global setup and a user setup in place for player #0?
     
  9. LexGear

    LexGear

    Joined:
    Sep 24, 2012
    Posts:
    11
    Thanks for the reply. Here is a screenshot of my input debugger. I don't see a global setup, but maybe you'll be able to tell from the below.