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
    Feb 15 at 18:15
  • \$\begingroup\$ I am using 2019 I will try and update to 2020 \$\endgroup\$ Feb 15 at 18:28
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\$

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.