Worrying about not using properties

I’m quite far into the development of my game now, and currently I only use variables (mostly public atm). I’ve only just heard about properties, and after lots of reading I’m very worried that I should have used properties, bur I’m still not clear as to why they still hold be used instead other than the fact that public variables are deemed bad practice.

To give an example, my player base class has lots of variables for different stats. In other scripts I use GetComponent to call on and perform calculations using these stats. Is this bad practice then? Why use properties at all? What can you do with a property that you can’t do with a variable? To me it just seems like extra lines of code for no apparent reason, and as I haven’t used them before I’m clueless on how to call on them, and use them for calculations. If anyone could give a layman basic of a property, and it being used from another script I would appreciate it, and a description of why I should/shouldn’t use them. Thanks

The reason is you can do a bit more with properties. If you give direct access to a field, you can change it to whatever you want and nobody cares.

Think of enemy hp. As the target takes damage, you reduce it’s hp, but suddenly you’re in the negatives and the enemy is still walking. Now, normally you’d have a method probably checking it (this is also another way vs properties). However, a property uses get/set accessors to do something similar.

    int hp = 0;

    public int Hp {
        get
        {
            return hp;
        }
        set
        {
            if (value <= 0)
                print("Target is dead");
            else
                hp = value;
        }
    }

This may not be the best use case for it, but I hope it gives you an idea. (And I mean this, because I’d probably use a method and pass in the damage done).

The main point is, when you set a property, you have the ability to do more and perform additional operations. If you just set the field directly, you’ll have to do other things.

Now, that being said, you will probably not need to convert your fields to properties just because. If you are simply storing a value, you’ll probably be fine.

Note: Others may be able to give a better idea, this was just a quick type up.

1 Like

Short answer: don’t worry. You’re fine.

@Brathnann has one of the two use cases for properties. The other one is if you want to distinguish between who gets to get and set a value. The most common case is when you want to only set the value privately, but get allow other scripts to get it:

public int CurrentHP { get; private set; }

That would only let the script in question set the hp, but allow any other script to check it’s current value.

They’re also nice to give shorter names to things you need often:

public Vector3 Position { get { return transform.position; } { set { transform.position = value; } }

If this is a value that needs to be set from the inspector, you’ll need to use a field anyway, so properties are not a choice in that scenario.

1 Like

They are if you use the more verbose syntax and serialize the backing field.

[SerializeField]
private float _foo;

public float Foo { get { return _foo; } set { _foo = value; }}

Ultimately I think a lot of it comes down to explicitly stating how you want your API used. In the health example if you wrap the field in a property and make the setter private (or protected) then you can define a TakeDamage method that everyone else uses to actually decrease that thing’s health. You can also define a Heal method that adds to health. Then you’re describing that thing’s interface in terms of stuff that happens in game and not necessarily in what that stuff actually does to that thing (because that can, and will, change).

Thanks for the replies there guys, some good info. I know you say not to worry and I am fine doing what I am doing but, as this is my first game, I would really like to learn the right/best way to do things sooner rather than later.

So that’s how you would set a property in its parent script. What is the correct way of calling on and changing this property within another script?

Exactly like you might access a normal field!

public class PropertyHaver {
    public int anIntField;
    public int AnIntProperty { get; set; }
    public int APrivatelySetProperty { get; private set; }

    public PropertyHaver(int privateValue) {
        APrivatelySetProperty = privateValue;
    }
}

var propertyHaver = new PropertyHaver(27);
propertyHaver.anIntField = 75;
propertyHaver.AnIntProperty = 42;
propertyHaver.APrivatelySetProperty = 1; // This line will give you a compile error

Note that if the get or set is private then accessibility will change with it. You can only set the value of a property with a privater setter from inside the class itself.

In the above case, you can also use readonly fields. Readonly fields can only be assigned a value in the object’s constructor. This won’t work for classes derived from MonoBehaviour since there is no constructor to assign values in.

public class ReadonlyExample {
    public readonly int number;

    public ReadonlyExample(int number) {
        this.number = number;
    }
}

var rOnly = new ReadonlyExample(420);
rOnly.number = 6; // compile error!
Debug.Log(rOnly.number); // produces 420

So if I understand correctly, there’s nothing I can’t do with variables that I can do with properties? As @Brathnann said regarding hp going negative; I currently have an if statement within a function that checks this, whereas a property allows this to be nested within the property itself so to speak?

I’d love it if programmers just finished stuff and not worried about language features. Worrying about language features should happen when you try to solve problems, not because you read about it and thought “oh cool!”. Rookie mistake right there :slight_smile:

Regarding properties, you only need them if:

  • you want to run code when accessing them.
  • you want to limit access in a particular way.
  • you want to check changes (see running code when accessing).

So not really that useful for a solo dev. If you are making middleware or code for a team, or providing a solution for others, then I feel properties are very useful.

They’re slower and less useful if it’s just you trying to finish a game. They will add meaningless boilerplate and clutter for simple tasks. Use things when they are needed, not because they are there.

This is my own opinion and is not gospel even slightly. Programmers all have different opinions about properties.

1 Like

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.

1 Like

Yes. But if you aren’t doing any of that, there is no point wasting time on properties. As @hippocoder mentioned properties aren’t free, and come with some disadvantages.

One of the good things about OOP programming is that you can change between a property and a field at will, with none of your code being the wiser. So I tend to do everything as fields first. Then if I need to use a property, I will simply create a property with the same name as the field, and remove or rename the field.

The only time external code cares about properties vs fields is when you get into reflection. That’s not a topic that someone asking ‘what is a property?’ needs to know or care about.

1 Like

I disagree with hippocoder on the costs and disadvantages of using properties. They don’t even cost time, with a couple of snippets in Visual Studio. Unfortunately, if we all take the time to debate each other on this, we’ll hijack this poor guy’s thread and he’ll never get a proper answer. Myself, I’m almost always controlling access, invoking an event, or doing validation. It saves me a lot of work down the road tracking down bugs.

1 Like

Properties are a method call. Fields provide direct access. Which means a property is inherently slower then a field. Most of the time this doesn’t matter, but it can be important in critical code.

There isn’t a proper answer to this.

I would suggest just finishing the game as is, and only adding in properties if there is a clear advantage.

Stopping to rework code to implement every new technique you discover is a recipie to never finish the game.

Nah, compiler optimization’s got you there. I’m used to running thousands of agents and shaving off milliseconds. Properties don’t matter in those circumstances unless you’re doing things you shouldn’t. Profile it. I never recommended that he go back and refactor all his code, but he asked a question, and I gave the best practice as I understand it. You disagree, I get it.

Huh, in which case I stand corrected and much of my argument doesn’t stand up.

I still don’t like writing out properties. But my reasons seem to be reduced to ‘because I don’t wanna’.

As valid a reason as any.

2 Likes