Thank you for the reply Brian, I should have posted that yes this same pause happens in a build, and also when testing on another machine.
In my early post: Improving Conditions: A Property Editor - #92 by LuDiChRiS
I was getting a pause in Edit mode whenever I clicked on a Node that had a predicate, and I resolved that by switching out Resources.LoadAll for: AssetDatabase.FindAssets(“t:Quest”). This sovled it, but could this be related?
private void BuildQuestList()
{
if (quests != null) return;
quests = AssetDatabase.FindAssets("t:Quest")
.Select(guid => AssetDatabase.LoadAssetAtPath<Quest>(AssetDatabase.GUIDToAssetPath(guid)))
.ToDictionary(quest => quest.name, quest => quest);
}
private void BuildInventoryItemsList()
{
if (items != null) return;
items = AssetDatabase.FindAssets("t:InventoryItem")
.Select(guid => AssetDatabase.LoadAssetAtPath<InventoryItem>(AssetDatabase.GUIDToAssetPath(guid)))
.ToDictionary(item => item.GetItemID(), item => item);
}
That’s from the PredicatePropertyDrawer.cs Full script here:
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using RPG.Quests;
using System.Linq;
using GameDevTV.Inventories;
using System;
using RPG.Stats;
namespace RPG.Core.Editor
{
[CustomPropertyDrawer(typeof(Condition.Predicate))]
public class PredicatePropertyDrawer : PropertyDrawer
{
private Dictionary<string, Quest> quests;
private Dictionary<string, InventoryItem> items;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty predicate = property.FindPropertyRelative("predicate");
SerializedProperty parameters = property.FindPropertyRelative("parameters");
SerializedProperty negate = property.FindPropertyRelative("negate");
float propHeight = EditorGUI.GetPropertyHeight(predicate);
position.height = propHeight;
EditorGUI.PropertyField(position, predicate);
//EditorGUI.PropertyField(negate.rectValue, predicate);
PredicateType selectedPredicate = (PredicateType)predicate.enumValueIndex;
if (selectedPredicate == PredicateType.Select) return; //Stop drawing if there's no predicate
while (parameters.arraySize < 2)
{
parameters.InsertArrayElementAtIndex(0);
}
SerializedProperty parameterZero = parameters.GetArrayElementAtIndex(0);
SerializedProperty parameterOne = parameters.GetArrayElementAtIndex(1); //Edit, was accidentally 0 in first draft
if (selectedPredicate == PredicateType.HasQuest || selectedPredicate == PredicateType.CompletedQuest || selectedPredicate == PredicateType.CompletedObjective)
{
position.y += propHeight;
DrawQuest(position, parameterZero);
if (selectedPredicate == PredicateType.CompletedObjective)
{
position.y += propHeight;
DrawObjective(position, parameterOne, parameterZero);
}
}
if (selectedPredicate == PredicateType.PlayerHasItem || selectedPredicate == PredicateType.PlayerHasItems || selectedPredicate == PredicateType.PlayerHasItemEquipped)
{
position.y += propHeight;
DrawInventoryItemList(position, parameterZero, selectedPredicate == PredicateType.PlayerHasItems, selectedPredicate == PredicateType.PlayerHasItemEquipped);
if (selectedPredicate == PredicateType.PlayerHasItems)
{
position.y += propHeight;
DrawIntSlider(position, "Qty Needed", parameterOne, 1, 100);
}
}
if (selectedPredicate == PredicateType.HasLevel)
{
position.y += propHeight;
DrawIntSlider(position, "Level Required", parameterZero, 1, 100);
}
if (selectedPredicate == PredicateType.MinimumTrait)
{
position.y += propHeight;
DrawTrait(position, parameterZero);
position.y += propHeight;
DrawIntSlider(position, "Minimum", parameterOne, 1, 100);
}
if (selectedPredicate == PredicateType.NPCHasItem || selectedPredicate == PredicateType.NPCHasItems || selectedPredicate == PredicateType.NPCHasItemEquipped)
{
position.y += propHeight;
DrawInventoryItemList(position, parameterZero, selectedPredicate == PredicateType.NPCHasItems, selectedPredicate == PredicateType.NPCHasItemEquipped);
if (selectedPredicate == PredicateType.NPCHasItems)
{
position.y += propHeight;
DrawIntSlider(position, "Qty Needed", parameterOne, 1, 100);
}
}
position.y += propHeight;
EditorGUI.PropertyField(position, negate);
}
private void DrawQuest(Rect position, SerializedProperty element)
{
BuildQuestList();
var names = quests.Keys.ToList();
int index = names.IndexOf(element.stringValue);
EditorGUI.BeginProperty(position, new GUIContent("Quest:"), element);
int newIndex = EditorGUI.Popup(position, "Quest:", index, names.ToArray());
if (newIndex != index)
{
element.stringValue = names[newIndex];
}
EditorGUI.EndProperty();
}
void DrawObjective(Rect position, SerializedProperty element, SerializedProperty selectedQuest)
{
string questName = selectedQuest.stringValue;
if (!quests.ContainsKey(questName))
{
EditorGUI.HelpBox(position, "Please Select A Quest", MessageType.Error);
return;
}
List<string> references = new List<string>();
List<string> descriptions = new List<string>();
foreach (Quest.Objective objective in quests[questName].GetObjectives())
{
references.Add(objective.reference);
descriptions.Add(objective.description);
}
int index = references.IndexOf(element.stringValue);
EditorGUI.BeginProperty(position, new GUIContent("objective"), element);
int newIndex = EditorGUI.Popup(position, "Objective:", index, descriptions.ToArray());
if (newIndex != index)
{
element.stringValue = references[newIndex];
}
EditorGUI.EndProperty();
}
void DrawInventoryItemList(Rect position, SerializedProperty element, bool stackable = false, bool equipment = false)
{
BuildInventoryItemsList();
var filteredItems = items.Where(pair =>
(!stackable || pair.Value.IsStackable()) &&
(!equipment || pair.Value is EquipableItem))
.ToList();
var displayNames = filteredItems.Select(pair => pair.Value.GetDisplayName()).ToArray();
var ids = filteredItems.Select(pair => pair.Key).ToArray();
int index = Array.IndexOf(ids, element.stringValue);
EditorGUI.BeginProperty(position, new GUIContent("Item"), element);
int newIndex = EditorGUI.Popup(position, "Item", index, displayNames);
if (newIndex != index) element.stringValue = ids[newIndex];
EditorGUI.EndProperty();
}
void DrawTrait(Rect position, SerializedProperty element)
{
if (!Enum.TryParse(element.stringValue, out Trait trait))
{
trait = Trait.Strength;
}
EditorGUI.BeginProperty(position, new GUIContent("Trait"), element);
Trait newTrait = (Trait)EditorGUI.EnumPopup(position, "Trait:", trait);
if (newTrait != trait)
{
element.stringValue = $"{newTrait}";
}
EditorGUI.EndProperty();
}
private void BuildQuestList()
{
if (quests != null) return;
quests = AssetDatabase.FindAssets("t:Quest")
.Select(guid => AssetDatabase.LoadAssetAtPath<Quest>(AssetDatabase.GUIDToAssetPath(guid)))
.ToDictionary(quest => quest.name, quest => quest);
}
private void BuildInventoryItemsList()
{
if (items != null) return;
items = AssetDatabase.FindAssets("t:InventoryItem")
.Select(guid => AssetDatabase.LoadAssetAtPath<InventoryItem>(AssetDatabase.GUIDToAssetPath(guid)))
.ToDictionary(item => item.GetItemID(), item => item);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
SerializedProperty predicate = property.FindPropertyRelative("predicate");
float propHeight = EditorGUI.GetPropertyHeight(predicate);
PredicateType selectedPredicate = (PredicateType)predicate.enumValueIndex;
switch (selectedPredicate)
{
case PredicateType.Select: //No parameters, we only want the bare enum.
return propHeight;
case PredicateType.HasLevel: //All of these take 1 parameter
case PredicateType.CompletedQuest:
case PredicateType.HasQuest:
case PredicateType.PlayerHasItem:
case PredicateType.PlayerHasItems:
case PredicateType.PlayerHasItemEquipped:
case PredicateType.NPCHasItem:
case PredicateType.NPCHasItems:
case PredicateType.NPCHasItemEquipped:
return propHeight * 3.0f; //Predicate + one parameter + negate
case PredicateType.CompletedObjective: //All of these take 2 parameters
case PredicateType.MinimumTrait:
return propHeight * 4.0f; //Predicate + 2 parameters + negate;
}
return propHeight * 2.0f;
}
private static void DrawIntSlider(Rect position, string caption, SerializedProperty intParameter, int minLevel = 1, int maxLevel = 100)
{
EditorGUI.BeginProperty(position, new GUIContent(caption), intParameter);
if (!int.TryParse(intParameter.stringValue, out int value))
{
value = 1;
}
EditorGUI.BeginChangeCheck();
int result = EditorGUI.IntSlider(position, caption, value, minLevel, maxLevel);
if (EditorGUI.EndChangeCheck())
{
intParameter.stringValue = $"{result}";
}
EditorGUI.EndProperty();
}
}
}
Also I was curious how you could tell from the Profiler image that it is the Quest and Inventory GetFromID methods that are the cause. Thanks for your help