FindRelativeProperty never worked for me? how does it even work?

Using serialized properties/objects is very beneficial - but I always ran away from them in editor code cause I was never able to get a non-null/legit value out of FindRelativeProperty #-_______-

Here’s what I have:

FSMTrigger.cs

  public class FSMTrigger : BaseTrigger, Interaction
  {
	public List<FSMTriggerState> states = new List<FSMTriggerState>();
        // stuff...
  }

FSMTriggerState.cs

public class FSMTriggerState : MonoBehaviour
{
	public List<int> ints = new List<int>() { 1, 2, 3, 4, 5 }; // for testing
	public List<FSMTriggerTransition> transitions = new List<FSMTriggerTransition>();
	public FSMStateType stateType = FSMStateType.Other;
}

FSMTriggerTransition.cs

  [ExecuteInEditMode]
  public class FSMTriggerTransition : MonoBehaviour
  {
	[HideInInspector] public List<EventDelegate> onTransition = new List<EventDelegate>();
	public FSMTriggerState toState;
    // stuff...
  }

For the sake of completeness:

public abstract class BaseTrigger : MonoBehaviour
{
   // stuff...
}

public interface Interaction
{
	void Interact(UnityEngine.GameObject actor);
}

Here’s what I’m doing:

FSMTriggerEditor.cs

void Test()
{
		var spStates = serializedObject.FindProperty("states");
		for (int i = 0; i < spStates.arraySize; i++) {
			Debug.Log("STATE TYPE: " + spStates.GetAt(i).GetValue<FSMTriggerState>().name);  // <--- THIS WORKS
		}

		var ints = spStates.FindPropertyRelative("ints");
		for (int i = 0; i < ints.arraySize; i++) {
			Debug.Log("Numbers: " + ints.GetAt(i).GetValue<int>()); // THIS DOESN'T
		}

		var spTransitions = spStates.FindPropertyRelative("transitions");
		for (int i = 0; i < spTransitions.arraySize; i++) {
			Debug.Log("Transitions: " + ints.GetAt(i).GetValue<FSMTriggerTransition>().name); // NOR THIS
		}

}

I wanted to make sure that the problem is NOT with the state class itself, so I went ahead and:

FSMTriggerStateEditor.cs

private void test()
{
	var spTransitions = serializedObject.FindProperty("transitions");
	for (int i = 0; i < spTransitions.arraySize; i++) {
		Debug.Log("Transitions names: " + spTransitions.GetAt(i).GetValue<FSMTriggerTransition>().name); // THIS WORKED! SO AS THE INTS OF COURSE
	}
}

So it’s pretty obvious that FindRelativeProperty isn’t working right - maybe I just don’t know how to use it - but I’ve seen a lot of scripts just reference the thing like I did - there’s no special path - just the name of the variable I want to fetch. Yet it’s not working with me - I get null reference exceptions. Even if I try the simplest of examples :frowning:

Any help would be greatly appreciated - thank you very much in advance.

EDIT: There was a mistake in the test script using FindRelativeProperty - although I fixed that, it’s still giving me a null ref:

	var spStates = serializedObject.FindProperty("states");
	for (int i = 0; i < spStates.arraySize; i++) {
		var state = spStates.GetAt(i);
		Debug.Log("STATE TYPE: " + state.GetValue<FSMTriggerState>().name); // WORKS

		var ints = state.FindPropertyRelative("ints");
		for (int j = 0; j < ints.arraySize; j++) { // BREAKS HERE - MEANING INTS IS NULL
			Debug.Log("Numbers: " + ints.GetAt(j).GetValue<int>());
		}
	}

EDIT:

Forums crosslink.

Hey vexe!

I always run into issues with Unity’s serialization when working on editor code. In my experience the SerializedProperty.FindPropertyRelative method is not meant to be used when the SerializedProperty is referring to a MonoBehaviour-derived object (like your FSMTriggerState object is), I’ve only had success using it when the object being referred to is a regular class decorated with the [Serializable] attribute.

For SerializedProperties that reference MonoBehaviours you could new up an instance of a SerializedObject passing in SerializedProperty.objectReferenceValue (if it isn’t null) to the constructor, then do a regular FindProperty off of that. But in your case you’re actually dealing with a List of MonoBehaviours, so you’d have to do that for each element (or else pass in the entire array, but I think that’ll have unintended consequences) and may want to consider a different approach altogether. It’s possible that your FSMTriggerState class shouldn’t be a MonoBehaviour at all - and if it should, then you’ll probably have to accomplish what you want in its own editor instead of trying to access it from another.

I hope that helps - Unity editor details really can be a pain sometimes, and the documentation really isn’t as clear as it should be. Good luck though!

Same as @vexe I’ve list of serializedProperties in reorderable list. So If I want subproperty of those property I need
private void DrawConditionsElement (Rect rect, int index, bool selected, bool focused)
{

			SerializedProperty eventConditionSerializedProperty = this.m_ConditionList.serializedProperty.GetArrayElementAtIndex (index);

SerializedProperty eventFieldSP=new SerializedObject(eventConditionSerializedProperty.objectReferenceValue).FindProperty("eventField");
}

public class EventCondition:ScriptableObject{
  public UnityEvent eventField;
}

So not just in MonoBehavours but also in ScriptableObject FindPropertyRelative is useless. What bother me is that now I need to keep array of eventFieldSP, keep track of add remove, not to do newing every draw.