godotengine / godot

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

Setting Transform2D origin causes negative scales to flicker #93003

Open aekobear opened 5 months ago

aekobear commented 5 months ago

Tested versions

System information

Godot v4.2.stable - Linux Mint 21.3 (Virginia) - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3070 Ti (nvidia; 535.171.04) - 12th Gen Intel(R) Core(TM) i7-12700K (20 Threads)

Issue description

When using transform.origin to set the position of a Node2D in combination with scale.x = -1 to flip a Node2D, the Node2D rapidly flips back and forth, even though it should stay flipped because scale.x = -1 every frame.

I expect transform.origin in 2D to work the same as position in 2D and (within reason) transform.origin in 3D

Notes:

I know that transform.origin is not commonly used in 2D (tutorials and docs favor position), but the variable is accessible and documented, with no warning that it behaves differently or should be avoided. As someone who makes both 2D and 3D games, it's helpful for me to have these APIs match in situations where there's no reason for a distinction. I see transform.origin / position to be one of these situations where it should work similarly in 2D and 3D, with Vector2 vs Vector3 being the only meaningful difference

Steps to reproduce

func _process(delta):
  scale.x = -1
  transform.origin += Vector2.ZERO

Minimal reproduction project (MRP)

transform2d-origin-bug.zip

aekobear commented 5 months ago

Some more information: I was able to reproduce the flickering problem in 3D on Godot 3.0. I wonder if it was a bug which has been fixed for 3D but 2D was overlooked at the time

AThousandShips commented 5 months ago

Nite that negative x scales are not supported so unsure how this should be treated

aekobear commented 5 months ago

Nite that negative x scales are not supported so unsure how this should be treated

Ah interesting. The note says that scale.x = -1 will be converted to scale.y = -1; rotation = 180, and when I look at the remote inspector, I see that the node is flickering between

scale.y = -1
rotation = 180

and

scale.y = 1
rotation = 180

if I flip the node2D by setting scale.y and rotation instead of scale.x, the flickering doesn't happen. And if I use scale.x in conjunction with translate() or position, the flickering doesn't happen

Even though "scale.x = -1" is technically unsupported, this seems like the only edge case where the compatibility code doesn't work right. If it's fixable, I think that'd be a big win

AThousandShips commented 5 months ago

If I was to guess I'd say this likely isn't an edge case but rather the entirety of the limitation, it doesn't necessarily convert anything, I'd say it's more that there's no way to tell the difference with the way we encode 2D transformations, but investigating if there's a specific issue here, rather than just the broader limitation, is a good idea, but otherwise this would fall under that broader discussion about changes to the 2D core mathematics which has a lot of things to consider, which I can't find any ongoing discussion for at the moment

But I'd say that the approach would be to avoid using or relying on any behavior with scale.x == -1 because of the limitations and potential weird behavior in a case that's not officially supported