godot: Camera2D limits doesn't work well if limit_smoothed is enabled

Godot version

3.4.2 stable

System information

Windows 10, GLES2, Intel HD Graphics 610

Issue description

Since godot version 3.4.1 the camera limits stop working properly if limit_smoothed is enabled, while in previous versions it never gave problems. When starting the scene, you notice a movement of the camera as if it was being moved:

https://user-images.githubusercontent.com/30391210/147719762-52a1872f-0db4-495f-be4c-41a1abe9b6ef.mp4

And sometimes when setting certain limits, the camera moves slightly.

In 3.3.3 works fine:

https://user-images.githubusercontent.com/30391210/147719778-4460e59f-c7de-482e-9e9f-0b5d74b13d09.mp4

But this happens with 3.4.1 and 3.4.2

https://user-images.githubusercontent.com/30391210/147719804-4fffaf9e-42c5-4f31-9702-fa1da4f1e101.mp4

Steps to reproduce

Enable limit_smoothed and smoothing_enabled to true on Camera2D.

Minimal reproduction project

TestCamera2DLimits.zip

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 22 (16 by maintainers)

Most upvoted comments

@dannygaray60 Yes, this is the expected behaviour. If you change the camera position and you don’t want it to scroll to the new position, then you call reset_smoothing(); exactly as you’re doing.

Note: If, as you suggest, you make the Camera2D a child of your player or you simple place the Camera2D where you want it to start, then it enters the SceneTree at the global_position as defined in the Inspector. Since there is no change in position, there will be no scrolling, because there is nowhere to scroll from. When you set the position in _ready() (and don’t use reset_smoothing() it scrolls from the position defined in the Inspector.

You are right in that this fix should be included in the release notes; since you’re probably not the only one that’s used to the previous broken behaviour.

Just as an aside, I don’t know whether it’s related, I haven’t really been following this topic, but just to mention that in this functionality:

real_t c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;

c is not capped to 1.0. i.e. c can end up being larger than one at low frame rates / tick rates with large smoothing values, which looks like it would cause oscillations. Low frame rates might be seen especially at startup.

May I make a suggestion? Probably, it is better to rename reset_smoothing() to snap_to_position(). Also, unbind it from the smoothing property and make it work whether smoothing is enabled or not.

We can’t rename methods anymore throughout 4.x, now that 4.0 is in release candidate stage.

when smooth is activated to a 2d camera, at the start of the scene the camera2d moves to its starting point (the player’s position)

@dannygaray60 This is the expected behaviour. It was a bug that the camera did not scroll smoothly to its new position. If you want the camera to immediately snap to the position and not move there smoothly, you need to call reset_smoothing(). With #63083, calling reset_smoothing() after adjusting the camera properties in _ready() now works correctly. If not, please let me know and provide a new MRP.

Note: #63330 captures some of the remaining bugs with limit_smoothed disabled and setting the camera properties in _ready().

Regardless of what is done further, for now this should be documented.

So it looks like the prescription (for now at least) would be to call them in a specific order (first reset, then force update), rather than calling one or the other or force → reset.

Might be worth considering whether we should A) take the suggestion you mentioned (update then fix camera pos then update again), B) document this specific way of doing it, or C) have a new method specifically for forcing a camera into its limits immediately with no smoothing… or, D) another suggestion I haven’t thought of.

Unfortunately I’m not sure of the rationale for the above-mentioned PR (#50935); maybe @Vitika9 can provide some insight as to exactly what changed in this PR and perhaps what the best resolution is now.

As calling force_update_scroll() right before calling reset_smoothing() was giving the intended behavior in #50807, therefore _update_scroll() was made to be executed first. In the case which is mentioned in this issue, the camera is already at it’s limit(top and bottom). The issue is getting resolved by calling reset_smoothing() twice because in this case _update_scroll() needs to be executed after setting smoothed_camera_pos or this can also be achieved by calling force_update_scroll() after reset_smoothing().

https://user-images.githubusercontent.com/79760854/148373873-2ea9c712-626f-4f17-a655-c0f8388f0089.mp4

May be we need to call _update_scroll() both before and after setting smoothed_camera_pos in the reset_smoothing() method, sorry if it sounds weird.