spherical gravity and player rotation

Started by
3 comments, last by digs 8 years, 2 months ago

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);

        OnTurn(gravityRotation);
    }

    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

Advertisement

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.

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);

My current game project Platform RPG

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

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

This topic is closed to new replies.

Advertisement