+2 votes

Hey everyone! Thank you for clicking on my question. This is my first post on this website, so feel free to leave some constructive criticism regarding my post, if you'd like.

I'm relatively new to Godot and I have recently started my first 3D project. I'm making a shooter, where the player is defending an objective against waves of enemies. This takes place on a planet with "realistic" gravity. I watched and read plenty of tutorials, but I could not find answers to my question.

This is the problem I ran into: I want to apply current_gravity to the player in a way that it always pulls the player toward the center of the planet, but I don't know how to do it.

Here is a short video of my project so far: https://youtu.be/yJkafqUAZnU

extends KinematicBody

Variables.

#Physics
var speed = 20
var acceleration = 20
var earth_gravity = 9.8
var current_gravity = earth_gravity
var MAX_SLOPE_ANGLE = 40
var fall = Vector3()

#Jump
var jump_power = 200
var jump_pressed = 0

#General
var mouse_sensitivity = 0.05
var is_on_ground = false

#Nodes
onready var Head = $Head

This rotates the player or the player's head when the mouse is moved.

func _input(event):
    if event is InputEventMouseMotion:
        rotate_y(deg2rad(-event.relative.x * mouse_sensitivity))
        Head.rotate_x(deg2rad(-event.relative.y * mouse_sensitivity))

.

func _process(delta):
    #Declares a variable that serves as the up vector
    var up = get_gravity_dir_vector()

This checks if player is standing on ground.

    if $GroundChecker.is_colliding():
        is_on_ground = true
    else:
        is_on_ground = false

This rotates the player toward the center of the planet. I copied it from one of Pigeonaut's videos on Youtube.

    transform = transform.orthonormalized()
    if transform.basis.y.normalized().cross(get_gravity_dir_vector()) != Vector3():
        look_at(Global.world_node.get_node("Planet").global_transform.origin, transform.basis.y)
    elif transform.basis.x.normalized().cross(get_gravity_dir_vector()) != Vector3():
        look_at(Global.world_node.get_node("Planet").global_transform.origin, transform.basis.x)

This part should apply gravity to the player, when they are not standing on ground.

    if not is_on_ground:
#       fall.y += current_gravity * delta  <==  This works on a flat surface, but not on a sphere. I tried rotating fall, but it didn't work.

This part should make the player jump.

    if Input.is_action_pressed("jump") and is_on_ground:
#       fall.y = jump_power <== This also works on a flat surface, but not on the planet.

This handles player movement on the surface of the planet.

    var vel = Vector3()
    if Input.is_action_pressed("move_forward"):
        vel += transform.basis.y
    if Input.is_action_pressed("move_backward"):
        vel -= transform.basis.y
    if Input.is_action_pressed("move_left"):
        vel -= transform.basis.x
    if Input.is_action_pressed("move_right"):
        vel += transform.basis.x 

    vel *= speed
    vel = move_and_slide(vel,get_gravity_dir_vector(),0.05,4,deg2rad(MAX_SLOPE_ANGLE), false)

This part is supposed to move the player vertically.

    move_and_slide(fall, up) 

This calculates the up direction relative to the player's position on the planet.

func get_gravity_dir_vector():
    return(Global.world_node.get_node("Planet").transform.origin - transform.origin).normalized()
in Engine by (36 points)
edited by

1 Answer

+1 vote
Best answer

Here's realistic gravity my friend:

func newtonian_gravity(delta, obj_1, obj_2):
    obj_1.velocity += (obj_2.global_transform.origin\
        - obj_1.global_transform.origin).normalized()\
        * GRAVITY * obj_2.mass\
        / pow((obj_2.global_transform.origin.\
        distance_to(obj_1.global_transform.origin)), 2) * delta
    obj_1.move_and_slide(obj_1.velocity, Vector3.DOWN)

To run this, just make an array of your objects and call the method like so:

func _process(delta):
    for obj_1 in planets:
        for obj_2 in planets:
            if obj_1 != obj_2:
                newtonian_gravity(delta, obj_1, obj_2)

Give each object a mass value. Gravity is very weak so your planet will need a big mass like pow(10, 19). The const GRAVITY is 0.00000000000666726.

This will work for n body problems so you can make a solar system if you want or just a single planet.

Any issues, blame Newton. ;)

by (365 points)
selected by

Thank you so much for your help! :) it's all very clear now!

Glad it helped! I've subbed to your YT channel so if you post it in action I'll take a look.

Thank you so much for your help and patience, it works perfectly now!

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.