Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Input freezes for several seconds shortly after repeatedly entering Play mode

Discussion in 'Input System' started by Richay, Mar 1, 2020.

  1. ZoopTEK

    ZoopTEK

    Joined:
    Feb 14, 2012
    Posts:
    22
    I am running Unity 2020.3.12f1 with Input System 1.0.4 and run into this problem. Very very annoying.
     
  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Thanks for the ping. Last effort to solve this got stuck at not being able to repro on our end. Raising this one again to have a look at the additional information that has been posted.
     
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Is anyone seeing this problem with 1.1-pre.6? There's been a flood of fixes since 1.0.2 so would be very curious whether this is still a problem with the latest package.
     
  4. ZoopTEK

    ZoopTEK

    Joined:
    Feb 14, 2012
    Posts:
    22
    I just tried upgrading to 1.1-pre.6 from 1.0.2, and it seems to have goofed up mouse input. It's super duper jerky. If I am moving my mouse more than a pixel per few seconds, it jumps. It's almost as if it's polling at an inconsistent speed. I am using fixed update.

    Apparently images only work in the post editor, but not when viewing the post... go figure.

    EDIT 1: Also, why is 1.1.0-preview.3 > 1.1-pre.6? Pre versus preview? 3 > 6?

    EDIT 2: Apparently 1.1.0-preview.3 doesn't have the jerkiness.

    EDIT 3: The problem still exists in the latest preview, after setting my computer to hibernate overnight.
     
    Last edited: Aug 31, 2021
  5. owenlshinyshoe

    owenlshinyshoe

    Joined:
    Aug 4, 2017
    Posts:
    8
    I have a hack fix that seems to work.

    We're using Unity 2021.1.11f1 and InputSystem 1.0.2.

    Call this function when your game starts up. You only need to call it once, but it doesn't hurt to call it more than once. Preferrably let the InputSystem update at least once before you call it.

    Code (CSharp):
    1. void HackFixForEditorPlayModeDelay()
    2. {
    3. #if UNITY_EDITOR
    4.     // Using reflection, does this: InputSystem.s_SystemObject.exitEditModeTime = 0
    5.  
    6.     // Get InputSystem.s_SystemObject object
    7.     FieldInfo systemObjectField = typeof(UnityEngine.InputSystem.InputSystem).GetField("s_SystemObject", BindingFlags.NonPublic | BindingFlags.Static);
    8.     object systemObject = systemObjectField.GetValue(null);
    9.  
    10.     // Get InputSystemObject.exitEditModeTime field
    11.     Assembly inputSystemAssembly = typeof(UnityEngine.InputSystem.InputSystem).Assembly;
    12.     Type inputSystemObjectType = inputSystemAssembly.GetType("UnityEngine.InputSystem.InputSystemObject");
    13.     FieldInfo exitEditModeTimeField = inputSystemObjectType.GetField("exitEditModeTime", BindingFlags.Public | BindingFlags.Instance);
    14.  
    15.     // Set exitEditModeTime to zero
    16.     exitEditModeTimeField.SetValue(systemObject, 0d);
    17. #endif
    18. }
    This sets InputSystem.s_SystemObject.exitEditModeTime to zero. The reason we do that is to disable a section of code in InputManager.cs (see below).

    My understanding of this code is that it discards input events that happened between the time we exit Edit Mode and Enter Play Mode so that they don't happen on the first frame of our game. Which is good and why I figure that probably we want to wait to disable this code until after InputSystem has done at least one update.

    I put logs in this code and watched it when the input delay was happening. As I waved my mouse over a button, it generated one event at a time and that event had a current time that put it in between exitEditModeTime and enterPlayModeTime, so it was skipped by this code. That current time of the event seems to be what's wrong and I have no idea what's causing that. But disabling this section of code is a hack workaround.

    Specifically, my log was this:
    Code (CSharp):
    1. Debug.LogWarning($"Skipping input cur {currentEventTimeInternal}, exit {InputSystem.s_SystemObject.exitEditModeTime}, enter {InputSystem.s_SystemObject.enterPlayModeTime}, num events {eventBuffer.eventCount}");
    And this is one of the logs that printed when I moved over the button:
    Skipping input cur 117751.3997743, exit 117751.384327, enter 117759.2947341, num events 1

    One of the conditions for the code if-statement to be true is "InputSystem.s_SystemObject.exitEditModeTime > 0", so setting it to 0 disables it. When we hit Play the next time, exitEditModeTime gets set to a valid value, so everything should return to normal.

    Here's the InputSystem code that I'm disabling:
    (In Library\PackageCache\com.unity.inputsystem@1.0.2\InputSystem\InputManager.cs)
    Code (CSharp):
    1. #if UNITY_EDITOR
    2. if ((updateType & InputUpdateType.Editor) == 0 &&
    3.     InputSystem.s_SystemObject.exitEditModeTime > 0 &&
    4.     currentEventTimeInternal >= InputSystem.s_SystemObject.exitEditModeTime &&
    5.     (currentEventTimeInternal < InputSystem.s_SystemObject.enterPlayModeTime ||
    6.     InputSystem.s_SystemObject.enterPlayModeTime == 0))
    7. {
    8.     // Note: My debug log.  It's not in the actual code
    9.     Debug.LogWarning($"Skipping input cur {currentEventTimeInternal}, exit {InputSystem.s_SystemObject.exitEditModeTime}, enter {InputSystem.s_SystemObject.enterPlayModeTime}, num events {eventBuffer.eventCount}");
    10.  
    11.     eventBuffer.AdvanceToNextEvent(ref currentEventReadPtr, ref currentEventWritePtr,
    12.         ref numEventsRetainedInBuffer, ref remainingEventCount, leaveEventInBuffer: false);
    13.     continue;
    14. }
    15. #endif
    Notes:

    I don't know the conditions for making the problem happen. For whatever reason it was happening to me consistently the other day, so I took the opportunity to look into it.

    The exitEditModeTime in my logs seems to indicate that my Editor was running for 32 hours, which sounds plausible. I often keep my work computer on for 5 or more days, putting it to sleep at night. I also usually have multiple Editors (2-3) running at the same time (on different Windows virtual desktops). I will sometimes close the Editor if I'm switching git branches, but it's common for me to have an Editor running continuously for more than a day.

    I was trying all kinds of things to get the problem to happen on one of the Editors I had open and finally gave up. Then I switched to the other Editor I had open, started to work on something different, and it happened on that one consistently. I think there's a good chance it depends on how long the Editor instance has been open.

    For those of you who are getting this problem and want to debug it, you can put logs in InputSystem and step through it by moving the package into your project. Copy the Library\PackageCache\com.unity.inputsystem@1.0.2 directory to the root of your project and then change Packages/manifest.json from "com.unity.inputsystem": "1.0.2" to "com.unity.inputsystem": "file:../com.unity.inputsystem@1.0.2".
     
  6. cp-

    cp-

    Joined:
    Mar 29, 2018
    Posts:
    78
    @owenlshinyshoe thanks for your investigation. It strongly supports the theories about the negative event time mentioned in older posts. Also, I think it should not be hard to fix.

    As @Rene-Damm asked: Have you tried to switch to a current 1.1.0-preview version?

    Reproducability is the issue here as the error seems to creep up only when Unity runs for a long time and possibly only when the PC went to standby/hibernation for a while in between. A repro-nightmare.
     
  7. darashayda

    darashayda

    Joined:
    Jun 27, 2020
    Posts:
    429
    Excellent!
    I have another way of doing what you elegantly accomplished. I will study yours and might make some more comments.

    There is a clogged queue some place when you reset or set time to 0 or inactivate and activate some part of the Input System, there is a FLUSH occur, so to say! This FLUSH in other systems are available for the programmer to enforce to avoid these sorts of backups.

    Somehow I did not find it, so my hack and yours works instead , but these are bad options.

    Input System guys need to add the so called FLUSH for their queues so we can force it even so secs or events.

    Else there will be another 1.5 years of this nightmare.

    Dara
     
  8. owenlshinyshoe

    owenlshinyshoe

    Joined:
    Aug 4, 2017
    Posts:
    8
    Yes, my logs make me think that the event time (specifically
    currentEventReadPtr->internalTime) is wrong during the input freeze. Though not negative. A time that puts it between when I hit Play and entered Play Mode, so that it gets discarded.

    I went in thinking this, but now I don't think there's a clogged queue. When the input freeze was happening, I logged every event that was processed. It logged nothing, then I waved my mouse over a button and it logged one event as the mouse entered the button and one event when it exited. That says to me that the queue was clear and input system functioning properly. However, the events were being discarded, because that section of code thought that the events had come between hitting Play and entering Play Mode due to the events' times.
     
  9. owenlshinyshoe

    owenlshinyshoe

    Joined:
    Aug 4, 2017
    Posts:
    8
    I have not. I will put that on my to-do list. Though it will be a while, since I have other tasks that take priority.
     
  10. owenlshinyshoe

    owenlshinyshoe

    Joined:
    Aug 4, 2017
    Posts:
    8
    I've been thinking about this some more, and here's what I think is happening:

    My observation:
    • This most likely happens when the Editor has been open for hours. Possibly also the computer being in sleep or hibernate mode is a factor.
    • The "input freeze" always takes a few seconds. I haven't timed it, but I'd say about 5 to 7.
    • The freeze only happens once, it never happens again during play.
    • The freeze often happens at the beginning of play, but not immediately. I've had it happen a few minutes into play.
    • When I put logs in the InputSystem C# code, the freeze appears to be because it's discarding events because their times are wrongly between the "exit edit mode" and "enter play mode" times.

    My guess is that the 5-7 seconds of freeze time corresponds to the time it takes for Play Mode to start for me. I have domain reloading on, and unfortunately it takes up to 8 seconds from the time I hit Play to my game actually starting.

    This makes me think that the time used to set InputSystem.s_SystemObject.exitEditModeTime and InputSystem.s_SystemObject.enterPlayModeTime (InputRuntime.s_Instance.currentTime) gets out of sync with the time used to set the events (currentEventReadPtr->internalTime).

    The code that I disable with my hack fix looks at the window of time between hitting Play and entering Play Mode. If any event times are in that window, it discards them.

    So my guess is that the event times get so that they don't line up with the time used for that window. The window only lasts for a few seconds: the time that it takes to enter Play Mode. And if the times get way out of sync, that window could happen minutes after play starts.

    That theory lines up with my observations. Why/how the event times get out of sync from exitEditModeTime/enterPlayModeTime, I don't know. I'll leave that to the Unity folks.
     
    NotaNaN, LeandroExHuMeD and flippi273 like this.
  11. andrew_oc

    andrew_oc

    Unity Technologies

    Joined:
    Apr 16, 2021
    Posts:
    77
    Hi all, thanks for all the feedback about this issue. We think we've finally been able to track it down and fix it. The issue was caused by using two separate sources of time, one for windows input event timestamps and another for current time in various other operations, pretty much as @owenlshinyshoe and others surmised. On Windows, those two time sources drift apart across sleep->resume cycles, and the effect is cumulative, so those who sleep their machines more often would experience longer freezes over time. The solution was to use a single source of time. The fix will be available in the next Unity release, but backports for 2021.2, 2021.1, and 2020.3 are also in the queue.
     
  12. RedHillbilly

    RedHillbilly

    Joined:
    Mar 24, 2014
    Posts:
    39
    Cool! Thanks a lot for fixing it! Testing as soon as it's live :)
     
  13. flippi273

    flippi273

    Joined:
    Nov 17, 2018
    Posts:
    24
    Awesome! How can we be alerted when this specific has been backported. I'm currently using 2021.1 and would want to update once it's been released.
     
  14. gnovos

    gnovos

    Joined:
    Apr 29, 2020
    Posts:
    26
    2021.2.0f1 still has this issue
     
  15. caliberbeats

    caliberbeats

    Joined:
    Oct 9, 2021
    Posts:
    2
    I've seen it said that this issue is exclusive to the editor, I'd like to add that I'm having this issue in builds.

    Button presses work just fine for toggling my map and pause menu, I can look around, etc. However passthrough events like WASD only receive a message for 1 frame every 15-20 seconds. The only solution I have found is restarting my computer. Restarting Unity does nothing to fix the issue in the editor, nor does restarting the built executable.

    I have no other inputs or controllers connected to my computer, not even a webcam/microphone, I've unplugged everything and set Input System to only support keyboard and mouse. On enable I enable my entire default actions, and subscribe to them all. When I try to move with WASD I debug log the input value from the subscriber. It only reads a value when it feels like it wants to, rather than when the Move input action bindings are held. Should an input action with type of passthrough be sending continuous messages to events subscribed with actions.Player.Move.performed += Move();?

    To make this even more confusing, the input debug logger shows all of my passthrough wasd pressed and values correctly, I'm simply not receiving the message in the player controller. The input system DOES know I'm pressing mapped buttons.

    Then, other times, as I said everything works as expected. If I restart my computer the issue is resolved for about one hour before it starts to happen again. At which point, the only way to continue testing or working is to restart the system because there is no other way to move my character.

    Why would restarting my computer be the only fix to this issue? I'd really love to stay with the times and keep my project open for easy porting in the future, I don't support a gamepad yet but I'd like to and this has been a really disheartening and stressful experience lol.

    Edit: I'm sorry for the necro, I've just seen above the explanation of time drift and that sound like my exact issue. I'm using 2020.3 so that would explain why I'm still stuck in the past.
     
  16. jwinn

    jwinn

    Joined:
    Sep 1, 2012
    Posts:
    88
    I'm experiencing this issue with 2021.2.2f1, and a recently new install of the Input System package. Has the fix been released yet?
     
  17. Unsettled

    Unsettled

    Joined:
    Dec 10, 2017
    Posts:
    1
    Same here, it's quite annoying.

    EDIT: luckily, @owenlshinyshoe 's fix is working for me. Maybe we can use it as a workaround at least for now...
     
  18. andrew_oc

    andrew_oc

    Unity Technologies

    Joined:
    Apr 16, 2021
    Posts:
    77
    Sorry about the delay on this. The fix is in version 2021.1.28 and 2020.3.22 now. There was an issue with the 2021.2 backport, but that has been resolved and so the next release should have the fix included.

    @caliberbeats that sounds like a potentially different issue because restarting the editor should have resolved it. We'd really appreciate a bug report for that one, if the new fix doesn't help (Unity Editor -> Help -> Report a bug).

    Nope, you'll get one performed event when the key is pressed, and another when it's released. Passthrough is really just for actions that have multiple bindings where you want to bypass the multiple control disambiguation logic https://docs.unity3d.com/Packages/com.unity.inputsystem@1.1/manual/Actions.html#action-types. If you just want to know if an action is active, you could switch to using actions.Player.Move.IsPressed().
     
    CykieProductions and NotaNaN like this.
  19. adslitw

    adslitw

    Joined:
    Aug 23, 2012
    Posts:
    275
    I'm having a similar issue - however I tried using the old input system too and I'm having the same problem there, so I think it might be a more fundamental problem. Inputs are sometimes being missed, so sometimes a key press isn't registered, and sometimes a key release isn't registered (so Input.GetKey returns true even though the key has been released). A clue might be that if you move the mouse then the key incorrectly being registered as pressed is 'released'.

    I'm on 2021.2.2, on an M1 Pro MacBook. The bug report no. is #1381681if you want to have a look @andrew_oc .
     
  20. azmi_unity

    azmi_unity

    Joined:
    Dec 13, 2020
    Posts:
    61
    Still having this issue in Unity 2021.2.3f1, Input System 1.1.1.

    The above hack fixes it for me.