0
\$\begingroup\$

I have the following class:

[System.Serializable]
public abstract class BaseBehaviour<T> : MonoBehaviour
{
    [SerializeField]
    public List<BaseAction<T>> Actions;
    protected int currentIndex = 0;
    public bool OptOut = false;
    public Intelligence.Intelligence Intelligence;
    public T BaseAiContext;
    public List<BaseConsideration> Considerations;
    
    public Dictionary<string, object> CacheValues = new Dictionary<string, object>();

    public abstract void UpdateBehaviour();

    public bool IsDone()
    {
        if (currentIndex > Actions.Count || OptOut)
        {
            return true;
        }

        return false;
    }

    public abstract float GetScore();
}

Then i have an implementation of this class:

[System.Serializable]
public class AttackTargetBehaviour : BaseBehaviour<ExampleAI>
{
    public override void UpdateBehaviour()
    {
        Actions[0].Execute(this);
    }

    public override float GetScore()
    {
        float currentScore = 1;
        for (int i = 0; i < Actions.Count; i++)
        {
            float score = 0; // Actions[i].GetScore(this);
            if (score <= 0.0f)
            {
                return 0;
            }
            else
            {
                currentScore *= score;
            }
        }

        return currentScore;
    }
}

However here the list doesn't show in the inspector window which ultimately means i can't add my scriptableobject actions.

Can anyone tell me how i can display such as list in the Unity inspector?

For reference my action looks like this:

    [System.Serializable]
public abstract class BaseAction<TContext> : ScriptableObject, IAction
{

And the implementation of this class is:

    [CreateAssetMenu(fileName = "Move to Target", menuName = "AnAppGames/AI/Example/Actions/MoveToTargetAction")]

public class MoveToTargetAction : BaseAction<ExampleAI>
{
    public override void Execute(BaseBehaviour<ExampleAI> context)
    {
        throw new System.NotImplementedException();
    }

    protected override void OnUpdate(BaseBehaviour<ExampleAI> context)
    {
        throw new System.NotImplementedException();
    }

    protected override void OnStop(BaseBehaviour<ExampleAI> context)
    {
        throw new System.NotImplementedException();
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ What Unity version are you using? 2020 has better generic support than 2019, so that may be a factor. \$\endgroup\$
    – DMGregory
    Commented Feb 15, 2021 at 18:15
  • \$\begingroup\$ I am using 2019 I will try and update to 2020 \$\endgroup\$ Commented Feb 15, 2021 at 18:28

1 Answer 1

1
\$\begingroup\$

Unity 2020 can handle more instances of generic types without extra steps. So something like this will display in the editor out of the box:

public UnityEvent<int> myEvent;

In Unity 2019 or earlier, you can sometimes work around the restrictions by giving a concrete name to the generic variant you want to use. Like this:

[System.Serializable]
public class EventWithIntegerArgument : UnityEvent<int> {}
public EventWithIntegerArgument myEvent;

So for your example, you may be able to take:

public abstract class BaseBehaviour<T> : MonoBehaviour
{
    [SerializeField]
    public List<BaseAction<T>> Actions;

And make it...

public abstract class BaseBehaviour<T> : MonoBehaviour
{
    [System.Serializable]
    public class TypeSpecificAction : BaseAction<T> {}

    [SerializeField]
    public List<TypeSpecificAction> Actions;

Here, each concrete instantiation of BaseBehaviour<T> for a different type T will also create its own nested TypeSpecificAction type based on that T. Since it's a specific named type, not a generic, it should work with Unity's serializer. But I have not tested this specific case.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .