x


Custom Editor Properties Revert to Defaults on Play

EDIT: I've more clearly figured out the problem, and made the code simpler to read.

I'm trying to create a manager class for flocking AI, so I can make one change and update every single member of the flock at once, rather than having to change the properties of every single member individually.

So I've got TestPropertyManager, which has an internal class called TestProperties. TestProperties is an internal class so that other internal classes can inherit from it in a way that mirrors the inheritance of the objects whose properties I'm managing.

using UnityEngine;
using System.Collections;

public class TestPropertyManager : MonoBehaviour
{
    public TestProperties TestManager = new TestProperties();

    public float TestA;
    public float TestB {get; set;}

            [System.Serializable]
    public class TestProperties
    {
       public float TestC;
       public float TestD {get;set;}
    }
}

Then I've got the custom inspector script, TestPropertyEditor, which just exposes the floats to the editor:

using UnityEditor;
using UnityEngine;

[CustomEditor (typeof(TestPropertyManager))]
public class TestPropertyEditor : Editor
{
    public override void OnInspectorGUI()
    {
       TestPropertyManager temp =    target as TestPropertyManager;

       temp.TestA = EditorGUILayout.FloatField("Test A", temp.TestA);
       temp.TestB = EditorGUILayout.FloatField("Test B", temp.TestB);

       temp.TestManager.TestC = EditorGUILayout.FloatField("Test C", temp.TestManager.TestC);
       temp.TestManager.TestD = EditorGUILayout.FloatField("Test D", temp.TestManager.TestD);

    }
}

The problem that I'm having with this system is that whenever I Play/Stop the game, the properties (TestB & TestD) revert to 0. The fields (TestA & TestC) retain the values they had in the editor. However, if I change TestA or TestC at runtime, then press Stop, they still revert to the values they had before pressing Play.

I also tried using SerializedProperty, but it had problems with the fact that Test belongs to TestManager, so I can't access Test with serializedObject.FindProperty(string propertyPath). I also can't get SerializedProperty to accept TestProperties, because it's not a type that it recognizes.

So basically I need the floats to persist when I press Play/Stop.

more ▼

asked Apr 23 '12 at 02:16 PM

Excrubulent gravatar image

Excrubulent
16 2 4 4

A development, but not quite there yet:

The [System.Serializable] attribute applied to the TestProperties class will allow TestC to persist when Play is pressed, but still not when Stop is pressed. Edited question to reflect this.

Apr 24 '12 at 04:18 AM Excrubulent
(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

This is a better answer than my other one, because it retains the private accessibility of the fields using [SerializeField].

Here's the updated version of TestPropertyManager that allows the property fields to persist on Play (although not on Stop):

using UnityEngine;
using System.Collections;

public class TestPropertyManager : MonoBehaviour
{
    public TestProperties TestManager = new TestProperties();
    public float TestA;

    [SerializeField]
    float _testb;

    public float TestB
    {
       get {return _testb;} 
       set {_testb = value;}
    }

    [System.Serializable]
    public class TestProperties
    {
       public float TestC;

       [SerializeField]
       float _testd;

       public float TestD
       {
         get{return _testd;}
         set
         {
          _testd = Mathf.Clamp(value, 0, UnityEngine.Mathf.Infinity);
         }
       }
    }
}

Notice the [SerializeField] attribute on the _testb and _testd fields. This allows Unity to retain their values while maintaining their private accessibility. I'm still using the same custom inspector script from the question.

Also, I've cast all my 3 votes for this feature request and would like to spread the word: If you also have this problem, go there and cast some votes.

Now the only problem is how to get those fields to persist on Stop. However, since this is a solution for one piece of the problem, I'm going to mark this question answered and start a new question.

more ▼

answered Apr 24 '12 at 05:34 AM

Excrubulent gravatar image

Excrubulent
16 2 4 4

(comments are locked)
10|3000 characters needed characters left

Add this code at the end of OnInspectorGUI() in your editor class:

if(GUI.changed)
{
     EditorUtility.SetDirty( target );
}

Reference: EditorUtility.SetDirty

more ▼

answered Apr 23 '12 at 03:24 PM

Kryptos gravatar image

Kryptos
7.2k 5 32

I was hoping it was some simple call that I had to make. Unfortunately it has no effect on the behaviour that I've described. Perhaps it's to do with the fact that I'm not changing the field directly, but instead changing a property that sets the field?

Apr 24 '12 at 12:35 AM Excrubulent

Never mind, read the updated question. SetDirty still doesn't have any effect.

Apr 24 '12 at 03:23 AM Excrubulent
(comments are locked)
10|3000 characters needed characters left

Okay, half-success. Here's the updated version of TestPropertyManager that allows the property fields to persist on Play (although not on Stop):

using UnityEngine;
using System.Collections;

public class TestPropertyManager : MonoBehaviour
{
    public TestProperties TestManager = new TestProperties();

    public float TestA;

    public float _testb;
    public float TestB
    {
       get {return _testb;} 
       set {_testb = value;}
    }

    [System.Serializable]
    public class TestProperties
    {
       public float TestC;

       public float _testd;
       public float TestD
       {
         get{return _testd;}
         set{_testd = value;}
       }
    }
}

Notice that TestB and TestD are accessing public fields _testb and _testd. This appears to be the only way to get Unity to not reset these fields when play is pressed. It's not ideal, because I'd like those fields to be private, but since I'm using a custom inspector, I can hide them from the inspector, which will do for now. No-one else will be using this code for the moment.

Also, I've cast all my 3 votes for this feature request and would like to spread the word: If you also have this problem, go there and cast some votes.

Now the only problem is how to get those fields to persist on Stop. However, since this is a solution for one piece of the problem, I'm going to mark this question answered and start a new question.

more ▼

answered Apr 24 '12 at 04:31 AM

Excrubulent gravatar image

Excrubulent
16 2 4 4

I'm leaving this answer here so future forum spelunkers can see the process I went through.

Apr 24 '12 at 05:35 AM Excrubulent
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x4163
x76
x33

asked: Apr 23 '12 at 02:16 PM

Seen: 1158 times

Last Updated: Apr 24 '12 at 05:35 AM