0
\$\begingroup\$

I've defined an abstract method in an abstract class with a generic return type. However, when I try to use the generic type as a Vector3 (or any other variable) I get this error :

Cannot implicitly convert type 'UnityEngine.Vector3' to 'Vector3'

this is my code : the error is in the line

return direction;
using UnityEngine;


public class DashAbility : Ability
{

    public Vector3 direction;

    public override Vector3 getAbilityData<Vector3>()
    {
        return direction;
    }

    public override bool trigger(pointerData pointer)
    {
        return InputMaster.tryPointer(rollInputTest);
    }

    bool rollInputTest(pointerData p)
    {
        return (p.phase == pointerPhase.Dragging) && p.startHit.collider.CompareTag("Player");
    }
}

and this is the class I'm deriving from:

using UnityEngine;

public abstract class Ability : MonoBehaviour
{
    public abstract bool trigger(pointerData pointer);
    public abstract T getAbilityData<T>() ;
}

\$\endgroup\$
4
  • 1
    \$\begingroup\$ This code looks fine to me, are you sure this is the whole code? Maybe you are importing some other library which also has another Vector3 definition? \$\endgroup\$ – S. Tarık Çetin Jun 17 '20 at 22:29
  • 1
    \$\begingroup\$ It looks like you have another type called Vector3 present. What does your IDE say when you hover over other instances of Vector3 in this code? Or if you print the fully-qualified type name? \$\endgroup\$ – DMGregory Jun 17 '20 at 22:29
  • \$\begingroup\$ @S.TarıkÇetin I'm only using UnityEngine in both scripts. \$\endgroup\$ – Venay Jun 17 '20 at 22:34
  • \$\begingroup\$ @DMGregory when I hover over Vector3 for the direction variable I get this: Struct UnityEngine.Vector3 Representation of 3D vectors and points and when I hover over the Vector3 in the abstract method I get this: Vector3 in DashAbility.getAbilityData<Vector3> \$\endgroup\$ – Venay Jun 17 '20 at 22:36
1
\$\begingroup\$

When you write this:

public override Vector3 getAbilityData<Vector3>()
{
    return direction;
}

It wants to override from this:

public abstract T getAbilityData<T>() ;

In this function, <T> is a placeholder that represents "Some arbitrary type I'll call T".

So in order to match this, the compiler has to interpret the <Vector3> as "Some arbitrary type I'll call Vector3" - ie. it's no longer referring to the type UnityEngine.Vector3, it's just using the string of characters "Vector3" to serve as a placeholder for this arbitrary type, matching the parent.

Naturally, there's no implicit conversion available from a real actual UnityEngine.Vector3 and this arbitrary type that we're just calling "Vector3", but could just as easily be an int or a bool or...

It looks like what you meant instead was something like this:

// "There are different kinds of ability, each with their own data type"
public abstract class Ability<T> : MonoBehaviour
{
    public abstract bool trigger(pointerData pointer);

    // "The getAbilityData method returns an instance of this particular ability's data type"
    public abstract T getAbilityData();
}

// "DashAbility is an Ability that uses Vector3 data"
public class DashAbility : Ability<Vector3>
{    
    public Vector3 direction;

    public override Vector3 getAbilityData()
    {
        return direction;
    }

    // ...
}

Here we've constrained T to be one specific type for each derived form of Ability. For DashAbility, it's UnityEngine.Vector3, so now DashAbility.getAbilityData() no longer has to have versions to handle any arbitrary type, only the real actual Vector3 version.

\$\endgroup\$
1
  • \$\begingroup\$ Works perfectly, and learned a lot about generics. Thanks for the answer \$\endgroup\$ – Venay Jun 18 '20 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.