- Home /
Velocity.normalize to a min of one
Hello, I am working on a game with a ball that bounces around a fixed area. I am using this: GetComponent<Rigidbody2D>().velocity = 3 * GetComponent<Rigidbody2D>().velocity.normalized;
to keep the ball moving at the same speed but able to change angles. The problem I am running into is that the X or Y can end up as 0 thus the ball stops moving up and down or left and right.
So what I believe is going on is that that line of code will lock the velocity to of X and Y to a sum of 3. thus meaning X can be 0 and Y can be three. So my question is how can I modify this to have it lock between 1 and 3 sum rather than 0 and 3 sum?
Any and all help is greatly appreciated.
Normalizing a vector makes its length equal 1. This does not necessarily mean that the sum of the x and y components equal 1, rather that x^2 + y^2 = 1. Do you actually want to clamp the sum of the components or are you trying to clamp the length of the vector?
With what I am watching during the game play to see the values that are causing the issues is the X and the Y on the 2Drigidbody , under the Info Velocity section, that is attached to the ball. Uploaded a pic to help clarify. When these are both above the absolute value of 0 then it is working great. Otherwise it is giving me the issue as stated above with the no movement on the X or Y.
i wonder if it's not because of (float) to (int) conversion. Have you tried with 3.0f ins$$anonymous$$d of 3 ?
I have tried that. And it has no issues with decimals. What is going on s that the normilized locks the number between 1 and 0. Then once X hits 0 then the ball just hits the top and bottom of the level so nothing has an effect on the X Velocity any longer.
I tested your line of code and it doesn't block the direction on x or y axis. I suspect it's another part of your script which has a bug. You surely has a "movement script" as your ball can't move if gravity scale = 0.
You ought to use Rigidbody2D.AddForce(force)
, and Rigidbody2D.AddTorque(torque)
to control your object, ins$$anonymous$$d of altering the velocity yourself. Doing so can have unintended consequences. Like forcing the physics engine to recompute everything, which is expensive.
Additionally using GetComponent<TYPE>()
all the time is prone to problems. Its very inefficient to use this every update (especially twice in one line). Also if the gameobject doesn't have a Rigidbody2D component, you will get a NullReferenceException and crash your game. Try caching (saving) that reference. Declare a variable Rigidbody2D my2DRB; in your class, and in Start() {my2DRB = GetComponent<Rigidbody2D>(); }
or make that variable public and set it in the inspector.
I ought to have addressed this earlier. However I am not sure what your question is.
You want the ball to bounce around between two walls? Like in Pong? I understand your code is multiplying the normalized velocity by three, and assigning it to the same Rigidbody2D.
I'm not sure how 2D rigidbodies compute velocity but it must be similar to 3D RB's. You can set the drag higher to reduce the maximum speed of your object with a given force (or torque). The higher the drag, the slower the object.
Edit: your comment picture shows that you have the Z Axis constrained. That will prevent the object from rotating. Which means you won't have movement on any other axis, provided your object is facing along the Y axis. Try unchecking that box.
Answer by Bunny83 · May 24, 2017 at 11:02 AM
If both axis should have a minimum absolute value of 1 that limits the range of each axis to [-2.828, -1] and [1. 2,828]
if you want to enforce a total velocity of 3:
To achieve that you want to first normalize the vector the way you did and in addition you would check each component and clamp them appropriately:
Vector2 vec = rb2d.velocity.normalized * 3f;
if (Mathf.Abs(vec.x) < 1f)
vec = new Vector2(Mathf.Sign(vec.x)*1f, Mathf.Sign(vec.y) * Mathf.Sqrt(3f*3f - 1f*1f));
else if (Mathf.Abs(vec.y) < 1f)
vec = new Vector2(Mathf.Sign(vec.x) * Mathf.Sqrt(3f*3f-1f*1f), Mathf.Sign(vec.y)*1f);
rb2d.velocity = vec;
Of course the value Mathf.Sqrt(3*3-1*1)
is a constant (Mathf.Sqrt(8)) based on your two parameters. So you could pre-calculate it as it never changes.
static float velocityLimit = Mathf.Sqrt(3f*3f - 1f*1f);
Note that if you want to use different "limits" you have to replace all "1f" constants with your desired minimum limit and "3f" with your desired total vector length.
Answer by Zooow · May 24, 2017 at 07:46 AM
Velocity is direction and speed expressed as a vector. If you don't allow your velocity vector to have x = 0, you'll never have your ball going straight up for instance, which breaks the purpose of physic controlled movement.
But your line of code seems not to be the problem for me. I think your problem is elsewhere in your code. Could you share more of your code?
Answer by plindsey · May 24, 2017 at 07:47 AM
But it wouldn't know if it should be 1 or -1 of there is no value in an axis? Why not add a little bit of chaos to stop it becoming stuck in left/right or up/down? Something like
GetComponent<Rigidbody2D>().velocity = 3 * GetComponent<Rigidbody2D>().velocity.normalized + Vector2((Random.value * 0.2f) - 0.1f, (Random.value * 0.2f) - 0.1f);
Your answer
Follow this Question
Related Questions
Unity 2D - How do I add the velocity and direction of an object to another object? 2 Answers
how to make an 2d object move the direction its facing using rigidbody2d.velcoity 1 Answer
how to jump at fixed height but faster 0 Answers
Why is enemy jumping at different speed even though the velocity is the same? 0 Answers
.normalized sometimes returns 0 values, in a condition that only functions if value is not 0... 1 Answer