0 votes

Working on a game where player can attach to walls, floors, and ceilings like a gecko. I've been trying to use moveandslide with an Area2D next to each surface tile to change gravity. But it's been tricky to get aligned and working and I'm afraid of the character disconnecting or the gravity impacting other objects.

How can I get the player character aligned to the different surfaces and moving along them reliably? Is there a simpler way?

in Engine by (18 points)

2 Answers

0 votes

Use Kenimatic body, use move and collide.

There is a few ways to do this, but you will have some pains in Godot because it doesn't use quaternions.

First way, switch Gravity.
This is the simplest way and Godot's Area nodes actually have properties to do this.

extends KinematicBody

export var GravityDirection = Vector3.DOWN
var GravityStrength = 9.8

func _physics_process(delta):
    var Gravity = GravityStrength * GravityDirection
    #Your character movement goes into velocity
    var Velocity = Gravity * delta
    move_and_collide(Velocity)

How can I get the player character aligned to the different surfaces and moving along them reliably?

The Godot manual shows a tutorial for using move_and_collide() to mimic move and slide: https://docs.godotengine.org/en/3.0/tutorials/physics/physics_introduction.html#move-and-collide

As for using it in your game, you will get the collision from moveandcollide().

extends KinematicBody

export var GravityDirection = Vector3.DOWN
var GravityStrength = 9.8

func _physics_process(delta):
    var Gravity = GravityStrength * GravityDirection
    #Your character movement goes into velocity
    var Velocity = Gravity * delta

    var Collision = move_and_collide(Velocity)

    if Collision :
        self.GravityDirection = -Collision.normal

This is the basics, it just works with the gravity, everything else is up to you.

by (1,443 points)
0 votes

For some reference, I got a similar mechanic to work in my game:, considering it's 2D: https://www.youtube.com/watch?v=oyosstz_-4E

Walking on walls involves movement code that ignores gravity, so it's a bit like platforming without the jumps. In fact, for me gravity ended up being a special case that I implemented as a separate movement state.

To detect walls I basically use a bunch of raycasts or intersection queries, and keep track of what directions the feet and forward vectors of the characters are. Knowing them in addition to jump direction also allows to decide how to position the character when it hits a surface. Then detecting a surface is done either with move_and_collider/slide or more raycasts.

This is a private-source project so I can't share code, but basically to move along the surface I advance the feet position by one frame, then raycast down from a small distance above (whatever "down" is relative to the surface, it's important to know). If I get a hit, I snap the feet there and reorient the character according to the hit normal. If I don't get a hit, there are several possibilities: either I dropped a sharp edge, in that case I either stop, or switch to gravity fall. Or, I hit a sharp wall. In the latter case, a raycast forward can help find back the surface. However I intentionally design my levels to avoid annoying cases like these :p
This video shows some debug visualisation: https://www.youtube.com/watch?v=1_Yi_vf6m9A
I had to face a lot more special cases but I don't remember them all right now, but one useful thing was to encapsulate "surface following" logic into a SurfaceTracker class, so I could easily focus on it and test it. My game has only one, but if your gecko has 4 feet you could use 2 or 4 SurfaceTrackers for each feet, depends on your game^^

Note that this was for a game where colliders can have arbitrary shapes (round turns, diagonals etc). If your game looks more like just blocks, you could also roll your own simplified collision code by using the tile grid.

by (27,956 points)
edited by
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.