Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera2D does not work properly when added as child of a moving node with smoothing off and smoothing speed greater than 0 #16918

Closed
adeluiz opened this issue Feb 22, 2018 · 18 comments
Milestone

Comments

@adeluiz
Copy link

adeluiz commented Feb 22, 2018

Godot version:
3.0 stable

OS/device including version:
tested on win 10, android and osx

Issue description:
When you create a simple camera as a child of the player, just to follow it, if you have disabled the smoothing but there is a speed greater than 0, the sprite does some strange flickering

Seems related to #14545 but it has been closed without solution.

Steps to reproduce:
To isolate the bug I've create a simple project, with just a camara that follows the player. The player has an increased velocity with time and it goes increasingly off-centered. Just run it and watch. And after that, set the smoothing velocity to 0 and run it again (it goes centered as it should be).

Minimal reproduction project:
Due to the incorrect use of _proccess, I've uploaded a new one that moves a sprite

Camera2dBug.zip
Camera2dBugV2.zip

@adeluiz adeluiz changed the title Setting Camera2D smoothing off does not work properly Camera2D does not work properly when added as child of a moving node with smoothing off and smoothing speed greater than 0 Feb 22, 2018
@eon-s
Copy link
Contributor

eon-s commented Feb 23, 2018

Looks like the classic jitter issue at first glance but the effect here disappeared completely when I changed the (incorrect) use of _process to _physics_process (because it uses a move_and_collide).

@adeluiz
Copy link
Author

adeluiz commented Feb 23, 2018

It is not just because the node type or the incorrect use of _process. I've just change the node type to Sprite and using this script to move the node and the bug it is already present (Camera2dBugV2.zip):

func _process(delta):
position = position + Vector2(delta*elapsed,0)
elapsed += delta*600

@eon-s
Copy link
Contributor

eon-s commented Feb 23, 2018

Ok, then may be the camera update bug, and that was already fixed by #15060 (which may need to be cherry picked for 3.0.1, ping @akien-mga ).

Try this on your script if you want to use a workaround until the proper fix is implemented on 3.0

func _process(delta):
  position.x += delta*elapsed
  elapsed += delta*600
  #is like a manual camera
  var screen_size = Vector2(270, 480) #get this from viewport or settings  
  get_viewport().canvas_transform.origin = -position + screen_size / 2

@adeluiz
Copy link
Author

adeluiz commented Feb 23, 2018

Thanks a lot, but everything works ok if I set the smoothing speed to 0 (I just have to remember it when I create a new camera)

@adeluiz
Copy link
Author

adeluiz commented Feb 23, 2018

I've checked again, and after setting the smoothing speed to 0 it works ok, so it doesn't seem related with #15060 but with smoothing being used even when smoothing was disabled

@KoBeWi
Copy link
Member

KoBeWi commented Apr 29, 2019

I tested the reproduction project in 3.1 and seems like node gets off-centered both when smoothing speed is 0 and when non-0.

@KoBeWi
Copy link
Member

KoBeWi commented Jul 14, 2020

@adeluiz Can you still reproduce this in 3.2.2?

@adeluiz
Copy link
Author

adeluiz commented Jul 14, 2020

Tested on a new Windows computer with a brand new 3.2.2 stable godot and the node get off-centered with smoothing speed greater than 0 and with the workaround (speed = 0). I've even tried to put an enormous smoothing speed, but nothing changed. The camera cannot follow the sprite. Sometimes there is a jitter and the camera catches the sprite if the speed is low, but with a forced high speed on the sprite, the sprite gets off centered as it speed increase).

If I sets the sprite position on _physics_process, everything work as expected.

So if I'm not wrong there are two different options:

  1. If you have to set the sprite position only on the _physics_process, please make it impossible to set on _process (throw an error or so)
  2. The bug is still present since we are allowed to set the sprite position wherever we need, but camera produce jitters if you do it on _process (this is very annoying for beginners and almost made me quit from use Godot)

@KoBeWi
Copy link
Member

KoBeWi commented Jul 14, 2020

