#move_and_slide next to wall returns collision

1 messages · Page 1 of 1 (latest)

mossy parrot
#

Hey, I'm using move_and_slide for 8-directional top down movement. If i walk all the way to a wall until i touch it, then move in parallel to it, each move_and_slide call returns true (as in colliding with the wall).
Can't really find any way to get rid of this behaviour, and running pretty much default settings on all objects except motion_mode = MOTION_MODE_FLOATING on the player.
How are you guys solving this?

#

Might be related to this issue in the image above, this block is moving right, and a collision is triggered as soon as it starts to move next to this corner

if i were to resize all colliders to 15.9999 instead of 16, this would probably go away, but that's not really an ideal solution

mossy parrot
#

To rephrase it,
all rectangles are 16x16
If A is at 0,0 and B is at 0,16, i dont expect them to collide (unless moving toward each other), but they do

#

Making every single collider 15.999999 solves this issue, but will cause issues when i check if a certain point is on the ground or in a wall, as that position could be in the tiny gap if its off by .00000000001
For that reason, I cannot consider this to be a solution

mossy parrot
#

Bump

mossy parrot
#

Bump

wild pilot
#

can i ask why do you not want it to return true if its colliding to the wall? sounds like proper behavior to me

#

if you touched the wall once then move parallel to it, you are still touching the wall until you move away

#

actually nevermind, i just realized what the behaviour is lmao

#

can you turn on collision boxes in debug menu and share the shapes?

mossy parrot
#

well you can't really see the tilemap collider

#

but the little guy to the left walks like this

if move_and_slide():
stop()

#

once he's hit a wall he will be stuck there forever, even if trying to walk away from the wall, move_and_slide will see a collision

#

@wild pilot

#

have tried to change motion mode and deselected all floor layers in the characterbody2d node but there's no difference

wild pilot
#

strange, is it possible your "collision tilemap layer" has some ghost tiles

grave sentinel
#

Maybe you can instead of stop() tell him to change direction?

wild pilot
#

Yeah I think if you say stop he will get stuck there forever, since there is no way to get away after you stop

#

Why do you need to stop?

#

Any gameplay reason?

#

You can just have move_and_slide() and that'll work fine, you'll be able to change directions

mossy parrot
#

Stop is my own function that selects a new direction after a certain time. I'm experiencing the same issue with all my objects though, not just this enemy

#

And i'm having the same issue against regular static bodies, not just tilemaps

#

The reason why this enemy gets stuck is that even if the new direction is north, the next move_and_slide call will return a collision and stop again

#

@wild pilot @grave sentinel

#

If this was my own engine with AABB collision only, the error would likely be due to checking bounds with >= and <= instead of >= and <
But of course given that this is a more complex collision checker with rotation and stuff, i have no idea

#

Can't test atm but i dont think move_and_collide has the same issue

wild pilot
#

Can you show us the "stop" function?

mossy parrot
#
extends CharacterBody2D

class_name BasicEnemy

const SPEED = 16.0
var direction = Vector2(-1,0)
var state = "waiting"
@onready var sprite = $AnimatedSprite2D

# damage blinking variables
var damage_blink_times := 0.0
var damage_blink_speed := 6.0

func start_random_walk():
    state = "walking"
    var v = randf()
    if v < .25:
        direction = Vector2(-1, 0)
        sprite.animation = "walk_right"
        sprite.flip_h = true
    elif v < .5:
        direction = Vector2(1, 0)
        sprite.animation = "walk_right"
        sprite.flip_h = false
    elif v < .75:
        direction = Vector2(0, -1)
        sprite.animation = "walk_up"
        sprite.flip_h = false
    else:
        direction = Vector2(0, 1)
        sprite.animation = "walk_down"
        sprite.flip_h = false
    sprite.play()

func hurt(attacker: Player):
    print("i'm hurt")
    velocity += (global_position - attacker.global_position).normalized() * 100
    damage_blink_times = 3
    
func stop():
    state = "waiting"
    sprite.frame = 0
    sprite.stop()

func _physics_process(delta: float) -> void:
    if damage_blink_times > 0:
        damage_blink_times -= delta * damage_blink_speed
        if damage_blink_times <= 0 or fmod(damage_blink_times,1) > 0.5:
            sprite.modulate.r = 1
            sprite.modulate.g = 1
        else:
            sprite.modulate.r = 2
            sprite.modulate.g = 1.5
    
    if state == "waiting":
        velocity = velocity.move_toward(Vector2.ZERO, delta * 300)
        if randf() < .01:
            start_random_walk()
    elif state == "walking":
        velocity = velocity.move_toward(direction * SPEED, delta * 300)
        if randf() < .001:
            stop()
    
    if move_and_slide():
        stop()
    
#

i remember now that i fixed my moving platform corner colliding (see first image) by using move_and_collide instead of move_and_slide

#

but my player still has issues, i show a "pushing" animation whenever move_and_slide returns true

grave sentinel
#

what happens if you just call move and slide() ?

mossy parrot
#

if i walk north up the wall, then go right, the player will play the pushing animation as i move alongside (not into) the wall

mossy parrot
#

so "works" but i want to be able to see if i walk into a wall

grave sentinel
#

you can use move_and_collide which returns a KinematicCollision2D object that should let you get where the collision occurs

#

use it in conjucntion with the moving direction to tell if it should attempt to push

mossy parrot
#

i absolutely could just write it off as the move_and_slide function not being production ready and instead use move_and_collide

#

but i want the sliding behaviour

#

so i'd have to reimplement it

grave sentinel
#

you can use get_slide_collision for the same KinematicCollision2D object

#

youll have to know the index of the collision tho

mossy parrot
#

absolutely, i've looked into those but i don't see them containing a clear distinction between colliders i've pushed against vs colliders that are just adjacent

#

so i could in theory test each collider in some way to see if there was an actual collision - but it would be quite messy

#

it does feel like something is broken though, i can't see how a "collision" behind you would ever be as relevant as you smashing into an object

grave sentinel
#

Can you simplify the wanted behavior for me? I think I'm missing something.

mossy parrot
#

I want to be able to move_and_slide and know when i hit a wall

I don't consider starting the move next to a wall to be a collision

#

i expect the top scenario to return true and the bottom to return false

#

both return true

#

i also don't expect this to return true (collision), assuming the velocity y component is 0, but it does

grave sentinel
#

you could have a separate collision area that is only in the forward direction that detects frontal collision

#

or expand it to the 4 cardinal directions and only check them when you are moving in that direction

mossy parrot
#

Sure, it would require me to switch the colliders off, move and then instantly switch them on again though (so that things which collide with the player work properly).
But having to do this for all objects isn't fun. Might be more worth it to ditch godots collision system entirely at that point

grave sentinel
#

I would make it so:

    if right collision area is colliding:
      stop```
#

or if using the signal when an area or body enters the Area2D:

    if moving right:
      stop()
mossy parrot
#

If using area2ds, they'd have to extend outside the regular collision box though

#

Causing collisions to be reported too early

grave sentinel
#

depends on when and how you react to the collision. You can use a "semaphor" variable to tell you that collision has happened before trying to keep moving in that direction.

mossy parrot
#

made a helper to solve this for my use case @grave sentinel @wild pilot

func move_and_slide2() -> bool:
    if move_and_slide():
        for i in get_slide_collision_count():
            var collision = get_slide_collision(i)
            if collision.get_normal().dot(velocity) < 0:
                return true
    return false
#

imo this should be an option in characterbody2d

wild pilot
#

Do your enemies move in fixed tiles or freely?

mossy parrot
#

freely

wild pilot
#

Ahh ok

mossy parrot
#

what's the proper channel for submitting feature requests?

wild pilot
#

#📥┃github-proposals

mossy parrot
#

thanks!

wild pilot