Search code examples
c#unity-game-engineinput

New Input System not Working at Timescale 0 even when Update Mode is set to "Process Events in Dynamic Update"


I've been learning the new input system for Unity, and everything was working great, until timescale is set to 0 and no input gets read at all. I've looked through other forums and found that I should have Update Mode set to "Process Events in Dynamic Update", but it turns out that was enabled by default.

Am I doing anything wrong here? Or is there something I'm missing?

here's my code: If I remove the part that sets Time.Timescale to 0 (located in a different spot), it works great, but with it in even my Print() functions do nothing

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class QuickMenuScript : MonoBehaviour
{
    public int MenuItemsAmount;
    public float cursorMoveSpeed;


    int cursorPosition;
    float progress;
    public Animator MenuHost;
    public void action(int id)
    {
        Animator animator = GetComponent<Animator>();

        if (id == 0)
        {
            MenuHost.SetBool("Continue", true);
        }
        if (id == 1)
        {
            MenuHost.gameObject.GetComponent<killPlayerFromUI>().kill();
        }
        if (id == 2)
        {
            Application.Quit();
        }
    }
    public void moveCursor(InputAction.CallbackContext context)
    {
        print("moving");
        if (context.performed)
        {
            if (context.ReadValue<float>() != 0)
            {
                if (context.ReadValue<float>() < 0)
                {
                    cursorPosition++;
                }
                else
                {
                    cursorPosition--;
                }
            }

            if (cursorPosition > MenuItemsAmount)
            {
                cursorPosition = 1;
            }
            if (cursorPosition < 1)
            {
                cursorPosition = MenuItemsAmount;
            }
        }
    }

    private void Update()
    {
        Animator animator = GetComponent<Animator>();
        progress = Mathf.MoveTowards(progress,cursorPosition,cursorMoveSpeed*Time.deltaTime);
        animator.SetFloat("Blend",progress);

    }
    public void Submit(InputAction.CallbackContext context)
    {
        print("submitting");
        if(context.performed)
        {
            action(cursorPosition);
        }
    }
    public void Back(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            MenuHost.SetBool("Continue", true);
        }
    }

    public void timeReturn()
    {
        Time.timeScale = 1;
    }

}

Here's my Player Input Component that I'm using for this: Image


Solution

  • I figured it out: It turns out that if I switch from using the UnityEvents to using the C# class, (and also switch to using Time.UnscaledDeltaTime), it works just fine.

    Check "Generate C# class" box in the Input Action Asset Properties

    Then subscribe to the InputAction.ActionMap.Action.performed Event, after making a variable which is defined to a new InputAction() asset. (Make sure to set InputAction, ActionMap, and Action to the names of the respective Input action assets, Action Maps, and Actions) Also I needed to make a new OnDestroy() function that unsubscribes to the event when the object is destroyed so I don't get any errors.

    Additional note: do not assign the InputAction to a new InputAction() when first declaring it, do it in the start() function instead. Updated Code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.InputSystem;
    
    public class QuickMenuScript : MonoBehaviour
    {
        public int MenuItemsAmount;
        public float cursorMoveSpeed;
    
        int cursorPosition;
        float progress;
        public Animator MenuHost;
        RollItGeneralInputs input;
    
        private void Awake()
        {
            input = new RollItGeneralInputs();
    
            input.QuickMenu.Enable();
            
            input.QuickMenu.MoveCursor.performed += moveCursor;
            input.QuickMenu.Submit.performed += Submit;
            input.QuickMenu.Back.performed += Back;
            
        }
        public void action(int id)
        {
            if (GetComponent<Animator>() == null) return;
    
            Animator animator = GetComponent<Animator>();
    
            if (id == 0)
            {
                MenuHost.SetBool("Continue", true);
            }
            if (id == 1)
            { 
                MenuHost.gameObject.GetComponent<killPlayerFromUI>().kill();
                MenuHost.SetBool("Continue", true);
                
            }
            if (id == 2)
            {
                Application.Quit();
            }
        }
        public void moveCursor(InputAction.CallbackContext context)
        {
            if (!context.performed) return;
    
            if (context.ReadValue<float>() != 0)
            {
                if (context.ReadValue<float>() < 0)
                {
                    cursorPosition++;
                }
                else
                {
                    cursorPosition--;
                }
            }
    
            if (cursorPosition > MenuItemsAmount)
            {
                cursorPosition = 0;
            }
            if (cursorPosition < 0)
            {
                cursorPosition = MenuItemsAmount;
            }
    
        }
        private void Update()
        {
            Animator animator = GetComponent<Animator>();
            progress = Mathf.MoveTowards(progress,cursorPosition + 1,cursorMoveSpeed*Time.unscaledDeltaTime);
            animator.SetFloat("Blend",progress);
    
        }
    
        public void Submit(InputAction.CallbackContext context)
        {
            Debug.Log("submitting " + cursorPosition);
            if (!context.performed) return;
    
            action(cursorPosition);
    
        }
        public void Back(InputAction.CallbackContext context)
        {
            print(MenuHost);
            if (!context.performed) return;
            if (MenuHost == null) return;
    
    
            input.QuickMenu.MoveCursor.performed -= moveCursor;
            input.QuickMenu.Submit.performed -= Submit;
            input.QuickMenu.Back.performed -= Back;
    
            print(MenuHost);
            MenuHost.SetBool("Continue", true);
    
            
    
        }
        private void OnDestroy()
        {
    
            input.QuickMenu.MoveCursor.performed -= moveCursor;
            input.QuickMenu.Submit.performed -= Submit;
            input.QuickMenu.Back.performed -= Back;
        }
        public void timeReturn()
        {
            Time.timeScale = 1;
        }
    
    }
    

    Another note: to subscribe to an event, just do:

    nameOfEvent += NameOfFunctionToCallOnEvent
    

    then to unsubscribe just do

    nameOfEvent -= PreviousFunctionYouSubscribedTo
    

    in this case the nameOfEvent would be the InputAction.ActionMap.Action.performed event we did earlier.