Search Unity

Input.GetKey...can be used outside the update function to save memory? As an Event?

Discussion in 'Scripting' started by Larpushka, Nov 4, 2015.

  1. Larpushka

    Larpushka

    Joined:
    Jan 6, 2015
    Posts:
    214
    Hey guys. I'm a bit curious if there is a way to avoid using the Input.GetKey outside the update function, like an Event, so it would only be in effect if a key is pressed. Is there a way?
     
  2. catalin.nastase

    catalin.nastase

    Joined:
    Sep 29, 2015
    Posts:
    2
    Valda, what memory are you trying to save?
    As for input events, there are non by default in Unity's API, but if you could create an InputManager that has such events, that code would still use Input.GetKey inside an Update. I do know that low level input is still checked on the main loop of the app. So there should not be theoretically any performance or memory huge difference between the Update or an Event way of checking the input. Event based is more elegant and the performance and memory issues in Unity's case can mainly be cause by the C# VM requirement's and implementation on top of the low level C++ engine. The communication between C++ and C# has an extra cost, but it's insignificant on today's hardware (at least what most of us are targeting to use with Unity).
     
    Matt-Roper likes this.
  3. catalin.nastase

    catalin.nastase

    Joined:
    Sep 29, 2015
    Posts:
    2
    Something like this can give you input Events.
    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4.  
    5. public class InputManager : MonoBehaviour
    6. {
    7.     public static InputManager Instance = null;
    8.  
    9.     public delegate void KeyEvent(KeyCode key);
    10.     public static event KeyEvent KeyPressed;
    11.     public static event KeyEvent KeyReleased;
    12.  
    13.     private KeyCode[] keycodes;
    14.  
    15.     void Start()
    16.     {
    17.         if (InputManager.Instance != null && Instance != this)
    18.             Destroy(gameObject);
    19.         else
    20.             Instance = this;
    21.  
    22.         keycodes = (KeyCode[])Enum.GetValues(typeof(KeyCode));
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         for (int i = 0; i < keycodes.Length; ++i)
    28.         {
    29.             if (KeyPressed != null && Input.GetKeyDown(keycodes[i]))
    30.             {
    31.                 KeyPressed(keycodes[i]);
    32.             }
    33.  
    34.             if (KeyReleased != null && Input.GetKeyUp(keycodes[i]))
    35.             {
    36.                 KeyReleased(keycodes[i]);
    37.             }
    38.         }
    39.     }
    40. }
     
  4. Larpushka

    Larpushka

    Joined:
    Jan 6, 2015
    Posts:
    214
    I thought I already replied to this topic but I don't see my reply...

    Anyway, what I wrote is that I appreciate the feedback and I'm now confident I can use it in the update function without feeling like I'm bogging down the system. Thank you
     
    Matt-Roper likes this.
  5. Rattdaddy

    Rattdaddy

    Joined:
    Mar 4, 2015
    Posts:
    13
    A bit of a thread necro, yes, but this was still near the top of the results when just searching this. I noticed recently in profiling something of potential interest.

    I had an Update() in an object that was always running, i.e. not destroyed on scene change. Within it there were two Input.GetKeyDown(KeyCode) checks, as well as a call to another singleton class's method, which was was merely a check for a third Input.GetKeyDown(KeyCode) check. E.g.


    Code (CSharp):
    1. private void Update()
    2. {
    3.     SomeManager.Instance.CheckInput();
    4.  
    5.     if(Input.GetKeyDown(KeyCode.F2) { DoSomething(); }
    6.     if(Input.GetKeyDown(KeyCode.F3) { DoSomethingElse(); }
    7. }
    where SomeManager.CheckInput() looked like

    Code (CSharp):
    1. public void CheckInput()  
    2. {    
    3.     if (Input.GetKeyDown(KeyCode.Tab))
    4.     {
    5.         if (gameObject.activeSelf) { DoBlah(); }
    6.         else { DoOtherBlah(); }
    7.     }
    8. }
    In the profiler, if I just put the original Update checks for input wrapped in a if(Input.anyKeyDown) { }, a la

    Code (CSharp):
    1. {
    2.     if(Input.anyKeyDown)
    3.     {
    4.     SomeManager.Instance.CheckInput();
    5.  
    6.     if(Input.GetKeyDown(KeyCode.F2) { DoSomething(); }
    7.     else if(Input.GetKeyDown(KeyCode.F3) { DoSomethingElse(); }
    8.     }
    9. }
    I saw quite a CPU drop in the BehaviourUpdate calls. Not sure if it was a huge drop, in an absolute sense, but it certainly dropped down the usage relative to what it was at the time. And simple enough to add for cases that there are multiple KeyCode checks. Just my two cents, and could be completely just a profiler/editor thing, or some other mitigating circumstance, but I've since taken to using that. Is this a known workaround for others, I wonder?
     
    TommySKD, calurin and Meri like this.
  6. Willkuerlich

    Willkuerlich

    Joined:
    Sep 23, 2014
    Posts:
    15
    Save the reference to SomeManager.Instance in your class, don't retrieve it on every Update() call again