Search Unity

Can I manually update Input states?

Discussion in 'Scripting' started by quizcanners, Jan 24, 2016.

  1. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    If my main Update function takes 10ms to complete and during those 10 mili seconds a button was pressed it would be cool to know it at the end of it and update character position or something, the game will feel more responsive.

    I understand why Unity updates Input only once at the start, you would want some persistence in your code. But if people know what they are doing maybe it is good idea to let them. This is like a key things to make Call of Duty on Unity)

    Like in the end of Unpdate:

    UpdateInputState();
    if Input.KeyPressed .....

    So is this possible already or impossible at all, or I need to post a request? Thanks.
     
  2. Zalosath

    Zalosath

    Joined:
    Sep 13, 2014
    Posts:
    687

    What is the purpose of this? I may be able to help.
     
  3. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    Thank you.

    Most mobile games are not to heavy on the CPU (I am talking about code in Update functions). But I added some calculations that are heavy. So one of my Update functions take up to 10ms to complete, each frame. But those calculations have nothing to do with character movement. So I could check for button press at the end of Update function, right before Rendering thread starts to work on next frame. Problem is, I will get KeyPressed=True only if that button was pressed 10ms ago. This is why Unity games on old PC and Phones have this lag. How do I update key states during Update function.
     
  4. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    No, this is not possible. Unity's input system updates at the beginning of the thread update (before Update or FixedUpdate run). It is not a multi-threaded input system running on a fixed time step with access to poll for fresh values on demand, which is what would be required to do what you want.
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Well, you technically wouldn't need a multi-threaded solution. You'd just really need raw access to the get the current state of something right then and there at that moment.

    The problem with such a thing is that a raw state is only 'on' or 'off'. There's no 'down' or 'up' event as that depends on the state of the button previously. This state from frame to frame is why it's tethered to the framerate. Unity polls at the beginning of the frame so as to update if the button is 'down', 'held', 'up', or 'none'.

    BUT, Unity does not have a raw method to poll the state of the controller at that very moment. If they did it would probably be called something like 'GetButtonRaw', and it'd probably be more costly than the 'Input.GetButton' or 'Input.GetButtonDown' methods... but only ever so slightly more costly to be honest.


    Your only option is to implement your own input manager writing a wrapper around some 3rd party solution. Problem there is that each OS has a different interface through which to do it, and you'd have to deal with the hurdles of finding solutions for each.

    I believe there are some premade options on the Unity Asset Store for this...

    I believe this is one that does:
    https://www.assetstore.unity3d.com/en/#!/content/21676
     
  6. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    It depends on how the input source works. Some input sources cannot be polled and are based on system messages that are delivered at the beginning of the thread update. (Depends on platform and API.) If it allows polling, yes, you could just grab the latest state. But for message based systems, you can't get a fresher message in the middle of a thread update because the messages are queued up waiting to be delivered on the next update. The only way to get a fresh value mid-update in that case is to have a second high-frequency thread receiving the messages and then you can do your polling from the main thread to grab the latest state from the input thread's queue. That's what I was getting at. For a polling-based system like XInput, yes, you could just poll at any moment and grab the latest values. Most systems don't work that way.

    This happens to be my system. :) But at present, it also does not allow you to grab a fresher input value mid update.
     
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Yeah... it depends.

    Hence the "technically you wouldn't"... it's not yes or no.

    You stated that a multi-threaded solution is what is required. And it's not required.
     
  8. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    Technically correct, but it was a generalization. Of all the platforms and input sources I've covered, I can only think of 2 that would allow you to just poll any device at any point to get current data. The majority don't. Even some that do can crash with certain devices when polled if the device doesn't support it.

    The OP never mentioned what platform(s) to which he was referring.
     
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Interestingly enough, most of the native tools I've used were quite the opposite. Allowing me to poll whenever I needed. You even mentioned one of them (XInput).

    So yes... it depends. Depends is a different word than required. You can't expect me to assume you meant "in the majority of cases I've dealt with", when you say "required". Required implies 100%.

    It's great that you clarified. But you can't blame me for inferring what I did from your original text as it didn't have that clarification.

    Or would you prefer an argument of semantics for the duration of the thread?
     
  10. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    If the intent is to both be able to get the freshest state and also not be prone to missing button events, especially at low frame rates, you can't beat event messages on a separate thread. Sure, you can poll an axis at any point during the frame to get the current state on certain input sources like XInput, but if you're concerned at all about missing button presses/releases that may have occurred mid-frame, you really can't rely on just instantaneous moment-in-time polling on a single thread. When I say a multi-threaded solution is required, I'm assuming the op wants a fully robust input solution that can handle this situation as well. Maybe I'm reading more into it than he is looking for... I don't know.

    I'm not interested in arguing semantics or minute technicalities. My post was made with what I read as the intent of the OP. In my opinion, to create an input system as responsive and robust as Call of Duty, a separate thread for handling input is required for reasons stated above.

    Yes, you are correct. Multi-threading is not always required to simply get the latest state of an input.
     
    Last edited: Jan 30, 2016
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Sure dude, whatever. I wasn't talking about preferences.

    You're not interested in arguing semantics yet you philibuster like it's so freaking important.
     
  12. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    You've clearly got a problem. Have a nice day.
     
  13. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    Wow, it was going so well until last 2 posts :)

    Any way. Thank you alot, this are the answers I was looking for.

    I am indeed interested in something that works on everything, so I wouldn't have to write my own solutions for every platform. But if it is the only way, I would do that.

    Other option I was looking for is some sort of SuperLate update. If I am reading this right there are no "PostFrameUpdate" update.

    I don't even need to know Time.deltaTime for my calculations. Just while frame is on screen I want to calculate something, before Input update. I even tried to see if I can put it in "OnApplicationPause" that is called after frame is rendered.

    Is there a way to create Update function that is called right after Frame is on screen but before next cycle begins?
     
  14. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,631
    Looking at the order of events here, the only thing I can think of would be:
    OnRenderImage or OnGUI

    OnRenderImage: Called after scene rendering is complete to allow postprocessing of the image. (Do your number crunching on the Camera?)

    OnGUI: Called multiple times per frame in response to GUI events. The Layout and Repaint events are processed first, followed by a Layout and keyboard/mouse event for each input event.

    That sounds very odd to do calculations in OnGUI, but it may work. And you'd have to make sure you're not executing your code in OnGUI multiple times per frame.

    Are your calculations such that you could do them in a separate thread? Do they need to interact with the Unity API in any way? If not, a Background Worker might be suitable and would take the load off the main game thread. Of course, there could be some cross-platform issues to work out depending on your targets.
     
    Last edited: Jan 30, 2016
  15. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    I have one thread already for other things. I will test your solutions.
    And I don't really have Update function that takes 10ms, that was just an example. But I do have one main Update() that calls MyUpdate() functions in other classes because order in which things are processed are important since there are many dependencies. I will try to move it to those functions and make sure it is called once per frame.