Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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

Discussion in 'Editor & General Support' started by MosquitoByte, Oct 22, 2020.

  1. MosquitoByte

    MosquitoByte

    Joined:
    Sep 17, 2018
    Posts:
    213
    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:
    https://i.gyazo.com/369a4c02a2d33caee0015ee022a070fd.gif

    Standing still and jumping:
    https://i.gyazo.com/31817933553ddf3d93defdea06184f4f.gif

    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.


    Code (CSharp):
    1. public class PlayerMovement : MonoBehaviour
    2. {
    3.     private Rigidbody2D MyRigidBody;
    4.     private float horizontalInput;
    5.     public float movespeed;
    6.     public float jumpForce;
    7.  
    8.     // Start is called before the first frame update
    9.     void Start()
    10.     {
    11.         MyRigidBody = GetComponent<Rigidbody2D>();  
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update()
    16.     {
    17.         horizontalInput = Input.GetAxisRaw("Horizontal");
    18.  
    19.         //Jumping code
    20.         if (Input.GetKeyDown(KeyCode.Space))
    21.         {
    22.             MyRigidBody.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
    23.         }
    24.     }
    25.     private void FixedUpdate()
    26.     {
    27.         MyRigidBody.AddForce(transform.right * horizontalInput * movespeed);
    28.  
    29.        //This is the problem
    30.         if(horizontalInput == 0)
    31.         {
    32.             Vector3 veloc = MyRigidBody.velocity;
    33.             veloc.x = 0;
    34.             MyRigidBody.velocity = veloc;
    35.            
    36.         }
    37.  
    38.     }
    39. }
    Code (CSharp):
    1. public class GravPoint : MonoBehaviour
    2. {
    3.     public float GravityScale;
    4.  
    5.     // Start is called before the first frame update
    6.     void Start()
    7.     {
    8.        
    9.     }
    10.  
    11.     // Update is called once per frame
    12.     void Update()
    13.     {
    14.        
    15.     }
    16.  
    17.     private void OnTriggerStay2D(Collider2D collision)
    18.     {
    19.         if(collision.GetComponent<Rigidbody2D>() != null && !collision.CompareTag("UnaffectedByOrbit"))
    20.         {
    21.             Vector3 Direction = (transform.position - collision.transform.position) * GravityScale;
    22.             collision.GetComponent<Rigidbody2D>().AddForce(Direction);
    23.  
    24.             collision.transform.up = (collision.transform.position - transform.position);
    25.  
    26.             collision.GetComponent<Rigidbody2D>().drag = 1.5f;
    27.         }
    28.  
    29.     }
    30. }
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    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.
    Code (CSharp):
    1. Vector3 velocity = MyRigidbody.velocity;
    2. Vector3 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
    3. MyRigidbody.velocity -= horizontalComponent;
     
  3. MosquitoByte

    MosquitoByte

    Joined:
    Sep 17, 2018
    Posts:
    213
    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:
    Code (CSharp):
    1.   private void FixedUpdate()
    2.     {
    3.         MyRigidBody.AddForce(transform.right * horizontalInput * movespeed);
    4.  
    5.         if(horizontalInput == 0)
    6.         {
    7.             Vector3 velocity = MyRigidBody.velocity;
    8.             Vector3 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
    9.             MyRigidBody.velocity -= horizontalComponent;
    10.  
    11.  
    12.         }
    13.  
    14.     }
    throws error: "Operator '-=' is ambiguous on operands of type 'Vector2' and 'Vector3' "
     
    Last edited: Oct 22, 2020
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Oops sorry forgot you're in 2D. This should work:
    Code (CSharp):
    1. Vector2 velocity = MyRigidbody.velocity;
    2. Vector2 horizontalComponent = Vector3.ProjectOnPlane(velocity, transform.up);
    3. MyRigidbody.velocity -= horizontalComponent;
     
  5. MosquitoByte

    MosquitoByte

    Joined:
    Sep 17, 2018
    Posts:
    213
    Thank you, it works nicely, though i dont understand exactly how. Is there an explanation i can find somewhere online?
     
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    I can try to explain here:
    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.
     
    trductan likes this.