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?
#move_and_slide next to wall returns collision
1 messages · Page 1 of 1 (latest)
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
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
Bump
Bump
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?
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
strange, is it possible your "collision tilemap layer" has some ghost tiles
Maybe you can instead of stop() tell him to change direction?
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
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
Can you show us the "stop" function?
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
what happens if you just call move and slide() ?
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
well it won't stop until my randf check above makes it stop
so "works" but i want to be able to see if i walk into a wall
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
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
you can use get_slide_collision for the same KinematicCollision2D object
youll have to know the index of the collision tho
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
Can you simplify the wanted behavior for me? I think I'm missing something.
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
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
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
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()
If using area2ds, they'd have to extend outside the regular collision box though
Causing collisions to be reported too early
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.
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
Do your enemies move in fixed tiles or freely?
freely
Ahh ok
what's the proper channel for submitting feature requests?
#📥┃github-proposals
thanks!
You need to make a proposal on GitHub tho I believe