- Home /
(C#) Displaying custom class variables in inspector (State Machine)
I know the question may be a bit vague but basically all I'm trying to achieve is for some public variables to be shown in the inspector. To give some context, I have an AI base class (removed unnecessary code) here:
AI Base Class
using UnityEngine;
using System.Collections;
public class AI : MonoBehaviour
{
protected StateMachine SM;
protected virtual void Start()
{
// Setup state machine with state idle as default state
SM = new StateMachine(this, typeof(Idle));
}
protected virtual void Update()
{
// Acts out the current state update behavior
SM.UpdateState();
}
}
As you can see it contains an instance of the custom class StateMachine. It's simplified version is as follows:
State Machine Class
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System;
[System.Serializable]
public class StateMachine
{
// Reference to the owning AI
public AI OwningAI { get; private set;}
// A stack of states currently in the state machine
public Stack<State> StateStack { get; private set;}
// Default(initial) state of this state machine (Initialized in constructor)
private State DefaultState;
// Constructor
public StateMachine(AI DwarfObj, Type StateType)
{
OwningAI = DwarfObj;
StateStack = new Stack<State>();
// Initialization of the default state
if(StateType.BaseType == typeof(State))
DefaultState = (State)Activator.CreateInstance(StateType, this);
else
Debug.LogException(new Exception("Parameter 'StateType' must be of type 'State'"), OwningAI);
// Adding the default state to the state stack
PushState(DefaultState);
}
// Adds a new state to the top of the stack & calls the enter state method
public void PushState(State StateObj)
{
StateStack.Push(StateObj);
StateStack.Peek().EnterState();
}
// Calls the update method for the state at the top of the stack
public void UpdateState()
{
StateStack.Peek().UpdateState();
}
// Removes the state at the top of the stack & calls the exit state method
// Note: Will not pop first (default) state
public void PopState()
{
if (StateStack.Count > 1)
StateStack.Pop().ExitState();
else
Debug.LogWarning("Attempted to pop default state", OwningAI);
}
}
Take note of the use of the [System.Serializable] attribute and the property:
public Stack<State> StateStack { get; private set;}
Almost there. Here we have the abstract base class State in its entirety:
State Class
using UnityEngine;
using System.Collections;
[System.Serializable]
public abstract class State
{
// State machine reference
protected StateMachine SM { get; private set; }
public State(StateMachine StateMachineObj)
{
SM = StateMachineObj;
}
// Called at the beginning of the state
public abstract void EnterState();
// Called every tick during the state
public abstract void UpdateState();
// Called at the end of the state
public abstract void ExitState();
}
For the sake of example, here's the Idle state:
Idle State Example
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Idle : State
{
public Idle(StateMachine StateMachineObj) : base(StateMachineObj) { }
public int ShowMeInTheInspector;
public string MeTooPlease;
public override void EnterState()
{
Debug.Log("Idle Entry");
}
public override void UpdateState()
{
Debug.Log("Idle Update");
}
public override void ExitState()
{
Debug.Log("Idle Exit");
}
}
Question
Okay so this is exactly what I want to achieve; when selecting an object that inherits from class AI, I want the inspector to display all public variables in its Current State. Its current state is the state that's on the top of the State Stack in its State Machine instance. Which from the example would be the ShowMeInTheInspector float and the MeTooPlease string. However these variables should only be shown if the current state is Idle as different states have their own variables. What would be the best way to go about doing this?
Keep in mind that I am using multiple custom classes, child classes, stacks and properties.
Answer by GameVortex · Feb 28, 2015 at 02:29 PM
You have some nicely written code there. The functionality you describe will require some custom editor scripts in order to display your States properly. You will need to write some custom inspectors for your statemachine as Unity will not out of the box serialize abstract classes (your State class) or properties (your Stack), unity cannot serialize Objects of type Stack either for that matter, and serialization is what makes unity display the variables of MonoBehaviours to begin with. You might want to take a look at the VFW plugin which comes with a lot of functionality for serialization and inspector GUI, other than that you will as states have to create custom inspectors.
I appreciate the response. This VFW plugin is pretty much perfect for what I needed, after a few video tutorials and slight modifications.
I did attempt to write up custom editor scripts however I became quite disheartened once I realized I probably couldn't learn what I wanted to in an afternoon. Although I will try again when I do have the time.
I guess now, the challenge would be to make it easy to change default values of all available states per prefab.
Thanks again!
Does [SerializeField] / @SerializeField
not work in this case?
While I do want specific fields to be serialized, its what these fields are contained in that make it a problem. The float and int fields were contained on a custom class, which itself was referenced on a property stack in another custom class which was finally referenced on the component script where I wanted the information displayed.
Your answer
Follow this Question
Related Questions
moving gameobject from state machine behaviour/different code result from inside OnStateExit() 1 Answer
Inspector defined variable wiped away when game is built. 2 Answers
How to delete a StateMachineBehaviour via Editor Script? 1 Answer
Variables not showing up in inspector 1 Answer
The box for entering a variable's value in the inspector is not where it should be. 0 Answers