howdy!
i made a small class and a custom inspector for it to more easily set the values for it. the inspector shows up just fine when i add this class/script to a gameobject, but the values always reset to the default starting values when i run the project and are never maintained. even if i set the values, click on a different object and then click back to it without running it, the values in the inspector always rest back to zero.
can anyone point out what i might be doing wrong here?
MiniPlanet c# class
using UnityEngine;
using System.Collections;
public class MiniPlanet : MonoBehaviour
{
public float rotationMod = 0.5f;
public Color planetColor = new Color(1.0f, 1.0f, 1.0f);
Transform tr;
// Use this for initialization
void Start ()
{
tr = this.transform;
}
// Update is called once per frame
void Update ()
{
tr.Rotate(0.0f, 360.0f * rotationMod * Time.deltaTime, 0.0f);
}
}
MiniPlanetInspector c# class:
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(MiniPlanet))]
public class MiniPlanetInspector : Editor
{
Color defaultMaterialColor = new Color(1.0f, 1.0f, 1.0f);
float selectedValue = 0.5f;
float minVal = 0.0f;
float maxVal = 1.0f;
public override void OnInspectorGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Rotation Modifier");
selectedValue = EditorGUILayout.Slider(selectedValue, minVal, maxVal);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Material Color");
defaultMaterialColor = EditorGUILayout.ColorField(defaultMaterialColor);
EditorGUILayout.EndHorizontal();
MiniPlanet mp = (MiniPlanet)Selection.activeTransform.GetComponent<MiniPlanet>();
mp.rotationMod = selectedValue;
if(mp.renderer)
mp.renderer.sharedMaterial.color = defaultMaterialColor;
EditorUtility.SetDirty (mp);
EditorUtility.SetDirty (this);
}
}
I think I know what your issue is. The way you are creating the editor fields is wrong from the way I understand how they are supposed to be used. Since you are specifying the value in the editor at the top, Unity feels the need to reset them. Instead, access the variables directly like the code below
[CustomEditor(typeof(MiniPlanet))]
public class MiniPlanetInspector : Editor
{
float minVal = 0.0f;
float maxVal = 1.0f;
public override void OnInspectorGUI()
{
MiniPlanet mp = (MiniPlanet)target;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Rotation Modifier");
mp.rotationMod = EditorGUILayout.Slider(mp.rotationMod, minVal, maxVal);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Material Color");
mp.planetColor = EditorGUILayout.ColorField(mp.planetColor);
EditorGUILayout.EndHorizontal();
}
}
And just to point you to some cleaner code, there are overrides to the EditorGUILayout methods that accept a string as the prefix label so you can eliminate the Begin/EndHorizontal calls and adding of a PrefixLabel. Here is what that looks like
[CustomEditor(typeof(MiniPlanet))]
public class MiniPlanetInspector : Editor
{
float minVal = 0.0f,
maxVal = 1.0f;
public override void OnInspectorGUI()
{
MiniPlanet mp = (MiniPlanet)target;
mp.rotationMod = EditorGUILayout.Slider("Rotation Modifier", mp.rotationMod, minVal, maxVal);
mp.planetColor = EditorGUILayout.ColorField("Material Color", mp.planetColor);
}
}
P.S.: Since you were setting the MiniPlanet’s renderer color in the editor, with this code you need to do it in the actual object itself. I would do it with a property’s set method with something along the lines of…
public class MiniPlanet : MonoBehaviour
{
public float rotationMod = 0.5f;
private Color _planetColor = new Color(1.0f, 1.0f, 1.0f);
Transform tr;
// Use this for initialization
void Start ()
{
tr = this.transform;
}
// Update is called once per frame
void Update ()
{
tr.Rotate(0.0f, 360.0f * rotationMod * Time.deltaTime, 0.0f);
}
public Color planetColor{
get { return _planetColor; }
set {
_planetColor = value;
if(renderer)
renderer.sharedMaterial.color = value;
}
}
}
shifty,
thanks much for the reply!
it makes sense that there should be an implicit target for a custom inspector, but i just didn’t see that or get it from the examples i was looking at.
the inspector now works perfect for the rotationMod variable, but not the color. i can set the color, and see it change on the miniPlanet gameobject, but when i run the project, the color resets to white. if i get rid of the get/set code from the planentColor struct and make the planetColor member variable public like the rotationMod one, it works fine. i’m still new to c# and wasn’t familiar with that get/set notation. have you used that before with unity and had it work ok?
-jesse
I am fairly new to custom inspectors myself and I agree the examples aren’t all that great. I just figured things out by just working in a test project with a script and custom editor to see what different types of editors do, what you can do with overrides, etc. So I suggest doing that since there aren’t many quality tutorials online.
I am a little confused how removing the property accessor from the code would make it work since I don’t see any other code that sets the renderer color, but if you figured it out that is good.
I can’t really say I have used property accessors in unity, but I see no reason why they shouldn’t work. The only time I see a need to code the Get and Set values like that is when you need to call extra code when the value changes. Otherwise, making it public should work fine. Just a side note, defining your own Get/Set properties like I mentioned above doesn’t automatically put them in the inspector. The only way I know how is to use custom inspectors.