0 votes


I am trying to make a project that implements physics that resembles Super Mario Galaxy, where someone can walk around a planet perpendicular to where they are standing and, and they can jump to other planets. As research, I read this article and this video, but I have no idea how to actually implement the system. Below is an image of a sample level that I want to make. I eventually want to add non-sphere planets. The code I have for the ray (called "Gravity Calculator") and the Player are shown below. I don't know if I have to use look_at() or something, but I honestly have no idea. Any help is appreciated :)

Two StaticBodies with a KinematicBody
Raycast (Gravity Calculator) Code:

extends RayCast

onready var player = get_node("../../Player")

#func _ready():
#   pass # Replace with function body.

func _process(delta):

func nearest_planet():
    #Get all planets and assume the first one is the closest
    var planets = get_node("../../Planets").get_children()
    var nearest_planet = planets[0]

    # Compare the distance from the assumed nearest to the other planet(s)
    for planet in planets:
        if planet.get_translation().distance_to(player.get_translation()) > nearest_planet.get_translation().distance_to(player.get_translation()):
            nearest_planet = planet
    # Return the nearest planet
    return nearest_planet

func ray_to_planet():
    #Get the relative distance from the player to the nearest planet and set the ray to cast there
    var raydestination = nearest_planet().get_translation() - player.get_translation()
    return get_cast_to()

func ray_normal():
    return get_collision_normal()

Player Code:

extends KinematicBody

onready var ray = get_node("Gravity Calculator")

var velocity = Vector3(0,0,0)

var gravity = 3

func _ready():
    pass # Replace with function body.

func _process(delta):
    move_and_slide(velocity, ray.get_collision_normal(), true)

func _physics_process(delta):
    velocity.y = velocity.y - gravity * delta
    velocity = move_and_slide(velocity, Vector3.UP, true)

func _move_by_input(delta):
    if Input.is_action_pressed("move_forwards"):
        velocity.z -= 1 
    if Input.is_action_pressed("move_backwards"):
        velocity.z += 1 
    if Input.is_action_pressed("move_right"):
        velocity.x += 1 
    if Input.is_action_pressed("move_left"):
        velocity.x -= 1 
asked May 22 in Engine by Dgoat (15 points)

Try looking on github. I downloaded a couple of demos when researching the same ideas, I know one of them used raycast to get the normals of the objects. I'll check if I can find them.

I saw this one, but haven't tried it.

I downloaded this one, I think it's FPS, haven't opened in a long time.

Downloaded and checked, moves a character model around a planet, has jump and collision.

Hope they help you figure out how it works, I've checked the codes, but it was a while ago.

Hey! Thanks for the links. The third one seemed to be the closest to what I was trying to do. When I added the code, it got the "walking around the planet" mechanic working, but whenever the player tried to switch planets, it stopped working, even after editing the code to make the ray point towards the nearest planet. You can see the code in action here. Do you have any ideas?

1 Answer

+1 vote
Best answer

I put together a small demo scene based on the third link I suggested to you.


You change planets by jumping on the pads and pressing "c".

To stop the player getting stuck on a planet, I disable the player rays and colliders. To point to a new planet, I set planet_position to the Vector3 of the target planet.

I added a cube planet to test extra shapes.

Transitions between planets and sides of the cube are not smooth and polished, but the essentials are there.

Hope it helps.

answered May 24 by DamonR (93 points)
selected May 25 by Dgoat
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.