- Home /
How to move on the surface of a sphere using spherical math? (Without Rigidbodies or raycasts)
Hi,
I want to be able to walk inside a imaginary sphere and facing the center of it. I know I can create the sphere, cast RayCast and inverse normal of the collision point or use Rigidbodies but I want to do it with math but I can't get my head around the math, specially the moving part.
To put it in another word, imagine super mario galaxy but inverse, being inside the sphere while still walking on the surface, like mario.
I've been searching for this for hours but can't find what I want. Thanks.
Answer by elenzil · May 09, 2017 at 08:42 PM
one cheapo- way to achieve this sort of stuff has two parts which you would do every movement update (ie in Update()):
move your player like normal. forget about the sphere. eg, if your player currently has velocity of (1, 2, 3), just move the player by (1, 2, 3).
constrain the player's position back to the surface, and re-calculate velocity.
let's talk about step 2. in step 1, it's likely that the player will move off the surface of the sphere. so step 2 is to put them back on the sphere.
the math looks something like this:
// unity-ish psuedo-code.
// this assumes that the player is:
// 1) originally on the surface of the sphere
// 2) moving tangentially to the surface of the sphere. (not jumping/falling)
// we'll use this value after constraining position to the surface.
void updatePlayerMotion(Player player, float dT, Sphere world) {
// stash the original player position & velocity
Vector3 originalPos = player.position;
Vector3 originalVel = player.velocity;
// ordinary linear motion.
// maybe this is done w/ unity physics instead. up to you.
player.position += player.velocity * dt;
// vector from the center of the world to the player position.
// if the world is centered at 0, 0, 0, then this is just player.position.
Vector3 worldCenterToPlayer = player.position - world.center;
// scale that vector so that its the size of the sphere
Vector3 constrainedPosition = worldCenterToPlayer.normalized * world.radius;
// and offset it by the center of the world again.
// if the world is at 0,0,0 this can be skipped.
player.position = world.center + constrainedPosition;
// okay, now the player position is on the surface.
// let's deal with conserving surface velocity.
// the goal of this section of code is to create a new velocity vector which:
// 1. has the same magnitude as the original velocity
// 2. is tangent to the sphere
// 3. is going in the same direction, more or less, as the original velocity.
// create a vector which is perpendicular to both the vector from the center of the world to the player
// and also to the original velocity:
Vector3 perpAxis = Vector3.Cross(worldCenterToPlayer, originalVel);
// create a vector which is perpendicular to both our 'axis' vector and the radius vector.
// this vector is going in the direction we want, but is likely the wrong size.
Vector3 tangent = Vector3.Cross(perpAxis, worldCenterToPlayer);
// re-scale the tangent vector so it's the same magnitude as the original.
player.Vector3 = tangent.normalized * originalVel.magnitude;
}
hi, elenzil. I have a question. what if i want to change the velocity with keyboard controls ? it seems to only work when the velocity is fixed...
hm, changing velocity should not be a problem. the quality of the approach will degrade as the velocity gets to be a sizable fraction of the radius of the sphere. like if you're traveling 100 units per frame and your sphere is only 200 units in radius or something.
Answer by aidinz · May 10, 2017 at 01:17 PM
This question was waiting so long that I went to forums and it got solved there. Full code:
Your answer
Follow this Question
Related Questions
Moveing on a Sphere in direction of Camera with Math 0 Answers
help with my orbit camera script 0 Answers
Simple Maths Problem - Help! 1 Answer
Math exponential number conversion 1 Answer
Any Good References for Game Math 1 Answer