+1 vote

I have an enemy character which walks around and switches directions when it bumps into a wall or cliff. It fires a laser in the direction it is facing if it sees the player character and has non-symmetric collision, so a simple

$AnimatedSprite.flip_h = true

won't cut it for switching the character's orientation.

This long and old issue thread seems to conclude that, due to a change (possibly a bug) that was introduced in the move from Godot 2 to Godot 3, using the naïve

scale.x = direction*scale.x

(where direction is 1 or -1 depending on whether the KinematicBody2D is facing to the right or left) won't work. From the thread, a mysterious workaround is to execute

scale.x = direction*scale.x * sign(scale.y)

whenever you reorient the KinematicBody2D. This works for the character itself, but the healthbar above the character's head flips and appears beneath the character when it changes direction. I can't seem to force the healthbar back above the character by fiddling with the Healthbar's scale properties.

I get that this may be a bug (in fact I think it certainly must be because, without ever modifying the KinematicBody2D's y scale one of its children is apparently getting a vertical reflection), but I feel as though many developers must have encountered something like this and found work-arounds.

Does anyone know a work-around I can apply to prevent this vertical flipping of the character's healthbar?

Godot version v3.2.3.stable.official
in Engine by (62 points)

1 Answer

+1 vote

As I understand, you are not supposed to mess with the scale property of physics bodies. I believe this is something that is aimed to be corrected in Godot 4, but for now I think there may be "safer" ways of accomplishing this task.

I have encountered similar issues, and a common work around is to have two collision objects, and to swap the objects depending on which direction the character is facing.
e.g

if facing_right:
    left_shape.disabled = true
    right_shape.disabled = false
else:
    left_shape.disabled = false
    right_shape.disabled = true

Or to cut down on lines, you could use something like a ternary statement:

left_shape.disabled = true if facing_right else false
right_shape.disabled = !left_shape.disabled

It's a bit messy, but might do what you're hoping for.

by (251 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.