1

Currently, the enemies I made are able to "patrol" an area and change direction when they hit a wall. I would like to put them on floating platforms without them falling off, how could I do that?

Here is the code that makes them change direction when they hit a wall:

func _physics_process(delta):
    _velocity.y += gravity * delta
    if is_on_wall():
        _velocity.x *= -1.0
    _velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
BlindVI
  • 21
  • 3
  • what do mean by falling off? is it sideways or up and down jitter? – Anirudh Ganesh Jun 05 '21 at 12:11
  • @AnirudhGanesh Oh sorry, i should have specified. The game is a 2D side scroller and I want the enemies to turn around when they get to the end of a platform, instead of keep going and falling off. Hope what i'm trying to say is clear – BlindVI Jun 05 '21 at 12:16
  • add an empty game object at the end of the platform, have it coloured so you can identify them easily (you'll find this option in the inspector. when the charter collides with the object, flip em. – Anirudh Ganesh Jun 05 '21 at 12:23
  • @AnirudhGanesh Oh i had thought about doing something like that lol. I just thought that there would have probably been a function that made it possible to recognize an empty tile and make the entity able to act upon that information. Thank you for the tip! – BlindVI Jun 05 '21 at 12:26
  • You can do it on the physics object, using a RayCast2D or an Area2D to detect if there is ground ahead. See [How can i make a rigid body jump in godot without givign it the ability to fly](https://stackoverflow.com/a/67404421/402022) - I know you are not asking about RigidBody2D, but the RayCast2D and Area2D solutions I suggest to detect ground for a RigidBody2D there can very easily be adapted for this (just don't use to them to check directly down, but off center at one side, and of course you don't use apply_central_impulse, but change velocity). – Theraot Jun 05 '21 at 13:18
  • @Theraot the problem with a raycast approach is that you might hit walls and the ray cast would still detect the wall as ground and the character will end up running endlessly. Ray cast would work well for platforms with open ends. – Anirudh Ganesh Jun 05 '21 at 18:42
  • you can just include the enemy in a group "enemy" and add an Area2D on the edge of the floating platform with a signal "body_entered" and on the script include a code if body.is_in_group("enemy"): include the code for change direction. – EL.ALEX78UK Jun 08 '21 at 13:55
  • Excuse me @Theraot, but could you show me an example of how to use the RayCast2D to check if there's ground ahead? I haven't grasped on its function yet – BlindVI Jun 18 '21 at 20:07
  • @Theraot i've tried doing this but the enemy now stand still. Where am i supposed to place the raycast and what errors are in the code? `func _physics_process(delta): _velocity.y += gravity * delta if is_on_wall(): _velocity.x *= -1.0 _velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y if $RayCast2D.is_colliding() == true: _velocity.x *= -1.0 $RayCast2D.position.x *= -1.0` – BlindVI Jun 22 '21 at 12:52

1 Answers1

1

On OP demand, here is how I would set this up using RayCast2D.

First of all, the RayCast2D will be a child of the KinematicBody2D and we need to position it to the side and pointing down. Also make sure the RayCast2D is enabled. As seen here:

Godot window screenshot

And for the code I'm using this:

extends KinematicBody2D

export var gravity:float = 100
var _velocity:Vector2 = Vector2.RIGHT * 100

const FLOOR_NORMAL:Vector2 = Vector2.UP

func _physics_process(delta:float) -> void:
    _velocity.y += gravity * delta
    _velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
    if is_on_wall() or (is_on_floor() and !$RayCast2D.is_colliding()):
        _velocity.x *= -1.0
        $RayCast2D.position.x *= -1.0

To check for the hole, we want to verify that the RayCast2D is NOT colliding. If it is colliding, it means there is floor ahead. The check for is_on_floor is to avoid it changing direction in the air.

Also, I'm checking both conditions on a single statement. First to avoid repetition, and second because if there are two checks that can change the direction, and they both change the direction… The result is that it didn't change direction! Next frame it will try to change direction again, at infinitum. Any similar situation will result in the KinematicBody2D changing direction in place. It would appear to not move.

Finally, the reason why I do the move_and_slide before all the checks is because, is_on_wall and is_on_floor are updated when you call move_and_slide.


And this is the game running with collision shapes visible (debug option):

Game recording

As you can see, it changes direction both on a wall and on a hole.

Theraot
  • 31,890
  • 5
  • 57
  • 86
  • Thank you! In the end the code was fine, i had messed up the direction of the RayCast2D thinking only the tip had to collide. Also i didn't check a box that said something like "Area collide" so that's why it wouldn't work. Now everything's smooth, thanks again! – BlindVI Jun 23 '21 at 16:27