Search Unity

2D Movement Help!!

Discussion in '2D' started by JayBeeArr, Feb 15, 2017.

  1. JayBeeArr

    JayBeeArr

    Joined:
    Mar 28, 2016
    Posts:
    2
    Hello, I need to move my player not only up and down but also left and right. But this script is only allowing me to move up and down and not left and right as well. Below is my script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour {
    6.  
    7.     public Rigidbody2D rb2D;
    8.     public float speed = 10f;
    9.  
    10.     // Use this for initialization
    11.     void Start ()
    12.     {
    13.         rb2D = GetComponent<Rigidbody2D> ();
    14.     }
    15.    
    16.     // Update is called once per frame
    17.     void FixedUpdate ()
    18.     {
    19.         float Horizontal = Input.GetAxis ("Horizontal") * Time.fixedDeltaTime * speed;
    20.         float Vertical = Input.GetAxis ("Vertical") * Time.fixedDeltaTime * speed;
    21.  
    22.         Vector2 newPositionX = rb2D.position + Vector2.right * Horizontal;
    23.         Vector2 newPositionY = rb2D.position + Vector2.up * Vertical;
    24.  
    25.         rb2D.MovePosition (newPositionX);
    26.         rb2D.MovePosition (newPositionY);
    27.     }
    28. }
     
  2. jackhearts

    jackhearts

    Joined:
    Apr 5, 2013
    Posts:
    103
    I'd hazard a guess that MovePosition() is probably overwriting newPositionX with newPositionY each time. You need to rewrite it so MovePosition only runs once with a vector2 holding both new positions. FixedUpdate() should only be for effecting rigidbody physics so you should be running this in update() anyway. And always use Time.DeltaTime.
     
  3. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,647
    Code (CSharp):
    1. rb2D.MovePosition (newPositionX);
    2. rb2D.MovePosition (newPositionY);
    Your player only moves up and down because these two lines conflict. MovePosition moves your character's rigidbody to an explicit location. Then you call it a second time, overwriting the first. If you changed the order of the lines, you would only be able to move left/right.

    The way to fix this is to call MovePosition just once, with both the X and Y position combined.

    Code (CSharp):
    1. private Vector3 movementInput;
    2.  
    3. private void Update() {
    4.     movementInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    5. }
    6. private void FixedUpdate() {
    7.     Vector3 offset = movementInput * Time.deltaTime * tweenSpeed;
    8.     Vector3 newPosition = rb2D.position + offset;
    9.  
    10.     rb2D.MovePosition(newPosition);
    11. }
    Getting the inputs in Update is the way to go, but the rest doesn't really make a difference. The position of the rigidbody will only be updated in FixedUpdate when using MovePosition, so there's no reason to run this logic every frame. Since it's running on the fixed timestep, using "fixedDeltaTime" is correct to make the player's speed independent of time step, however "deltaTime" will also return "fixedDeltaTime" when used within a FixedUpdate function so either will work.
     
    Last edited: Feb 15, 2017
  4. jackhearts

    jackhearts

    Joined:
    Apr 5, 2013
    Posts:
    103
    true, only glanced and should've specified splitting inputs and physics. o_O

    Using Time.DeltaTime is better practice because the correct one will always be returned. But yea, fixeddelta within fixed works too.
     
  5. JayBeeArr

    JayBeeArr

    Joined:
    Mar 28, 2016
    Posts:
    2
    Thanks Jeffreyschoch and JackHearts! I changed the code so that it uses a Vector 2 rather than a Vector 3 because I'm working in a 2D project but they work perfectly! (I dunno if that is a big change to how things work (using Vector 2 instead of Vector 3) but it still works regardless).

    I think also referencing Vectors is something new I learned as well so I will be implementing that in future projects!
     
  6. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,647
    Position is a Vector3, so be aware that if you set position to a Vector2, the Z value will be assigned 0 implicitly.

    For example:
    Code (CSharp):
    1. Vector3 position = new Vector3(10,10,3);
    2. // position is now (10, 10, 3)
    3. position = new Vector2(5, 5);
    4. // position is now (5, 5, 0)
    5.  
    6. // reversed:
    7. Vector2 position = new Vector2(5, 5);
    8. // position is now (5,5)
    9. position = new Vector3(10,10, 3);
    10. //position is now (10, 10)
     
    JayBeeArr likes this.
  7. jackhearts

    jackhearts

    Joined:
    Apr 5, 2013
    Posts:
    103
    JayBee. vectors are convenient holders for floats so quite essential. A vector3 being x,y,z and vector2 x and y. The 2D scripting elements are simply ignoring the z axis. MovePosition for instance will only affect x and y so the z of the vector3 won't make a difference.You can access each value easily with myVector.x, etc. So your original code can be written like this...

    Code (CSharp):
    1. float Horizontal = Input.GetAxis ("Horizontal") * Time.fixedDeltaTime * speed;
    2.     float Vertical = Input.GetAxis ("Vertical") * Time.fixedDeltaTime * speed;
    3.  
    4.     Horizontal = rb2D.position.x + 1 * Horizontal;
    5.     Vertical = rb2D.position.y + 1 * Vertical;
    6.  
    7.     Vector2 newPos = new Vector2(Horizontal, Vertical);
    8.  
    9.     rb2D.MovePosition (newPos);
    When working in 2D you should be able to use vector2 pretty much all the time without ill effect. Just be aware of what jeffrey mentioned. If you change a position directly like transform.position = new vector2() then the z will set to zero. That may cause a problem if you've got sprites at certain z values for whatever reason.
     
    JayBeeArr likes this.