| Keywords | public, private, protected, internal, static, const, readonly, get, set |
|---|---|
| Category | Classes |
| In Unity | [SerializeField] private fields, Time.deltaTime (static property) |
Fields, Properties & Modifiers
A field is a variable that belongs to a class. A property looks like a field from the outside but runs code when you read or write it. Modifiers control who can see a member (public, private) and how it behaves (static, const, readonly).
Access modifiers
| Modifier | Who can use it |
|---|---|
private | Only code inside this class. The default if you write nothing. |
protected | This class and classes that inherit from it. |
internal | Any code in the same assembly (for most Unity projects, all your scripts). |
public | Anyone. |
Rooms in a house. private is your bedroom: only you go in. protected is the family room: you and your children. internal is the whole house: anyone who lives there. public is the front yard: anyone passing by.
Unity adds a twist: whether a field shows in the Inspector is separate from who can access it in code. public fields and [SerializeField] private fields show up; plain private ones don't. See Better Ways to Do Things.
Properties
A property has a get (runs when read) and/or a set (runs when assigned; the new value is called value).
public class Health : MonoBehaviour
{
[SerializeField] private float max = 100f;
private float current;
// Read-only from outside: others can see it but not change it.
public float Current => current; // "=>" is short for a get that returns this
// Computed property: no stored value, calculated each time.
public float Percent => current / max;
public bool IsDead => current <= 0f;
// Full property with validation.
public float Max
{
get { return max; }
set
{
max = Mathf.Max(1f, value); // never allow 0 or negative
current = Mathf.Min(current, max);
}
}
// Auto-property: C# creates the hidden field for you.
public int Deaths { get; private set; } // anyone can read, only this class can write
}
// Using it: looks just like fields
if (health.IsDead) Respawn();
healthBar.fillAmount = health.Percent;
health.Max = 150f; // runs the set code
// health.Deaths = 0; // error: the setter is private
A field is an open box: anyone can reach in and swap what's inside. A property is a box with a shop assistant in front. When you ask for the contents, the assistant can check, calculate or refuse. From the outside, you just "ask the box".
[field: SerializeField] public int Deaths { get; private set; } .static
A static member belongs to the class itself, not to any one object. There's only one copy, shared by everything.
public class Enemy : MonoBehaviour
{
public static int AliveCount; // one number shared by ALL enemies
void OnEnable() { AliveCount++; }
void OnDisable() { AliveCount--; }
}
// Read it without any enemy reference:
if (Enemy.AliveCount == 0) OpenExitDoor();
You've used static members already: Time.deltaTime, Mathf.Clamp, Vector3.zero, Debug.Log. A static class can only contain static members and can't be instantiated; it's used for helpers like Mathf.
const and readonly
const | readonly | |
|---|---|---|
| Set when? | At compile time, in the declaration | In the declaration or the constructor |
| Allowed types | Numbers, bool, char, string, enums | Any type |
| Automatically static? | Yes | No (add static yourself) |
| Example | const string SaveKey = "Save"; | static readonly int SpeedId = Animator.StringToHash("Speed"); |
public class Player : MonoBehaviour
{
private const int MaxLives = 3; // never changes
private static readonly Color HurtColor = new Color(1f, 0.3f, 0.3f); // not a compile-time constant
private readonly List<Item> items = new List<Item>(); // the LIST can't be replaced, but you can Add to it
}
What happens at runtime
- Each object gets its own copy of every non-static field. 100 enemies = 100
currenthealth values. - Static fields exist once, created the first time the class is used, and live until the app (or the Editor's script domain) reloads.
- A property is really a pair of hidden methods (
get_Current(),set_Max(value)). Simple ones are usually inlined, so they cost about the same as a field. constvalues are pasted directly into the code where they're used at compile time.
Common Mistakes
- Making everything public "so it works". Now any script can break your object's state. Default to private; open up only what's needed.
- Using static to share data between objects that aren't really global. Two players in local multiplayer would share one "static health". Use references instead.
- A property that calls itself:
public float Speed { get { return Speed; } }causes aStackOverflowException. Return the backing field (speed), not the property (Speed).
See also
- Inheritance & Interfaces
- Attributes (
[SerializeField]and friends)
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Microsoft C# documentation.