godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.71k stars 20.12k forks source link

Stutter/Jitter and screen freezing in a simple 2D project #25162

Closed di-kang closed 4 years ago

di-kang commented 5 years ago

Godot version: Godot 3.0.6

OS/device including version: MacOS 10.14.1 MacBook (Retina, 12-inch, 2017) 1.2 GHz Intel Core m3 8 GB 1867 MHz LPDDR3 Intel HD Graphics 615 1536 MB (Also reproduced on multiple devices including PC and exported game on mobile and PC.)

Issue description: Any object that is moving seems to periodically stutter or jitter accompanied by screen freezing in a 2D project. And it seems to happen more frequently on devices with low processing powers or non-Windows devices.

Steps to reproduce: Create a new project with a KinematicBody2D or an AnimatedSprite or a RidiBody2D and modify position with move_and_slide() or set_global_position() or apply_impulse() after adding a Camera2D as a child node.(But it still happens even without the Camera2D.)

Minimal reproduction project: 3.1 Beta 2 ~Godot_Jitter.zip~ Improved Version by @Ploppy3


KinematicBody2D, _physics_process(), move_and_slide()

https://youtu.be/78S95yugRDk

extends KinematicBody2D
const SPEED = 75
var motion = Vector2()

func _physics_process(delta):
    if Input.is_action_pressed('ui_right'): motion.x = SPEED
    elif Input.is_action_pressed('ui_left'): motion.x = -SPEED
    else: motion.x = 0
    motion = move_and_slide(motion, Vector2(0, -1))
    print(delta, position)

AnimatedSprite, _physics_process(), set_global_position()

https://youtu.be/gdc6NOoWG4E

extends AnimatedSprite
const SPEED = 75
var motion = Vector2()

func _physics_process(delta):
    if Input.is_action_pressed('ui_right'): motion.x = SPEED
    elif Input.is_action_pressed('ui_left'): motion.x = -SPEED
    else: motion.x = 0
    set_global_position(get_global_position() + motion*delta)
    print(delta, position)

KinematicBody2D, _process(), set_global_position()

https://youtu.be/YVFtkbuyqEQ

extends KinematicBody2D
const SPEED = 75
var motion = Vector2()

func _process(delta):
    if Input.is_action_pressed('ui_right'): motion.x = SPEED
    elif Input.is_action_pressed('ui_left'): motion.x = -SPEED
    else: motion.x = 0
    set_global_position(get_global_position() + motion*delta)
    print(delta, position)

RigidBody2D, _physics_process(), apply_impulse(), camera smoothing on

https://youtu.be/MGMlhl0tPTA

extends RigidBody2D
const SPEED = 7
var motion = Vector2()

func _physics_process(delta):
    if Input.is_action_pressed('ui_right'): motion.x = SPEED
    elif Input.is_action_pressed('ui_left'): motion.x = -SPEED
    else: motion.x = 0
    apply_impulse(position, motion)

I may have amplified the jittering by using apply_impulse() like that but modifying the position of the object directly using set_position() didn't make much difference. EDIT: Changing the process mode of the camera to CAMERA2D_PROCESS_PHYSICS solved the severe jittering of rigidbody itself.


I'm about to sign a deal with a publisher with my game that I made with Godot and because of the jitter I might have to move all my codes to Unity. Time and cost to move all the codes put aside, I'm reluctant to switch to different engines because I really like the design philosophy of Godot and Godot itself.

