Homing-Missile icon indicating copy to clipboard operation
Homing-Missile copied to clipboard

Something with 'rotateAmount' calculation

Open Kuuo opened this issue 7 years ago • 4 comments

When calculating rotateAmount , it is

rotateAmount = Vector3.Cross(transform.up, direction).z

But I think it should be

rotateAmount = Mathf.Asin(Vector3.Cross(transform.up, direction).z) * (180 / Mathf.PI)

The reason why Vector3.Cross(transform.up, direction).z works is only because the value of these two is very close!

That's say the angle between 2d vector a and b is <a, b>

With normalized a and b, I believe Vector3.Cross(a, b).z is just the sin of <a, b>, because

|a x b| = |a| |b| sin(<a, b>)

|v| is the magnitude of vector v, a x b is the cross-product of a and b

since a and b are normalized, |a| and |b| are 1 , so |a x b| = sin(<a, b>); and since a and b are 2d vectors, the x and y of a x b are 0, so the z of a x b is just the magnitude of a x b ,

which goes to Vector3.Cross(a, b).z = sin(<a, b>)

Therefore, <a, b> should be: Mathf.Asin(Vector3.Cross(a, b).z) * (180 / Mathf.PI) ,

The Mathf.Asin returns radians, multiply it by (180 / Mathf.PI) to turn it into degrees.

Actually, there's a simply way to get <a, b>, that is Vector3.Angle(a, b) . I decompiled the UnityEngine.dll file and found the implementation of this method:

// UnityEngine.Vector3
public static float Angle(Vector3 from, Vector3 to)
{
    return Mathf.Acos(Mathf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1f, 1f)) * 57.29578f;
}

The number 57.29578f is just (180 / Mathf.PI) .

Mathf.Clamp() here is to avoid some number errors, because the cos of any degree can only be between -1 and 1

You get cos from dot-product, and sin from cross-product, <a, b> can also be:

`Mathf.Acos(Vector3.Dot(a, b)) * (180 / Mathf.PI)

I think because dot-product is way more easy to calculate than cross-product, so the built-in method uses the dot-product.

To sum up, with vector a and b, the angle of a and b can be :

Mathf.Asin(Vector3.Cross(a.normalized, b.normalized).z) * (180 / Mathf.PI) // only works for 2d vectors
Mathf.Acos(Vector3.Dot(a.normalized, b.normalized)) * (180 / Mathf.PI) // works for 3d and 2d vectors
Vector3.Angle(a, b) // works for 3d and 2d vectors
Vector2.Angle(a, b) // only works for 2d vectors

Kuuo avatar Oct 17 '17 03:10 Kuuo

and how would you implement this? also for 3D what must you change?

Suya1671 avatar Apr 30 '20 06:04 Suya1671

Got it

dheerajpullupara avatar May 03 '20 13:05 dheerajpullupara

any updates?

Suya1671 avatar May 10 '20 14:05 Suya1671

and how would you implement this? also for 3D what must you change?

@Suyashtnt modify line 25 in the HomingMissile.cs to: float rotateAmount = Vector2.Angle(transform.up, direction); https://github.com/Brackeys/Homing-Missile/blob/cf2617702b54c1806b3915edaa130cc16116c33e/Homing%20Missile/Assets/HomingMissile.cs#L25

Kuuo avatar May 11 '20 05:05 Kuuo