How to make an extension method available just from a class

Hi there!

I’m defining this extension method to get a signed angle between two vectors.

public static float SignedAngle(this Vector3 vector3, Vector3 v1, Vector3 v2)
        {
            var _angle = Vector3.Angle(v1, v2);

            Vector3 _crossProduct = Vector3.Cross(v1, v2).normalized;
            if (_crossProduct.z > 0) _angle *= -1;

            return _angle;
        }

Now I can call this function typing Vector3.SignedAngle(v1, v2), just like Vector3.Angle function.

The thing is, there’s a second way to call this defining a variable:

Vector3 v;
v.SignedAngle(v1, v2);

This makes no sense. I’d like SignedAngle to be strictly called from Vector3 class, not from a Vector3 variable, just like Vector3.Angle function.

Any idea on how to do this?

With that definition, you cannot use Vector3.SignedAngle. That function defines a method to be called on instances of Vector3, not a static extension of the Vector3 struct itself.

The only option for directly extending those Unity classes/structs would be to write a wrapper class that implements and extends the current functionality.

You can change your function like this to work properly:

public static float SignedAngle(this Vector3 v1, Vector3 v2) {
    var _angle = Vector3.Angle(v1, v2);

    Vector3 _crossProduct = Vector3.Cross(v1, v2).normalized;
    if(_crossProduct.z > 0)
        _angle *= -1;

    return _angle;
}

So then you would call the function on the first vector, passing the second vector to find the signed angle.

Vector3 v1;
v1.SignedAngle(v2);

You wrote an extension method, not a static method.

The this Vector3 vector3, references the Vector3 you’re calling the method on. The v in v.SignedAngle(v1, v2); And v1 and v2 are the 2 passed in as parameters.

Extension methods are a way to fake adding a method to the interface of an object.

If you want a static method, you just declare it static.

public static float SignedAngle(Vector3 v1, Vector3 v2)
{
    var _angle = Vector3.Angle(v1, v2);

    Vector3 _crossProduct = Vector3.Cross(v1, v2).normalized;
    if (_crossProduct.z > 0) _angle *= -1;

    return _angle;
}

This will mean that’s it’s a member of whatever class you added it to (I usually have a ‘VectorUtil’ class I do this with). You can’t insert static methods into existing classes.

2 Likes

Thank you guys. So I assume there’s no way to extend Vector3 class to make a Vector3.SignedAngle call, right? Unless you have the SDK available I guess…

Not without great effort or money.

However, it’s merely the difference between this:

Vector3.SignedAngle(v1, v2);

and this:

v1.SignedAngle(v2);

Seems like a minor sacrifice in syntax for the same functionality.

Or this

Vector3Util.SignedAngle(v1, v2);
1 Like

Thanks again guys. Absolutely understood. I’m always a bit obsessed on trying to get the best organized code, but I assume I have to deal with this in a less elegant way.

If you enable the experimental runtime in Unity 2017, and get access to C# 6, you can import @Kiwasi 's suggestion statically:

using static Vector3Util;

...

var signedAngle = SignedAngle(v1, v2);

That might be more elegant?

5 Likes

Just like you, I was wondering about that. Decided to stop at this.
Since you for sure have the extension class:

public static class Extensions{}

I did it like that:

public static Vector2 GetRandomDirection => new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f));

and you use it anywhere just like any extension:

Extensions.GetRandomDirection

:slight_smile: