Topic was automatically imported from the old Question2Answer platform.
Asked By
mighty_monarch
EDIT - Never Mind - I didn’t google enough the first time. Apparently this is a known behavior, but I’d hesitate to call it expected or correct.
I have a KinematicBody2D scene with an AnimatedSprite child. Previously, in order to make the character face the opposite direction, I changed the scale of the AnimatedSprite to -1 if the character was facing that direction. However, I recently added a another child node with a RayCast2D and some Particles2D that always face forward, so I decided to change the Scale of the whole KinematicBody2D instead of the AnimatedSprite so that the Sprite and the RayCast2D/ Particles2D would be facing the correct direction.
This system works the same so far when the character is facing right (positive x scale) but exhibits strange behavior when the character is facing left (negative x scale). The whole character (Sprite and Particles) appears to flip back and forth horizontally each frame. Upon further inspection, I have narrowed the issue to when I call move_and_slide_with_snap and the end of my _phyisics_process method.
Immediately before I call move_and_slide_with_snap on the first loop facing left, my body’s scale is (-1,1) as I expect. However, when I return from that method call, both signs have flipped, and the scale is (1,-1). At the start of the next loop, I change just the x component of the scale to -1 (because the character’s state is facing left) and immediately before the next move_and_slide_with_snap call, the scale is (-1, -1) (I have never touched the y component of the scale.) Immediately after the move_and_slide_with_snap call, the scale is (1,1) and the cycle continues.
Should move_and_slide_with_snap have a side effect on the body’s scale? Is setting the body’s x scale negative not an appropriate way to flip the whole node and children horizontally? Does anyone have any insight here?
Yeach, you can do this. With separate boolean variable. I use what solution:
var changed_scale = false
func _physics_process(delta):
if Input.is_action_pressed("player_left"):
if (!changed_scale):
scale.x=-1.0
changed_scale=true
elif Input.is_action_pressed("player_right"):
if (changed_scale):
scale.x=-1.0
changed_scale=false
Why variable, not checking “scale”? Because “scale” isn’t properly represents real scale of object for some reason. And transform.get_scale().x does the same thing, I’m checked it recently.
Physics work properly, by the way.
Looks like in engine code, variable multiplie old value by new. I find something (116 line) in engine code, what maybe causes what, but I’m not sure.
UPD: I find a bit better solution. For better understanding read this tutorial from documentation.
var h_scale = true
func _physics_process(delta):
if <condition to change scale to left> && !h_scale:
<Node2D>.transform.x *= -1.0
h_scale = true
elif <condition to change scale to right> && h_scale:
<Node2D>.transform.x *= -1.0
h_scale = false
if str(<Node2D>.transform.x.x) == "-0": <Node2D>.transform.x.x=0
if str(<Node2D>.transform.x.y) == "-0": <Node2D>.transform.x.y=0
if str(<Node2D>.transform.y.x) == "-0": <Node2D>.transform.y.x=0
if str(<Node2D>.transform.y.y) == "-0": <Node2D>.transform.y.y=0
#<Node2D> - it's any node what you need to change scale