I know proper and structured programming would state that all variables should have getters/setters, but in the Unity3D environment is this recommended? Due to the strict typecasting of variables in C# (I don’t use the var keyword) is there an inherit danger to using purely public variables.
Other than the obvious issue that one can not control the value of these variables, is there a reason in this setting not to use public variables to facilitate inter-script communication?
I’m not sure what you mean by strict typecasting - could you elaborate?
In general, a far more important issue than properties vs. fields is making your code express its intended purpose.
Consider:
class MyCoolPlayer : MonoBehaviour
{
public int coins;
}
class MyCoolPlayer : MonoBehaviour
{
public int Coins { get; set; }
}
For most purposes, the second bit of code hasn’t really changed anything for you - any other class in the program can still read AND write the Coins value.
However, consider this:
class MyCoolPlayer : MonoBehaviour
{
public int Coins { get; private set; }
}
This code is better because it makes it clear that while anyone should be able to read the value of Coins, only the Player class should be able to change it.
tl;dr: Write your code to express its purpose, rather than writing it to obey (often arbitrary or unrelated) methodologies. Object orientation, MVVM, etc are tools to complete a job, not strict guidelines that you’re heathen if you don’t obey.
If you’d like an example of good code structure more relevant to your specific project, feel free to ask.
class MyClass : MonoBehavior
{
private int _coins;
public int Coins {
get {
return _coins;
}
set {
_coins = value;
}
}
}
Is this recommended or in Unity’s case is just making variables public ok? For the most part it seems it’s encouraged since it gives you editor access to the fields.
@Slev The var keyword is not weak typing, ie the variable type is determined by the compiler, and the type is not guessed at runtime(like python). Var is not recommended because it can make the code confusing. As for public variables, the only issue is that they are exposed in the inspector, I would advise you only make variables public that really need to be.
Sometimes its not a good idea to give inspector access to variables, It can get messy and you may forget(I do) what variables should be set in the inspector, and which ones are just for show. However keep it public if you were going to hard code said variable anyway.
If you’re creating a MonoBehavior, and you want to expose a value to the editor, then fields are your only option. Properties don’t show up in the editor.
As far as the pro’s and cons? One is performance. Public fields might perform better than properties. I say might because it’s really up to the JIT compiler. In .NET (i.e. not Mono), property getters and setters that have no other code than backing field access may be optimized away by the JIT compiler, so a speed difference doesn’t exist in that scenario. But then again, if the JIT compiler is having a bad day, or it doesn’t like the way you’re referencing your property in your other code, maybe it won’t. It’s not something you can control. If you make it a field, the JIT compiler has no option. Don’t know if Mono’s JIT (does it even use a different JIT on Windows?) will do the same or not.
Of course, if you want to do some other processing when the value changes (like firing an event), then you have no choice but to use a property.
I often use [SerializeField] on my private variables that I don’t want to be accessed from other classes, but that I do want to show in the inspector.
And if I use a public field that I don’t want to show in the inspector, I use [HideInInspector] to hide it from there.
Also, if I know I need to read/write values from other classes, I just make it public. What’s the point of making a property with both a getter and a setter if all you’re doing is returning the value and setting the value? If you’re going to include some extra code in there, then sure. But if all you’re doing is saying
get { return x; }
set { x = value; }
You might as well make it public, right?
I use properties when I want extra code or when I only want it to be read but not written to.
This really depends, for instance like JasonBricco stated when you want to be able to possibly edit the value via inspector cool use [SerializeField], what this does is allow the field to be seen in the inspector but not be accessible directly outside the class. If you want to be able to read then you can do
[SerializeField]
private float someField;
// This is a read only property.
public float SomeField {
get {
return this.someField;
}
}
// This is still a read only property.
// but with advantages such as
// allowing xml serialization to still occur
// without making the variable public.
public float SomeField {
get {
return this.someField;
} private set {
this.someField = value;
}
}
// This is a read / write property.
// This approach can be dangerous,
// Data Encapsulation is being violated
// as you are exposing the variable to outside
// mutation. A better approach would be to
// evaluate the 'value' keyword first.
public float SomeField {
get {
return this.someField;
} set {
this.someField = value;
}
}
// This is a better approach as
// you are checking the value of
// 'value' to ensure it s not zero for this example.
// This is good to ensure you do not divide by zero
// if someField was the denominator of some logic.
public float SomeField {
get {
return this.someField;
} set {
if(value != 0) {
this.someField = value;
}
}
}
In the end there is no right or wrong answer because it depends on the situation, once the conditions in which the logic will be written has been established then we can talk about right and wrong.