Jump to content
  • Advertisement
Sign in to follow this  

spherical gravity and player rotation

This topic is 1046 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm having trouble with a player controller I'm developing. Basically, there are many small planetoids... the player can run around on these planets (so gravity is always a force that is planet.position - player.position)


(Unity C#)


I can move the player around the planet just fine, and the player's up vector always faces opposite gravity direction, but I can't seem to rotate the player towards horizontal input axis if the gravity is anything other than -y.


ie, if I change gravity like I am, planet.pos - player.pos, i can't seem to simultaneously affect both the up vector of the player and a rotation around that up vector 


It appears I don't know how to affect a single quaternion axis... for example, I'd love to do something like...


rotate.yAxis(horizontal input * rotation speed) while local upVector = -gravityDirection


but unfortunately that's only pseudo code : (


here is code that's getting me close

void FixedUpdate()
        _rigidbody.MovePosition(_rigidbody.position + transform.TransformDirection(moveDirection) * moveSpeed * Time.deltaTime);

        gravityDirection = (_planetoid.transform.position - transform.position).normalized;
        _rigidbody.AddForce (gravityDirection * gravityStrength);

        gravityRotation = Quaternion.FromToRotation (Vector3.up, -gravityDirection);


    void OnTurn(Quaternion rot)
        targetRotation *= Quaternion.AngleAxis(rotationVelocity * h * Time.deltaTime, transform.up);
        transform.rotation = rot; // ******** swap this out for targetRotation ***********

// ******** swap this out for targetRotation ***********


this is saying that if rot is the variable being used, the player runs around the player properly (always appearing to be standing upright no matter where they are on the planet), but rotating towards input doesn't work. 


if you swap rot out for targetRotation, the player rotates towards input axis, but no longer aligns to the planets surface


any help would be amazing

Edited by digs

Share this post

Link to post
Share on other sites

What do you mean by horizontal input axis? And can you provide a video of the problem?


EDIT: I should also note that gravity does not cause rotation it's self. So there is little need to have rotation be modeled by physical math.

Test to see what Celestial body has the greatest pull on the object in question. If the force is strong enough to pull the object into it's own surface, then change the direction to the new Celestial body.


transform.rotation = Quaternion.LookRotation(_planetoid.transform.position - transform.position).normalized)


This hasn't been tested myself, and I am not too familiar with Unity's API. But conceptually it should work. Hopefully anyways.

Also character rotation from player input will need to be modified as well. Easiest way to do that, is to treat the character as if he was always standing up straight. Rotate him. Then apply the look at transformation. That is assuming that Unity does it's best to keep a frame of reference when it does a look at.

Edited by Tangletail

Share this post

Link to post
Share on other sites
I'm assuming you want the input scheme to work something like mario where the input is relative to the camera. That being the case you first need to get the direction in world coordinates.
Vector3 worldDir = Camera.main.transform.InverseTransformDirection(new Vector3(horizontalControl, verticalControl));
You can then use the world input direction in world coordinates with the gravity direction to construct a rotation
transform.rotation = Quaternion.LookRotation(worldDir, -gravityDirection);
To use these inputs to actually control the player you will need to project the worldDir onto the the plane created by the player position and gravity direction.
Vector3 projected = worldDir - Vector3.Project(wordDir, gravityDirection);
Vector3 normalizedWorldDir = worldDir.normalized;
Vector3 projectedNormalized = normalizedWorldDir - Vector3.Project(normalizedWorldDir, gravityDirection);
// projecting the vector skews the direction. Imagine if the input control formed a perfect circle, projecting
// the circle into a plane can skew it to be an oval leading to some directions not reaching their full range
// projecting the normalized vector allows us to calculate to what extent the input has been skewed to 
// correct it
Vector3 finalMoveDirection = projected * (1.0f / projectedNormalized.magnitude);

_rigidbody.AddForce(finalMoveDirection * moveStrength);

Edited by HappyCoder

Share this post

Link to post
Share on other sites

I hope this video can illustrate my issue better




thanks for the help guys


*edit* @tangletail - more specifically, horizontal input axis is a value from -1 to 1, depending on how far a joystick is moved

Edited by digs

Share this post

Link to post
Share on other sites

@happycoder, does your suggestion only work when the player is perpendicular to the camera? 

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!