- Home /
Custom Inspector - How to add functionality?
Hello community,
I apologize in advance for not always using proper terms.
For the last 2 days I have been learning about how to modify the UI of the Inspector in Unity. I am quite happy with the result I have achieved so far. Today, I finished the basic structure and wanted to implement functionality. So far, when the user makes adjustments to something within the Inspector - those changes only affect the inspector and nothing else.
Basic Setup : I want to make my work easier. Instead of modifying tons of values each time I create a new "enemy" ,"player" or "npc" object - i just want to use my custom inspector. Here is some of the code I used :
using UnityEditor;
using System.Collections;
using UnityEngine;
[CustomEditor(typeof(HealthScript))]
public class ControlInterface : Editor {
// ---------------------- START VARIABLES ----------------------------------- //
SerializedObject serObj; // i have no idea what that is
private bool isActiveOnCharacter = true;
private bool useHealthTex =false;
private bool monoHealthBar = true;
private bool canRegenHealth = false;
private bool canAttack = false;
private string tagForObject="";
private string tagForEnemy ="";
private int characterTypeIndex;
private string[] characterTypeOptions = new string[4] {"not Defined", "Player","Mob (hostile)","NPC (neutral)"};
private string characterName="";
SerializedProperty myMaxHealth; // again not much of an idea how that works
private float myCurHealth = 0f;
private float regenRate = 0f;
private string[] RegenRateSamples = new string[4] {"slow","normal","fast","custom" };
private int regenIndex =0;
public Color green;
public Transform myEnemy;
private float baseDamage;
private float hitChance;
private float coolDown;
// ---------------------- End VARIABLES ------------------------------------- //
public void OnEnable(){ // got the idea for the following 2 code lines from an existing unity script ( antialiasing)
serObj = new SerializedObject(target);
myMaxHealth = serObj.FindProperty("myMaxHealth");
}
public override void OnInspectorGUI() {
EditorGUIUtility.LookLikeInspector();
isActiveOnCharacter = EditorGUILayout.Foldout(isActiveOnCharacter,"Character Setup:");
EditorGUILayout.Separator();
if(isActiveOnCharacter){
characterTypeIndex = EditorGUILayout.Popup("Character Type: ",characterTypeIndex, characterTypeOptions);
switch(characterTypeIndex){
// NOTHING CHOSEN
case 0:
// THis function resets some of the specific values previously entered
// and moreover is the default setting of "Character Type: ".
NotSpecified();
break;
// PLAYER CHOSEN
case 1:
// This function allows specifications about the Player object
// and contains several functions that are being shared by the
// different object types.
SpecifiedPlayerObject();
break;
// MOB CHOSEN
case 2:
// This function allows specifications about the Mob object
// and contains several functions that are being shared by the
// different object types.
SpecifiedMobObject();
break;
// NPC CHOSEN
case 3:
// This function allows specifications about the NPC object
// and contains several functions that are being shared by the
// different object types.
SpecifiedNPCObject();
break;
// Catch loopholes
default:
// Throw out a LogWarning - this message should never appear
// if it does scream at developer!
Debug.LogWarning("Something went wrong ...!");
break;
}
}
}
// ----------------------------Chosen Character------------------------------ //
private void NotSpecified(){
EditorGUILayout.BeginHorizontal("Button");
EditorGUILayout.LabelField( "Please specify character type!");
EditorGUILayout.EndHorizontal();
// ---------------Reset some Variables--------------- //
tagForObject="";
myMaxHealth = 0;
myCurHealth = 0;
regenIndex = 0;
regenRate = 0;
tagForEnemy ="";
// ---------------Reset some Variables--------------- //
}
private void SpecifiedPlayerObject(){
EditorGUILayout.BeginVertical();
SetupHealth ();
GUILayout.Box("", new GUILayoutOption[]{GUILayout.ExpandWidth(true), GUILayout.Height(1)});
PlayerOnlyHealthBarDisplay();
GUILayout.Box("", new GUILayoutOption[]{GUILayout.ExpandWidth(true), GUILayout.Height(3)});
SetupBasicAttack();
EditorGUILayout.EndVertical();
}
I have been trying to understand the basic principals using the Image Effect scripts from Unity. and in there it appeared as if they would simply say - every variable in my editor class is of type SerializedProperty and i would just assign the value inputed via
SerializedObject serObj;
some variable in my editor class =serObj.FindProperty("some variable I have in my "true" class);
i don't think that would work quite as I would want it to work.
Example :
I created a variable myMaxHealth in the Editor Class. (assume it was an int) . Then somewhere in the inspector I am storing a value to this variable :
myMaxHealth = EditorGUILayout.IntSlider(....);
I would like to have this value been the new value of my true myMaxHealth variable in the real HealthScript class (not the editor).
Can you help me ? . I really tried finding a solution, but I am struggling. I know, I am quite far off track with my solutions... - at least I think I am .
Thank you,
Daniel
Answer by vbbartlett · Feb 13, 2013 at 08:31 PM
Basics: target is the instance of the class that the editor is displaying.
Thus if you have
HealthScript hs = (HealthScript)target;
then if you actually want the gui controls to directly effect the instance you would do something like
hs.m_maxHealth = EditorGuiLayout.IntSlider(hs.m_maxHealth,...)
This sets the slider to the value of the instance and then when it changes applies that change back to the instance.
I have a very simillar question, and I always end up with NullReferenceException when I'm trying to get access to a list from target in editor
this one is equal to HealthScript:
public class EventScript : $$anonymous$$onoBehaviour {
public List<Action> actionList;
public class Action
{
float time;
FieldInfo[] fieldInfos;
object[] fieldValues;
public Action(float time, FieldInfo[] fieldInfos, string eventName)
{
this.time = time;
this.fieldInfos = fieldInfos;
this.fieldValues = new object[3];
}
}
void Awake()
{
actionList = new List<Action> ();
actionList.Add(new Action(5.56f, new FieldInfo[3], "name"));
actionList.Add(new Action(5.56f, new FieldInfo[3], "name"));
actionList.Add(new Action(5.56f, new FieldInfo[3], "name"));
}
// Use this for initialization
void CreateEvent()
{
// Call constructor of Event via reflection
}
}
and here I,m trying to get access to fields:
[CustomEditor(typeof(EventScript))]
public class EventEditor : Editor {
private EventScript the_script;
public List<EventScript.Action> actions;
void OnEnable()
{
the_script = (EventScript)target;
// How to get access to List<Action> "events" from currently editing instance's of EventScript?
for(int i = 0; i<the_script.actionList.Count; i++)
{
Debug.Log("WOW");
}
}
public override void OnInspectorGUI()
{
}
}
this causes error: NullReferenceException: Object reference not set to an instance of an object EventEditor.OnEnable () (at Assets/Editor/EventEditor.cs:16)
Unholy crap, I've found the problem! This works pretty fine in play mode!
Your answer
Follow this Question
Related Questions
Public Scene Variables not appearing in the inspector 2 Answers
Unity Editor - Class variable value contrain 4 Answers
ReImport in c# of GameObjects only for Scene Objects, not assets? 1 Answer
Parent Class variables in Child Class's Inspector (C#) 0 Answers
Editor Script, Index Out of Range Exception after Play 1 Answer