简体   繁体   中英

rigidbody2d constant velocity based on direction

I currently have this script (don't read too much into the code, not everything is pasted here, only what is needed to understand the question):

Touch[] touches = Input.touches;
Vector2 dir = (Camera.main.ScreenPointToRay (touches [i].position).GetPoint (0) - obj.getGameObject ().transform.position).normalized * speed;
obj.getGameObject ().GetComponent<Rigidbody2D> ().velocity = dir;

The problem is that the speed of the rigidbody is different based on distance from the object to the touched point, so the speed will be 2x or more if you touch a point distant from the gameobject, compared to a point close to the gameobject.

How would I go about fixing this, so I can achieve a constant velocity which isn't based on distance from the gameobject?

The core of the problem lies within this line:

Vector2 dir = (Camera.main.ScreenPointToRay (touches [i].position).GetPoint (0) - obj.getGameObject ().transform.position).normalized * speed;

The direction vector is denormalized due to a cast

When you calculate this difference between the touch position and the object position with Camera.main.ScreenPointToRay (touches [i].position).GetPoint (0) - obj.getGameObject ().transform.position , you have to remember that this result may not be 2D - it is a Vector3 . This means that it may have a non-zero z-value, if the result of GetPoint (0) and transform.position are not at the same position on the z-axis.

When you normalize the Vector3 , its length becomes 1, but only if its z-value is taken into account. When you store this value in Vector2 dir , that Vector3 is cast to a Vector2 and its z-value is discarded. This means that the length of the previously-normalized vector is no longer guaranteed to be 1; it can vary anywhere in the range of [0,1].

The cast vector's length depends on the relative size of the z-value

If you multiply this new Vector2 with speed and use it to set the velocity of a rigidbody, the magnitude of the rigidbody's velocity will be between 0 and speed , rather than always speed . The reason why the object goes faster if your touch is farther, and slower if it is closer, is because the z-value (which will be constant) will become less relative to your x- and y-values the farther away your touch is. Here's an illustration to show how this will affect the cast Vector2 :

在此处输入图片说明

Note how casting the normalized Vector3 will result in a longer Vector2 if the z-value is smaller relative to the other values. (The diagram assume x = 0, to make it easier to read.)

The solution

Fixing this problem isn't too difficult - you just need to normalize the vector once the z-value has become 0, whether by cast or by explicit assignment. Then your direction is guaranteed to be a length of 1, and your speed will be constant. Here's an example:

Touch[] touches = Input.touches;
Vector3 dirRaw = Camera.main.ScreenPointToRay (touches [i].position).GetPoint (0) - obj.getGameObject ().transform.position;
dirRaw.z = 0;
Vector2 dir = dirRaw.normalized * speed;
obj.getGameObject ().GetComponent<Rigidbody2D> ().velocity = dir;

Hope this helps! Let me know if you have any questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM