# Rigidbody-based Planetary Player Controller for Unity

When creating a player controller, gravity is usually applied in just one direction, which is down.

But what about gravity with a central point? This is a job for the planetary walker.

A planetary walker is a type of controller that allows the player to walk on a spherical object (just like the planets), with the center of gravity being in the center of the sphere.

## Steps

Below are the steps to make a planetary rigidbody walker, with a central point of gravity in Unity:

• Open the Scene with your circular level (in my case I have a custom-made planet model and a custom Skybox in the Scene) • Create a new script, call it "SC_RigidbodyWalker" and paste the code below inside it:

SC_RigidbodyWalker.cs

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]

public class SC_RigidbodyWalker : MonoBehaviour
{
public float speed = 5.0f;
public bool canJump = true;
public float jumpHeight = 2.0f;
public Camera playerCamera;
public float lookSpeed = 2.0f;
public float lookXLimit = 60.0f;

bool grounded = false;
Rigidbody r;
Vector2 rotation = Vector2.zero;
float maxVelocityChange = 10.0f;

void Awake()
{
r = GetComponent<Rigidbody>();
r.freezeRotation = true;
r.useGravity = false;
r.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
rotation.y = transform.eulerAngles.y;

Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}

void Update()
{
// Player and Camera rotation
rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
playerCamera.transform.localRotation = Quaternion.Euler(rotation.x, 0, 0);
Quaternion localRotation = Quaternion.Euler(0f, Input.GetAxis("Mouse X") * lookSpeed, 0f);
transform.rotation = transform.rotation * localRotation;
}

void FixedUpdate()
{
if (grounded)
{
// Calculate how fast we should be moving
Vector3 forwardDir = Vector3.Cross(transform.up, -playerCamera.transform.right).normalized;
Vector3 rightDir = Vector3.Cross(transform.up, playerCamera.transform.forward).normalized;
Vector3 targetVelocity = (forwardDir * Input.GetAxis("Vertical") + rightDir * Input.GetAxis("Horizontal")) * speed;

Vector3 velocity = transform.InverseTransformDirection(r.velocity);
velocity.y = 0;
velocity = transform.TransformDirection(velocity);
Vector3 velocityChange = transform.InverseTransformDirection(targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0;
velocityChange = transform.TransformDirection(velocityChange);

if (Input.GetButton("Jump") && canJump)
{
}
}

grounded = false;
}

void OnCollisionStay()
{
grounded = true;
}
}``````
• Create a new script, call it "SC_PlanetGravity" and paste the code below inside it:

SC_PlanetGravity.cs

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SC_PlanetGravity : MonoBehaviour
{
public Transform planet;
public bool alignToPlanet = true;

float gravityConstant = 9.8f;
Rigidbody r;

void Start()
{
r = GetComponent<Rigidbody>();
}

void FixedUpdate()
{
Vector3 toCenter = planet.position - transform.position;
toCenter.Normalize();

if (alignToPlanet)
{
Quaternion q = Quaternion.FromToRotation(transform.up, -toCenter);
q = q * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, q, 1);
}
}
}``````
• Create a new GameObject and call it "Player"
• Create a new Capsule, move it inside the "Player" object, and change its position to (0, 1, 0)
• Remove the Capsule Collider component from the Capsule
• Move the Main Camera inside the "Player" object and change its position to (0, 1.64, 0)
• Attach the SC_RigidbodyWalker script to the "Player" object (you'll notice it will add additional components such as Rigidbody and Capsule Collider).
• Change Capsule Collider Height to 2 and Center to (0, 1, 0)
• Assign Main Camera to Player Camera variable in SC_RigidbodyWalker
• Lastly, attach the SC_PlanetGravity script to the "Player" object and assign your planet model to the Planet variable

Press Play and observe the Player align to the planet's surface: 