Usually, this is because you’re trying to instantiate a class that isn’t derived from ScriptableObject or MonoBehavior… but I don’t see any of that behavior in the script you have here, so beyond that, I’m honestly not sure.
For your entertainment pleasure, this is my Condition.cs (which contains both the Condition code and classes AND the code to draw itself (as my DialogueNode has a Custom Editor as well to call the Condition.DrawInspector() using the same techniques I outline in my Inventory Item editor.
One small issue with this setup is that right now it has cross dependency between namespaces to get the names of the dialogues.
using GameDevTV.Inventories;
using RPG.Quests;
using System.Collections.Generic;
using System.Linq;
using RPG.Dialogue;
using UnityEditor;
using UnityEngine;
namespace GameDevTV.Utils
{
[System.Serializable]
public class Condition
{
[SerializeField] private List<Disjunction> and = new List<Disjunction>();
public bool Check(IEnumerable<IPredicateEvaluator> evaluators)
{
List<IPredicateEvaluator> evalList = evaluators.ToList();
foreach (Disjunction dis in and)
{
if (!dis.Check(evalList))
{
return false;
}
}
Debug.Log("Evaluation of condition is true.");
return true;
}
[System.Serializable]
public partial class Disjunction
{
[SerializeField] private List<Predicate> or = new List<Predicate>();
public bool Check(IEnumerable<IPredicateEvaluator> evaluators)
{
var evalList = evaluators.ToList();
foreach (Predicate pred in or)
{
if (pred.Check(evalList))
{
return true;
}
}
return false;
}
#if UNITY_EDITOR
public List<Condition.Predicate> GetPredicates() => or;
public void AddPredicate(DialogueNode owner)
{
Undo.RecordObject(owner, "Add Predicate");
or.Add(new Condition.Predicate());
EditorUtility.SetDirty(owner);
}
public void RemovePredicate(Predicate predicateToRemove, DialogueNode owner)
{
Undo.RecordObject(owner, "Remove Predicate");
or.Remove(predicateToRemove);
EditorUtility.SetDirty(owner);
}
#endif
}
[System.Serializable]
public class Predicate
{
[SerializeField] private EPredicate predicate;
[SerializeField] private List<string> parameters = new List<string>();
[SerializeField] private bool negate = false;
public bool Check(IEnumerable<IPredicateEvaluator> evaluators)
{
Debug.Log($"Testing {predicate} {parameters[0]}");
foreach (var evaluator in evaluators)
{
bool? result = evaluator.Evaluate(predicate, parameters.ToArray());
if (result == null)
{
continue;
}
if (result == negate) return false;
}
return true;
}
#if UNITY_EDITOR
public void SetEPredicate(EPredicate value, DialogueNode owner)
{
if (predicate == value) return;
Undo.RecordObject(owner, "Change Predicate");
predicate = value;
EditorUtility.SetDirty(owner);
}
public void SetNegate(bool value, DialogueNode owner)
{
if (negate == value) return;
Undo.RecordObject(owner, "Change Negate");
negate = value;
EditorUtility.SetDirty(owner);
}
public void AddParameter(DialogueNode owner)
{
Undo.RecordObject(owner, "Add Parameter");
parameters.Add("");
EditorUtility.SetDirty(owner);
}
public void RemoveParameter(int stringToRemove, DialogueNode owner)
{
Undo.RecordObject(owner, "Remove Parameter");
parameters.RemoveAt(stringToRemove);
EditorUtility.SetDirty(owner);
}
public void SetParameter(int index, string value, DialogueNode owner)
{
if (parameters[index] == value) return;
Undo.RecordObject(owner, "Change Parameter");
parameters[index] = value;
EditorUtility.SetDirty(owner);
}
public List<string> GetParameters() => parameters;
public EPredicate GetEPredicate() => predicate;
public bool GetNegate() => negate;
#endif
}
#if UNITY_EDITOR
public void RemoveDisjunction(Disjunction disjunctionToRemove, DialogueNode owner)
{
Undo.RecordObject(owner, "Remove Disjunction");
and.Remove(disjunctionToRemove);
EditorUtility.SetDirty(owner);
}
public void AddDisjunction(DialogueNode owner)
{
Undo.RecordObject(owner, "Add Disjunction");
and.Add(new Disjunction());
EditorUtility.SetDirty(owner);
}
public void DrawInspector(DialogueNode selected)
{
Disjunction disJunctionToRemove = null;
foreach (Disjunction disjunction in and)
{
EditorGUILayout.Separator();
Predicate predicateToRemove = null;
foreach (Predicate predicate in disjunction.GetPredicates())
{
EditorGUILayout.BeginHorizontal();
predicate.SetNegate(EditorGUILayout.Toggle("Negate", predicate.GetNegate()), selected);
predicate.SetEPredicate((EPredicate)EditorGUILayout.EnumPopup(predicate.GetEPredicate()), selected);
if (GUILayout.Button("-")) predicateToRemove = predicate;
EditorGUILayout.EndHorizontal();
if (predicate.GetEPredicate() != EPredicate.None)
{
int stringToRemove = -1;
var stringList = GetNeededList(predicate.GetEPredicate(),0);
var secondParamList = GetNeededList(predicate.GetEPredicate(), 1);
for (int i = 0; i < predicate.GetParameters().Count; i++)
{
int positionInList = PositionInList(predicate.GetParameters()[i], i==0?stringList: secondParamList);
Debug.Log($"PositionInList = {positionInList}");
if (positionInList < 0) positionInList = 0;
EditorGUILayout.BeginHorizontal();
if (stringList != null && stringList.Count > 0)
{
Debug.Log($"{stringList.Count} - {positionInList} ");
predicate.SetParameter(i,
stringList
[EditorGUILayout.Popup(positionInList,i==0? stringList.ToArray():secondParamList.ToArray())],
selected);
}
else
{
predicate.SetParameter(i, EditorGUILayout.TextField(predicate.GetParameters()[i]),
selected);
}
if (GUILayout.Button("-")) stringToRemove = i;
EditorGUILayout.EndHorizontal();
}
if (stringToRemove > -1)
{
predicate.RemoveParameter(stringToRemove, selected);
}
if (GUILayout.Button("Add Parameter"))
{
predicate.AddParameter(selected);
}
}
}
if (predicateToRemove != null)
{
disjunction.RemovePredicate(predicateToRemove, selected);
}
if (GUILayout.Button("Add Predicate"))
{
disjunction.AddPredicate(selected);
}
if (GUILayout.Button("Remove Disjunction"))
{
disJunctionToRemove = disjunction;
}
}
if (disJunctionToRemove != null)
{
RemoveDisjunction(disJunctionToRemove, selected);
}
if (GUILayout.Button("Add Disjunction"))
{
AddDisjunction(selected);
}
}
private List<string> GetNeededList(EPredicate predicate, int position)
{
switch (predicate)
{
case EPredicate.HasQuest:
return GetObjectNames<Quest>();
case EPredicate.CompletedQuest:
return GetObjectNames<Quest>();
case EPredicate.HasItem:
return GetObjectNames<InventoryItem>();
case EPredicate.AboveLevel:
{
return NumberList();
}
case EPredicate.MinimumTrait:
{
return position==0?TraitList():NumberList();
}
}
return new List<string>();
}
List<string> NumberList()
{
List<string> result = new List<string>();
for (int i = 1; i < 100; i++)
{
result.Add($"{i}");
}
return result;
}
List<string> TraitList()
{
List<string> result = new List<string>()
{
"Strength",
"Agility",
"Constitution",
"Intelligence",
"Charisma",
};
return result;
}
private List<string> GetObjectNames<T>() where T:ScriptableObject
{
List<string> result = new List<string>();
foreach (T obj in Resources.LoadAll<T>(""))
{
result.Add(obj.name);
}
return result;
}
private int PositionInList(string parameter, List<string> listToCheck)
{
return listToCheck.IndexOf(parameter);
}
#endif
}
}