the node get off-centered with smoothing speed greater than 0 and with the workaround (speed = 0)

So that sounds like a different issue (because the original was that smoothing speed causes smoothing even when disabled).

@adeluiz
Copy link
Author

adeluiz commented Jul 14, 2020

I don't know. Maybe same bug, maybe my guess (about smoothing) was wrong. I have tried something new and it is funny. I have changed the script on the sprite:

extends Sprite

var dir = -1

func _ready():
	pass

func _process(delta):
	position  = Vector2(dir * 30  + dir * randf() * 10, 0)
	dir = -dir

	pass

That makes the sprite never to be on the center of the camera. But if you change the _process for _physics_process, it is always on the center

@adeluiz
Copy link
Author

adeluiz commented Jul 14, 2020

Here is the new camera jitter godot example project.
I've added a sibling sprite, and it moves with the parent as it is expected, but the camera... the camera is never where it should be. Unless you move the sprite on the _physic_process, then everything work as expected.
Camera2dBugV3.zip

@eon-s
Copy link
Contributor

eon-s commented Jul 14, 2020

Disabling VSync, the sprite shakes a little but stays on the center up to nearly 20k pixels/sec, then offsets a bit and start with the big jitter.

The Camera2D process mode does not change anything on the normal behavior of the OP example.

@adeluiz
Copy link
Author

adeluiz commented Jul 14, 2020

Please try the V3. It is really weird. To me it shows like everything works something like:

· all process stuff is done in a thread(atomic, protected, no render while process is done)
· render on another thread
· all physic_process stuff and camera position movement on another threat (atomic, protected)

If godot works like that, on _process there should be no movement stuff at all (only state logic or so), otherwise jitter should happens for sure, and smooth movements could be difficult to achieve. Everything that result in something that moves should be on _physic_process if I'm not wrong

@adeluiz
Copy link
Author

adeluiz commented Jul 15, 2020

I have uploaded a GIF capture of Camera2dBugV3 to see the effect of the camera being never centered on the sprite when moved with _process (remember that the camera is a sibling of the sprite, so the logic says that it has to follow the sprite on every frame, as the sibling sprite does):

LateralScrollerV3

I move the sprite to the left and right on every frame and the camera is not able to follow the sprite (the camera position seems to be updated a frame later than the sprite or the other sibling sprite).
But if I change the _process for _physic_process, it is always centered (see it on the next gif, you only see two sprites that doesn't seem to move on screen, always camera centered, as intended).

LateralScrollerV3physics

@KoBeWi
Copy link
Member

KoBeWi commented Jul 15, 2020

Not sure what to do about this tbh. I tried the camerabugv3 and noticed that the camera has a process_mode property. Of all combinations, the movement isn't jittery when process_mode is Idle (default) and node moves in _physics_process(). Also calling force_update_scroll() on camera each frame seems to help too.

I looked into Camera2D's source and it seems to update scroll on internal process. I guess the jitter is due to desync in script process and camera process. The interesting bit is this:

case NOTIFICATION_TRANSFORM_CHANGED: {
if (!is_processing_internal() && !is_physics_processing_internal()) {
_update_scroll();
}

This basically means that if internal processing is disabled, the scroll updates on transform change, which means it's done just when the camera moves. And indeed, when you use camera.set_process_internal(false) the jitter is gone.

Either this should be documented or when smoothing is disabled we should always update scroll.

@eon-s
Copy link
Contributor

eon-s commented Jul 15, 2020

Position changes in _physics_process is only for things that use physics bodies, it should not affect the camera behavior.

Maybe expose Camera.set_process_internal on the inspector, on project settings, or bind it with the camera process mode?

@KoBeWi
Copy link
Member

KoBeWi commented Jul 15, 2020

or bind it with the camera process mode?

Looking at the code, something like PROCESS_IMMEDIATE, which disable all internal process, would make the most sense. The source code for smoothing and processing looks weird.

@akien-mga akien-mga added this to the 3.3 milestone Apr 28, 2021
@akien-mga
Copy link
Member

This was fixed in #46717.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants