Making a gameobject's "right" or "sideways" direction relative?

Hello all, i am experimenting around with some game mechanics involving gravity rotating around a circular planet. All has been going well so far, mostly. However, i noticed a slight bit of unwanted inertia on my player object, that is, i wasn’t inputting any movement but it was still sliding ever so slightly. My normal trick for this would be to set the player’s x velocity to 0 every frame they aren’t inputting a horizontal direction, however i quickly realized that this caused problems with the planetary gravity mechanic. The player has a capsule collider 2d and the planet is a combination of a gameobject with a circle collider as the parent of an object with a trigger collider and a script named GravPoint.cs.

Holding left and jumping:

Standing still and jumping:

I need to find a way to make the Player’s sense of right and left Relative to it’s orbit on the planet so i can stop it from sliding around when not in movement.

public class PlayerMovement : MonoBehaviour
{
    private Rigidbody2D MyRigidBody;
    private float horizontalInput;
    public float movespeed;
    public float jumpForce;

    // Start is called before the first frame update
    void Start()
    {
        MyRigidBody = GetComponent<Rigidbody2D>();  
    }

    // Update is called once per frame
    void Update()
    {
        horizontalInput = Input.GetAxisRaw("Horizontal");

        //Jumping code
        if (Input.GetKeyDown(KeyCode.Space))
        {
            MyRigidBody.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
        }
    }
    private void FixedUpdate()
    {
        MyRigidBody.AddForce(transform.right * horizontalInput * movespeed);

       //This is the problem
        if(horizontalInput == 0)
        {
            Vector3 veloc = MyRigidBody.velocity;
            veloc.x = 0;
            MyRigidBody.velocity = veloc;
           
        }

    }
}
public class GravPoint : MonoBehaviour
{
    public float GravityScale;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
       
    }

    private void OnTriggerStay2D(Collider2D collision)
    {
        if(collision.GetComponent<Rigidbody2D>() != null && !collision.CompareTag("UnaffectedByOrbit"))
        {
            Vector3 Direction = (transform.position - collision.transform.position) * GravityScale;
            collision.GetComponent<Rigidbody2D>().AddForce(Direction);

            collision.transform.up = (collision.transform.position - transform.position);

            collision.GetComponent<Rigidbody2D>().drag = 1.5f;
        }

    }
}

project your velocity vector on the plane defined by your player’s up normal. Then subtract that from the velocity to remove the horizontal component.

Vector3 velocity = MyRigidbody.velocity;
Vector3 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
MyRigidbody.velocity -= horizontalComponent;

interesting, i’ve never seen ProjectOnPlane before, what does it do? I may need a bit of an explanation, because i don’t think i did it correctly:

  private void FixedUpdate()
    {
        MyRigidBody.AddForce(transform.right * horizontalInput * movespeed);

        if(horizontalInput == 0)
        {
            Vector3 velocity = MyRigidBody.velocity;
            Vector3 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
            MyRigidBody.velocity -= horizontalComponent;


        }

    }

throws error: "Operator ‘-=’ is ambiguous on operands of type ‘Vector2’ and ‘Vector3’ "

Oops sorry forgot you’re in 2D. This should work:

Vector2 velocity = MyRigidbody.velocity;
Vector2 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
MyRigidbody.velocity -= horizontalComponent;

Thank you, it works nicely, though i dont understand exactly how. Is there an explanation i can find somewhere online?

I can try to explain here:
6446014--721559--demo.png
So the Green arrow here is your character’s local “up” direction. We can use that to create the Blue Plane.

The Red arrow is your character’s current rigidbody velocity vector. We want to remove any part of that velocity vector that is parallel to the Blue plane, because that is the “sideways” part. So first we have to calculate the sideways part. We do that by projecting the Red vector onto the Blue plane, which I’m illustrating with the black dashed line in this diagram. The result of that projection is the Magenta arrow. That Magenta arrow is the “horizontal” component of the velocity vector. If we subtract that Magenta horizontal vector from the Red velocity vector, we are left with a vector that has zero local horizontal component. That final vector would look a bit like the dashed black line with an arrow pointing upwards, and it represents only the “up/down” component of your original Red velocity vector.

Hope that made sense!

So in the code:
“velocity” is the red arrow
“horizontalComponent” is the magenta arrow
“transform.up” is the green arrow
The blue plane is what we’re projecting the velocity on.

1 Like