I also noticed that in 3.1 'Physics Jitter Fix' option has been added in the settings menu ( https://twitter.com/reduzio/status/984783032459685890 ) but that doesn't seem to help solve the issue.

Ploppy3 commented 5 years ago

Did you try without spamming the console? It can have a pretty significant impact. As example: remove the print(...) line 15 of your character.gd

Edit: On my side, I can clearly see it stuttering with the print calls, and not without them.

di-kang commented 5 years ago

@Ploppy3 Yup I tried without it. I wish the solution was that simple... I really don't wanna switch to Unity.

Xrayez commented 5 years ago

This might work better when exported, maybe try to experiment with Vsync in project settings. If you have dual monitor setup with different refresh rate this could impact stuttering in my experience. In my case it would work smoothly on 1st monitor, while stuttering happens while debugging the game on 2nd monitor, for instance.

di-kang commented 5 years ago

@Xrayez I read comments on different threads about turning on or off Vsync making the issue disappear or at least less severe but in my case, it didn't make any difference. The only thing that seemed to make it less severe was setting physics fps to higher than 60.https://github.com/godotengine/godot/issues/17823#issuecomment-431084637 But it didn't make the issue disappear and the difference was negligible.

eon-s commented 5 years ago

@diiiiiiiii can you try with 3.1 beta? there were many fixes in KB2D, Camera2D and Viewport, also the Camera has a new update mode (physics) in the properties which may help on some cases.

di-kang commented 5 years ago

EDIT: Changing the process mode of the camera to CAMERA2D_PROCESS_PHYSICS solved the severe jittering of rigidbody itself.

@eon-s Yeah I've been testing with 3.1beta2. And it did fix the jitter of moving object itself when camera smoothing is on. But unfortunately overall stutter is still there.

eon-s commented 5 years ago

As a workaround while this is being investigated, the camera with smooth issue could be replaced by custom code to move the viewport and make a smoothing that moves and rounds positions on physics process.

Related issues (some comments may mention other workarounds):

2667

16918

17823

23758

eon-s commented 5 years ago

Wait, I think I have read it wrong, smooth enabled fixes some jittering?

sicienss commented 5 years ago

I am working in 3.1 beta 2, and thought I'd share my experience.

I notice periodic stuttering on my background when I am running in windowed mode in my native resolution (640x360), but it is perfectly smooth in fullscreen. There is a stutter about every half second.

I also notice that the FPS while windowed oscillates between 58 and 59, but while in fullscreen it is a smooth 60.

Changing the camera's process mode has no effect.

Not sure if this is related to the reported issue.

eon-s commented 5 years ago

Tested the sample project, got some stuttering on the background (Ubuntu, R5, godot 3.1b2), irregular and it do not seems to be related to physics, looks more like a floating precision issue because zoom is low, motion is also slow...

sicienss commented 5 years ago

I also tested the sample project (Window 8, Intel HD Graphics 4600, 3.1b2).

I also noticed stuttering on the background. For me, it was more pronounced and happened about every second. Commenting out the print() line didn't help.

When I put the test project in fullscreen, I did not notice the stuttering.

Tried to screen capture, but the quality isn't very good, so I'm not sure it'll be much help.

eon-s commented 5 years ago

I was playing a bit with refresh rates, with vsync off forcing fps to match the monitor (60 and 40) the stuttering was gone, could it be possible that the engine is not taking the correct vsync values or not applying it?

girng commented 5 years ago

i changed _physics_process to _process and removed print, seems like jitter is gone for me OS; w10, 64-bit, 144hz monitor (gtx 950)

if you are still having this issue and don't want to move to unity... i recommend using _process and custom camera movement underneath it (if the camera2d node is the culprit, however, it should work fine there's been some work on it lately)

and yeah if i run it using physics_process it's insanely jittery (non playable)

sicienss commented 5 years ago

@eon-s , I tried this as well, in both the sample project and my full-scale project.

I disabled vsync and hard-coded the FPS to match my refresh rate (60 Hz). It pretty much got rid of the stuttering!

I wonder why this is. As I mentioned before, when vsync was enabled, I never noticed the stuttering in full screen—only windowed. Could it be that vsync is working properly in full screen mode but not in windowed mode?

disable_vsync

force_fps

di-kang commented 5 years ago

RigidBody2D, _physics_process(), apply_impulse(), camera smoothing on

https://youtu.be/MGMlhl0tPTA

