You will want to read up on the concept of encapsulation, as it applies to programming. Properties are the modern evolution of this fundamental OOP practice. The idea is that if you give other classes direct access to your class variables (they’re called fields, in the world of C#), those classes can modify that variable in unexpected and possibly dangerous ways. By putting a layer of code in between, you protect your code by controlling access and being able to validate the values set to your fields. With properties, you can limit access, so that the value of a field can be read but not set, or only set within the class. You can validate the value being set, and if for example it shouldn’t be null, you can throw an error so that the writer of the calling code knows what they’re doing wrong, rather than creating a subtle bug that can take weeks to track down. Encapsulation also means that you can debug the set values of a field easily (very nifty for finding bugs where multiple classes set the value of a field in a single frame), and makes setting up events based on the set value easy. Also handy for buffer-like situations, where you want to clear the value when it’s accessed.
There’s two kinds of properties, auto-implemented which looks like this:
// Private property
float AutoProperty { get; set; }
And a property with a backing field, which looks like this:
// Public property with a private setter. Anybody can read the value, only this class can set it.
public float AutoProperty { get { return someField; } private set { someField = value; } }
For Unity, properties aren’t exposed to the editor, so if you want to have proper encapsulation while exposing the value to the editor, you do this:
// Public property backed by a field, with no setter. This protects m_encapsulatedFloat from being set by other classes while allowing them to read the value. We could also do a setter with no getter, if we didn't want them to be able to access the value of this field but be able to set it.
[SerializeField]
private float m_encapsulatedFloat;
public float EncapsulatedFloat { get { return m_encapsulatedFloat; } }
As for how they’re used, you use properties exactly like you would a field:
float encapsulated = EncapsulatedFloat;
Basically, ALWAYS use encapsulation for public access. It will make your code cleaner and harder to break, make debugging easier, and save you refactoring.