- Home /
Translation in 2D with a normalised vector.
I really can't see why this doesn't do anything. The player character doesn't move at all but the rest of the script works fine. It doesn't throw any errors and the rest operates as intended. I know there are other ways involving setting the transform.position directly but I the problem with that is that moving diagonally end up faster than moving straight because the it produces a vector (in practice but not the data type) or 5x by 5y (i.e. 50^1/2 on the diagonal (about 7) rather than the 5 I want). Instead I want to produce a vector between x and y and normalise it before multiplying by 5 so that the max speed is consistent in all directions.
Here is my code:
moveDirection = new Vector2 (Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
moveDirection = moveDirection.normalized;
transform.Translate(moveDirection * Time.deltaTime * maxSpeed);
Note I have also tried
moveDirection.Normalize;
Which also compiled but didn't do anything.
Answer by DiegoSLTS · Aug 17, 2016 at 10:10 PM
With that little code I can only guess that maxSpeed is 0. Or you set the timeScale to 0 so Time.deltaTime is 0.
Add a Debug.Log line or a breakpoint on the debugger to check the values of moveDirection, Time.deltaTime, maxSpeed and the product of all three just before the Translate line.
Also, "moveDirection.Normalize;" should give you a compile error since you're missing the "()" before the ;.
The other reasons that are also possible are:
$$anonymous$$aybe the Horizontal and / or Vertical axis have been changed in the input manager. So they might return 0 all the time because they aren't mapped to "any" / "the wrong" keys.
$$anonymous$$aybe this code fragment isn't inside Update.
$$anonymous$$aybe "Update" has been spellt wrong? Like "update" for example (common Java programmer error ^^).
$$anonymous$$aybe the script is disabled (checkbox).
ps: normalizing the vector has an often unwanted sideeffect. The input axis don't necessarily be 1 as soon as the user presses the button down (see the Sensitivity / Gravity settings of the axis in the input manager). normalizing will force you to full speed as soon as the input axis differ from "0". If the axis "gravity" isn't too high (and snap is off) if would also take longer to stop moving after the user released the keys.
Usually it's better to use Vector3.Clamp$$anonymous$$agnitude. This allows the vector to get any possible value as long as it's length is below the clamp limit. If it's larger it will be clamped to the given length:
moveDirection = new Vector2 (Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
moveDirection = Vector2.Clamp$$anonymous$$agnitude(moveDirection, 1f);
transform.Translate(moveDirection * Time.deltaTime * maxSpeed);
This will ensure that the length of moveDirection never gets larger than 1f but it can get smaller. Controller and joystick users will love you ^^ (if the axis are setup).
Clamp$$anonymous$$agnitude simply does this:
public static Vector2 Clamp$$anonymous$$agnitude(Vector2 vector, float maxLength)
{
if (vector.sqr$$anonymous$$agnitude > maxLength * maxLength)
{
return vector.normalized * maxLength;
}
return vector;
}
So it only normalizes the vector if it's larger than maxLength.
Answer by Rocketman_Dan · Aug 18, 2016 at 01:11 PM
@DiegoSLTS Yeah that was a typo. I did use the parentheses to in .Normalize(); but that wasn't a direct copy paste.
I suspected that something else in my script was overriding it somehow and was cleaning up my whitespace and comments to post it here and it started to make it move. There must have been something I forgot to comment out amoungst the other comments.
While it wasn't working it returned (0.7, 0.7) as the full positive Y, full positive X vector and maxSpeed was 5 as intended. These still are the same.
Now however it now treats the mouse point as the positive direction in the world (making controls incredibly clunky) where my intention was to have WASD control the position on the screen within the main camera and the look rotation be independent. How might I overcome that. Perhaps make the player a child of an empty object with the movement part of the scrip on it?
Here is the full script:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour
{
public float maxSpeed = 5f;
public float shipBoundaryRadius = 0.4f;
public int rotationOffset = -90;
float logDelay = 0;
Vector2 moveDirection;
Rigidbody2D playerRigidbody;
// Update is called once per frame
void FixedUpdate()
{
//translation controls
/*
pos.y += Input.GetAxis("Vertical") * Time.deltaTime * maxSpeed;
pos.x += Input.GetAxis("Horizontal") * Time.deltaTime * maxSpeed;
*/
moveDirection = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
moveDirection = moveDirection.normalized;
transform.Translate(moveDirection * Time.deltaTime * maxSpeed);
Debug.Log("moveDirection is " + moveDirection.normalized);
Debug.Log("max speed is " + maxSpeed);
//decrement delay time for outputting boudary strike info to log
logDelay -= Time.deltaTime;
Vector3 pos = transform.position;
//restrict ship to boundary of screen
if (pos.y + shipBoundaryRadius > Camera.main.orthographicSize)
{
pos.y = Camera.main.orthographicSize - shipBoundaryRadius;
if (logDelay <= 0)
{
Debug.Log("PlayerShip boundary strike - restrict to screen");
logDelay = 0.5f; // to prevent log from being filled with logs of this collision
}
}
if (pos.y - shipBoundaryRadius < -Camera.main.orthographicSize)
{
pos.y = -Camera.main.orthographicSize + shipBoundaryRadius;
if (logDelay <= 0)
{
Debug.Log("PlayerShip boundary strike - restrict to screen");
logDelay = 0.5f;
}
}
float screenRatio = (float)Screen.width / (float)Screen.height;
float widthOrtho = Camera.main.orthographicSize * screenRatio;
if (pos.x + shipBoundaryRadius > widthOrtho)
{
pos.x = widthOrtho - shipBoundaryRadius;
if (logDelay <= 0)
{
Debug.Log("PlayerShip boundary strike - restrict to screen");
logDelay = 0.5f;
}
}
if (pos.x - shipBoundaryRadius < -widthOrtho)
{
pos.x = -widthOrtho + shipBoundaryRadius;
if (logDelay <= 0)
{
Debug.Log("PlayerShip boundary strike - restrict to screen");
logDelay = 0.5f;
}
}
//Update the transfprm
transform.position = pos;
//Rotation controls
//get vector equal to difference between ship and mouse
Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
difference.Normalize(); //normalise vector (i.e. make length = 1)
float rot = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg; //find the angle in degrees
// set ship rotation to that angle with an offset value to alow the code snippet to be use with any object (by default for our purposes is -90)
transform.rotation = Quaternion.Euler(0f, 0f, rot + rotationOffset);
//NOTE: lesson learned use this method in future for better accuracy
}
}