So, right now i am making a game where i have a player and his stats and a monster and their stats. I have the variables in private so that things cannot accidently manipulate them. But i also use the get/set functions to make the variables accessed if used correctly. However, the variables with the get/set do not show up on the inspector in Unity. Is there a way that i can make these variables show up without making the base variables public?
using UnityEngine;
using System.Collections;
public class playerStats : MonoBehaviour {
//these are the base variables; they cannot be seen by other scripts
private int m_health = 10;
private int m_damage = 3;
private int m_strength = 2;
private int m_maxHealth = 10;
private int m_playerLevel = 1;
private int m_experience = 0;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
//these variables can be used by other scripts
//they take the values of the base variables
//however, they dont show up in the inspector
public int health
{
get { return m_health; }
set { m_health = value; }
}
public int damage
{
get { return m_damage; }
set { m_damage = value; }
}
public int strength
{
get {return m_strength; }
set {m_strength = value; }
}
public int maxHealth
{
get {return m_maxHealth; }
set {m_maxHealth = value; }
}
public int playerLevel
{
get {return m_playerLevel; }
set {m_playerLevel = value; }
}
public int experience
{
get {return m_experience; }
set {m_experience = value; }
}
public void HurtMonster(int monsterHealth)
{
monsterHealth -= m_damage;
}
}
P.S. If u couldnt tell by the title, i am using C#.
Sweet, the serilize field was exactly what i needed. I just needed to put it in front of my private variables like so:
SerializeField]
private int m_health = 10;
[SerializeField]
private int m_damage = 3;
[SerializeField]
private int m_strength = 2;
[SerializeField]
private int m_maxHealth = 10;
[SerializeField]
private int m_playerLevel = 1;
[SerializeField]
private int m_experience = 0;
[SerializeField]
private int m_monsterHealth;
Now, do u know if i can put only one SerializeField in front of a block of code so that all of them can become serialized? And to clarify…these objects arent public, they are just seen in the inspector, right?
I don’t know offhand but a quick way to test it would be to create a public value of the same type that could be seen in the inspector, and in the update function assign the private variable’s value to the public variable. Then try to change your serialied field and see what happens to your public value.
You could make it private and if I understand you question correctly try this:
[System.Serializable]
private class Health
{
public int strength
{
get {return m_strength; }
set {m_strength = value; }
}
[SerializeField]
private int m_strength;
}
[SerializeField]
private Health health;
Hope this answers you question. Now I may be wrong but hope this helps.
[SerialiazeField] causes compiler warnings when building using Microsoft’s .NET 4.5.1 instead of Mono.NET. Just in case you’re doing a Windows Phone or Windows Store build.
Unity, by default, only displays in the Inspector what is SAVED or CAN be saved on the disk.
Unity saves fields from a type deriving from UnityEngine.Object (MonoBehaviour/ScriptableObject), OR class with the [Serializable] attributes.
Only public fields are saved by default. Private fields are ignored, unless flagged with [SerializeField].
The Inspector will also ONLY display variable that Unity can save. For example, it will not display Hashtable, Dictionary, or nested list, because Unity is unable to save those types.
The Inspector only display fields, and ignore properties (get/set), events and methods.
If you want the inspector to work in any other way, you have to write your own Custom Editor. (Ex.: See my signature for Advanced Inspector)
I’ve not used it myself, but the OnValidate method in a MonoBehaviour could be useful for using setter methods via a default Inspector.
My untested assumption is that we could mark the backing fields with [SerializeField], make public setter methods which enforce whatever rules we want to have, and have an OnValidate method similar to the following:
[SerializeField]
private float privateBackingField = 0;
public float PublicAccessibleProperty {
get {
return privateBackingField;
}
set {
privateBackingField = Mathf.Clamp01(value);
}
}
void OnValidate() {
PublicAccessibleProperty = privateBackingField;
}
I believe this would mean that every backing field is re-applied via its public property each time an Inspector value is changed. As long as you don’t have any complex interdependencies between your properties this should be a pretty straightforward solution, in theory. (And even with complex interdependencies it shouldn’t be that much more difficult, since you can just call whatever you’re using to enforce them anyway.)
Heck, I bet you could even use reflection magic to automate this from a common subclass of MonoBehaviour.
Edit: Tested the above code. Works great. I will totally be using and abusing this from now on.
Edit 2: Of course the downside to this is that the getter isn’t actually being used by the Inspector, so if we’ve got any kind of data transformation going on there it’ll be getting ignored. So contrary to what I initially had written above, this is handy for applying rules on set but not so useful on get. For that I believe you would indeed need a custom Inspector, because you’re looking to change the basic rules by which Unity displays stuff in there. (Or… hacky approach… have separate private backing fields for the Inspector and for runtime, and update the Inspector fields via their getters at the end of OnValidate… but that’s really getting funky and I wouldn’t want to maintain it on a large codebase, and it still wouldn’t be particularly reliable for derived getters… I think a custom Inspector would be a clearer approach.)
You have it right that the getter isn’t used… And in some cases - in some project I have been on - it wasn’t enough. Data conversion between what is displayed and what is serialized is something we have done a lot of time.
Using properties to convert a format Unity is able to save from and back to a format the user is able to read is quite useful.
Is it possible to write a generic custom Inspector? I know that if we have ComponentX that if we write ComponentXInspector it does its thing. But can we write BaseClass and then have BaseClassInspector, will BaseClassInspector be used for derived classes? (I’ll test this myself if the answer isn’t known.)
An easier way to just see private variables in inspector (read only) is to put it into debug mode (top right corner). This way you don’t have to mess around with all that attributes cluttering your code. If you need to save those values anyway go with serializefield.