I'm obviously super-late, but this might help out others in the future. I had a similar problem and, for what's probably the first time in my life, I came up with my own solution!
It shares a little with avencherus's answer, but I admit I don't fully understand his code, so I can't point out the differences, other than that this is almost painfully simple.
Godot version 3.1.1 stable official.
Note: this is for when you aren't using a RigidBody(2D) or even
move_and_collide(), though who knows, you might be able to adapt it to fit those cases.
I use a vector,
velocity, and add it to
position after checking that it won't put the object inside another collider.
The idea is that you cast a ray the length, and in the direction, of the velocity vector. If it hits something, it means you'll be colliding in the next frame, so instead of
position += velocity, you
get_collision_point() and set
position = that (accounting for the object's size, since
position is in its center; this is crucial, because raycasts also usually start from the center, and if you fail to do this it won't work properly; if you've moved raycast origin, take that as the center).
Note 2: I've only tested this for gravity so far. This means I've only cast 1 ray, vertically. I'll update the answer once I've done more work on my character controller.
Here's the basic code. It's what I got so far. I avoided putting in a lot of variable definitions, as they're obvious and I wanted to it to be uncluttered.
# adding gravity
velocity.y += GRAVITY
# adding input movement
raycast.cast_to.y = height + velocity.y * delta
position = raycast.get_collision_point() - Vector2(0, height)
velocity.y -= GRAVITY
position += velocity * delta
$CollisionShape2D.shape.extents.y, set in
_ready(). My sprite (and collision shape) is a square.
velocity.y -= GRAVITY is to stop
velocity.y from increasing unceasingly, or else it will interfere with input movement later. Outright setting it to 0 messes things up, since our raycast depends on it.
For accuracy's sake, you'll need more than one ray, but the underlying code should be the same.
From my tests so far, this works when I've jacked
GRAVITY all the way up to 18000 — normally, it's only 50 — but fails at 19000 and onward. Do keep in mind this is gravity, so it's acceleration, meaning it boosts
velocity.y to ridiculous values in just milliseconds, as it increases by that amount every frame.
I don't know what breaks things at this point, but I probably won't investigate either, because I can't see any use-case scenarios for it; except for space sims, I guess, but those are way above my level.