@eon-s Camera smoothing is enabled only in the last code example. And unlike the stutter of entire screen or objects, which occurs in all code examples, when camera smoothing is enabled the moving object(RigidBody2D, KinematicBody2D, etc.) itself jitters back and forth viciously. And changing the process mode of the camera to CAMERA2D_PROCESS_PHYSICS solved the jittering of moving object itself but not the overall stutter. And I'm sorry if I made any confusions. English isn't my first language.

Tested the sample project, got some stuttering on the background (Ubuntu, R5, godot 3.1b2), irregular and it do not seems to be related to physics, looks more like a floating precision issue because zoom is low, motion is also slow...

Since the issue remains even without the camera, I don't think it's related with zoom.


KinematicBody2D, _process(), set_global_position()

https://youtu.be/YVFtkbuyqEQ

@girng In the third code example, _process() was used instead of _physics_process(). I haven't tried the custom code for camera movement though. Yet again, it happens even without the camera.


@sicienss I read several comments in related threads about fixing fps and I tried fixing it to 60 and 40.(Whether Vsync is enabled or not didn't matter) And it seems like when fps is fixed to 40 or lower, stuttering happens a lot less frequently. But maybe it's because fps is too low and it becomes difficult to notice the stuttering. And also in my case, couldn't find a noticeable difference between full screen mode and windowed. But I'll test that again for just in case.

EDIT: Test: Fullscreen Test: 40Fps, Vsync-False Test: 60Fps, Vsync-False Test: No Camera2D Test: 40Fps, Vsync-False, No Camera2D

di-kang commented 5 years ago
screen shot 2019-01-21 at 03 16 32 screen shot 2019-01-21 at 14 08 06

(Fps has been fixed to 60 in the settings)

I'm not sure this is normal or even related to this issue but 2nd and 3rd process delta spikes happen when the object starts moving. Is it normal to see that kind of spikes in a simple project and everything has finished loading before the movement?

behelit2 commented 5 years ago

I'm having same problem diiiiiiiii is having in his move_and_slide use case.

2D project with kinematic characters Godot 3.0.6 Win10 64bit Intel i5-2550K CPU 16gb ram Geforce GTX 970

reduz commented 5 years ago

Just as a side comment, you can use move_and_slide in regular _process now in 3.1, this can fix many jitter problems of having to use it in _physics_process. Although this nowadays seems it's not much of a problem.

Also stutter is most of the time OS related. When you go full-screen, both OSX and Windows give your process more priority so it gets interrupted less. If you don't see stutter full-screen, it sounds like some background task is the culprit.

Also, removing the print, I don' t see any stutter at all in your demo under X11. On Windows, I see occasional stutter (background task most likely) when windowed and nothing at full-screen. This is perfectly expected.

behelit2 commented 5 years ago

@reduz I have seen the same results you have with X11, it runs flawlessly. However, I don't think it's wise to quickly blame the problem on background processes in Windows and OS-X. After all, 2D games in other engines/frameworks (Unity, XNA, etc) run flawlessly in Windows and OS-X without any noticeable stuttering. That tells me there is something those other engines are doing right, that Godot is doing wrong. Thus, it could be OS related, but also Godot related as well. Is my logic incorrect here?

eon-s commented 5 years ago

@reduz can you give more details about using move methods outside physics process? That may need to be documented and mentioned in tutorials too.

Ping @kidscancode @gdquest

reduz commented 5 years ago

@behelit2 I don't know. If you or anyone else wants to investigate, here is something I suggest trying:

Let me know if you see anything odd.

reduz commented 5 years ago

On Windows, If I force the priority of this demo above normal or high, stutter goes away completely too. I Wonder if other engines to do this somehow.

di-kang commented 5 years ago

@reduz I was about to write a similar point that behelit2 has addressed. Even my Mac is a very low powered machine, it runs simple 2D games quite well without any stutter, in full-screen mode or not. And this example project is way much simpler(almost empty) than those games.

On Windows, I see occasional stutter (background task most likely) when windowed and nothing at full-screen. This is perfectly expected.

So it's a bit difficult to agree with you on expected stuttering on simple 2D project like this when it's not on full-screen mode.

Also as I mentioned above, it happens on ios(including iPad pro) as well which handles Fornite without a sweat.(But to be fair I haven't tried the example project on iPad pro. Only my full game. I'm planning on testing the example project on iPad pro tomorrow or so.)

reduz commented 5 years ago

@diiiiiiiii I tried your demo on Windows on high priority and stutter goes away when windowed. Apparently changing the priority manually is possible on Windows:

https://forums.ogre3d.org/viewtopic.php?t=83225#p518528

I am not so sure it's possible in OSX, though.

eon-s commented 5 years ago

What about forcing high performance settings on the GPU? maybe godot is detected as a regular app and the OS optimizations try to reduce the resources used by the program.

reduz commented 5 years ago

@eon-s I dont think this is GPU related

reduz commented 5 years ago

@diiiiiiiii I raised the process priority on windows, apparently it can be set to above normal (not high or critical). This got rid of the stutter for me (though it still does a bit of stutter for 3/4 seconds after loading, then goes completely smooth).

If you can build from master and test, let me know if it helps. On unixes doing something like this is impossible (though I see no problems on X11). Maybe OSX has something similar, but I don' t know much about the platform.

I personally never seen jitter/stutter on Android or iOS. Please test this with Godot 3.1, which fixes some jitter issues in all platforms.

reduz commented 5 years ago

For OSX there seems to be a really strange OS bug in fullscreen and the fix is pretty hacky. It affects most engines and libraries. If anyone with OSX wants to investigate and try any of the solutions mentioned here, feel free:

https://github.com/glfw/glfw/issues/772

homarox commented 5 years ago

I have the same problem with a simple endless running game. I had the test on Linux, Window10 and Android devices (Samsung s6, Samsung Note 5, Xiaomi 6X) and try all ideas above, but it does not work for all test devices :( image

Shin-NiL commented 5 years ago

@homarox endless runner is the type of game where this issue is more noticeable. I remember to see it when I was prototyping a game some time ago.

homarox commented 5 years ago

@homarox endless runner is the type of game where this issue is more noticeable. I remember to see it when I was prototyping a game some time ago.

Does it have any best solution for this situation? FPS looks seem good, I also tried VisibilityEnabler2D to enable animation only node on viewport but not helpful. And it's happened more frequently when your game runs long time enough.

reduz commented 5 years ago

@homarox what version of Godot are you using?

homarox commented 5 years ago

@homarox what version of Godot are you using?

@reduz I am using Godot 3.1 Beta 2

reduz commented 5 years ago

Added this guide in hopes of getting better reports on these issues: https://docs.godotengine.org/en/latest/tutorials/misc/jitter_stutter.html

starry-abyss commented 5 years ago

For me this project on 3.1-beta2 on Win 7 runs sometimes smooth, sometimes jitters at different frequencies (but the frequency of jitter is kept for several seconds), but most of times it stutters about once in a second (either alone or together with jitter). By "sometimes" I mean that those cases are switched during the same one run of the game.

Increasing process priority doesn't seem to help.

I had an idea that this is the kind of error similar to camera jitter in pixel art games when the positions of everything is rounded to integer every frame (and the characteristics of jitter depend on things like camera settings and fractional part of player's position). But don't have a clear idea of how to prove or disprove this theory.

starry-abyss commented 5 years ago

Windows is known to cause stutter in windowed games. Stutter may be visible on Desktop Linux, [...] associated with [...] compositors.

I'm almost sure that this is about #19783, and think v-sync should be turned off automatically (by the engine!) when in windowed mode. But need more feedback to confirm.

reduz commented 5 years ago

While turning off vsync makes it smooth, this entirely because of brute force. This will make the game use a huge amount of CPU (and battery on laptops) so it should be avoided.

I still am not sure whether:

The source of stutter definitely does not come from Godot, but I wonder if anything else can be done from our side.

reduz commented 5 years ago

Well, in any case, we will soon see how this works in Vulkan, which does all the swapchain work manually.. should be easy to tell if anything is wrong there.

behelit2 commented 5 years ago

@reduz So... I'm not sure where you get the idea that Windows is a stutter prone operating system. It is the most common gaming OS for desktops and laptops. This is because most games, despite your apparent misconception, run really well for the most part. I do not understand why you won't consider Godot as a potential source for the problem.

I can play Starbound (a highly complex and sophisticated 2d game utilizing procedural terrain generation) for literally hours on end (in both windowed mode and full screen) without even the faintest hint of stuttering. I go to check the process priority, and it is set to normal. All manner of emulated 2D titles, from any 2D game system you can think of, run perfectly with no stutter (and have been doing so since 2001). Yet, simple 2D games in Godot with a single background layer exhibit frequent stuttering.

I don't mean to be offensive, but it really seems like your explanation of background processes and OS issues is avoiding a legitimate problem here. Cuphead, a game with insanely detailed 2D graphics, would not have sold millions of copies if it exhibited frequent stuttering in Windows. If you actually played many 2D games in Windows, you would realize that blaming background processes is barking up the wrong tree. I understand that solving this issue probably isn't going to be an easy fix. I understand this is something Godot has been struggling with for a long time. But this is a very real problem and sweeping it under the carpet by pointing your finger at the OS is not going to make it go away. As more users adopt Godot, more people are going to notice this, and eventually Godot will gain a reputation for being a terrible 2D game engine.

This is not an attack, but a heartfelt concern. I really like Godot. I have fallen in love with GDscript and I think the interface is extremely intuitive. I want to see it succeed. But this stuttering is like a thorn in it's paw...

starry-abyss commented 5 years ago

@reduz

While turning off vsync makes it smooth, this entirely because of brute force. This will make the game use a huge amount of CPU (and battery on laptops) so it should be avoided.

No, because besides turning v-sync off I also suggest to cap the framerate. This way the game would use the same amount of CPU. I see v-sync as a measure to fix vertical frame tearing, and I don't understand why it's taken for granted here that it is also an universal way to cap the framerate.

I recently tested the project in the other issue I'm pointing to, and turning v-sync off clearly helps on my PC, while still with framerate of 60!

I'm interested in testing different stutter/jitter demos too (Godot or not) and giving feedback. Maybe we should create a tracker meta-issue where all of those projects/issues are collected? (without the hot issue discussions, only pointers to issues and summary of what helped in each case) Also, I'm personally totally OK with it all dealed after 3.1 is released.

The source of stutter definitely does not come from Godot, but I wonder if anything else can be done from our side.

I agree, but if some setup makes smoothness for 90% of cases, IMHO it's in interest of Godot project to make it the default one.

That said, the issues we have are different ones with different causes, and some of them probably are very game-specific and can only be dealed with from the game's side. So I suggest dividing them and treating one by one instead of seeing them as one united unavoidable mess.

di-kang commented 5 years ago

@reduz I took a bit of time and tested in several kinds of settings. And the results were

Jitter fix in 3.1 did work very well. So I'm wondering, wouldn't it mean that there could be a bit more that can be fixed or optimized in Godot?

reduz commented 5 years ago

@behelit2 I don't know if this is a Windows problem or an OpenGL driver problem. It definitely is not a Godot problem for the simple reason that:

  1. It works fine full-screen, and in most other platforms
  2. Godot does absolutely nothing that could cause stutter in such simple demos. There is no code that can be checked becuase nothing platform dependent that could be causing this exists in the codebase.

Most games on Windows are DirectX games, where you have more control on how vsync is performed, so it is very possible this definitely is OpenGL related. This is why I ask anyone interested to try the same simple demo in Unity or another OpenGL based engine.

reduz commented 5 years ago

@starry-abyss Disabling VSync and capping FPS is a horrible idea. It's just wrong because you are relying on the system scheduler caling a delay() function, which has 3 problems:

VSync is designed to solve this problem and run your game as efficiently possible. It works using an interrupt directly from the GPU that unblocks your render thread at the very precise time it has to. It should never be turned off. The problem here is, in my opinion, either OS related or OpenGL (driver or wgl) related.

reduz commented 5 years ago

Again, we will see soon how all this works in Vulkan.

behelit2 commented 5 years ago

@reduz I disagree with your reasoning.

  1. It does NOT work fine full-screen. I tried diiiiiiiii's example in 3.1 beta 2 in full screen and the stuttering is clearly still present in Windows 10. Maybe not as severe as the video, but it's totally there. Maybe try doing 2-3 passes over the bars to see it, it's kind of a short example.

  2. I accept that you are a "game industry veteran with over 20 years of experience". But saying there is absolutely nothing that could cause stutter in Godot is hubris. Saying there is no code that can be checked, in any reasonable development setting, is ridiculous!

The Starbound example I quoted... Is OpenGL. It runs exactly the same in Linux as it does in Windows 10. Full screen or windowed, it runs for hours without a single stutter. I could probably quote a dozen similar examples where this is the case. Immensely complicated games that use OpenGL, that run multiplatform... Run without stuttering. We shouldn't have to "prove it" with example projects in other game engines... Because there are WHOLE GAMES where this kind of stuttering never happens.

I mean no offense. I hold you in the highest respect for your efforts with Godot. But at some point, reality has to hit! There are so many unresolved issues with 2D stuttering and the solutions I see are like a sledge hammer, when this clearly needs a scalpel.

Shin-NiL commented 5 years ago

Again, we will see soon how all this works in Vulkan.

Would not it be more interesting first to try to solve the current issues (like this one) before starting to work on new functionalities? What I fear is to repeat the same cycle that was the migration from OpenGL 2 to OpenGL 3 which for me, as user one old engine user, was very traumatizing.

DDru commented 5 years ago

In Unity3d, this problem occurs if you move the camera through Vector.Lerp. The camera does not have enough time for set position if the objects are moving. Helps use Vector.Smoothdamp.

Also many years ago I got this problems in BlitzBasic3d and BlitzMax on winXP, win7. Me helped the use of delta time together in vsync. Function move_and_collide use delta time? This line with delta time work perfectly on my win10: motion = move_and_slide(motion * delta, Vector2(0, -1))

reduz commented 5 years ago

@Shin-NiL change should hopefully be very minimal this time compared to 2.0 -> 3.0 migration. Most will stay as it is and it's mostly an internal rendering change rather than a full engine rewrite.

behelit2 commented 5 years ago

@reduz Okay... Now I feel bad. I just tested my main project in 3.1 beta 2, and I did notice a SLIGHT improvement in stuttering. It's less noticeable now, but still there.

However, I'm really excited that the intermittent jitter in Camera2D smoothing is fixed! It works perfectly now. I can report issue #17823 as resolved.

reduz commented 5 years ago

@behelit2 You are definitely misunderstanding me. What I mean is that whatever is causing the problem (IF there is a problem) is no longer in the platform-independent code in 3.1 (this was fixed), but must be something related to the platform-specific wgl code (the windows GL context management). Checking the wgl implementation I can't see anything strange or out of place.

Looking on the internet, I find people with similar issues using OpenGL but nothing seriously seems like a good fix either (suggestions range from disabling vsync to forcing flush before swapping buffers, all previously proposed).

Maybe the games you tried use these, but I think the stutter is not as bad as to justify anything like that (I see at much once small stutter per minute, even on a crappy computer), these fixes are overkill.