Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Problem with {get; set;}

Discussion in 'Scripting' started by BMM7, Dec 4, 2019.

  1. BMM7

    BMM7

    Joined:
    Sep 20, 2017
    Posts:
    54
    I have these two scripts:

    Code (CSharp):
    1. public class PlayerStats {
    2.  
    3.     private int health = 100;
    4.     private float strength = 500f;
    5.  
    6.     public float Strength { get; set; }
    7.  
    8.     public int Health {
    9.         get { return health; }
    10.         set { health = value; }
    11.     }
    12. }

    Code (CSharp):
    1. public class PlayerScript : MonoBehaviour {
    2.  
    3.     PlayerStats stats = new PlayerStats();
    4.  
    5.     void Start() {
    6.         Debug.Log("Player Health: " + stats.Health);
    7.  
    8.         Debug.Log("Player Strength: " + stats.Strength);
    9.     }
    10. }

    When I write get {return health; } and set {health = value; } prints the 'health' value to the console, but when I use the shorthand around property {get; set; } to print the value of the 'strength' field, it is printing the value 0, not the value 500 that I defined.

    Why can't I print the value 500? What is wrong with this shorthand?
     
  2. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    You didn't implement it the same as your Health property: you are not returning the strength field explicitly.

    Instead, you have an "auto-implemented property" which connects itself to a field created automatically by the compiler. This field won't be called strength, but something like __strength.

    Write out your Strength property in the same syntax as your Health property.
     
  3. BMM7

    BMM7

    Joined:
    Sep 20, 2017
    Posts:
    54
    I changed the 'strength' field to _strength, but it didn't resolve.
    Could you change the script and post it again with corrections? This will facilitate my understanding.
     
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    You can't guess what field name the auto-implemented properties will use. The compiler will always avoid a conflict with the fields you use explicitly.

    Code (CSharp):
    1. public class PlayerStats {
    2.  
    3.     private int health = 100;
    4.     private float strength = 500f;
    5.  
    6.    public float Strength {
    7.         get { return strength; }
    8.         set { strength = value; }
    9.  
    10.     public int Health {
    11.         get { return health; }
    12.         set { health = value; }
    13.     }
    14. }
     
  5. BMM7

    BMM7

    Joined:
    Sep 20, 2017
    Posts:
    54
    This syntax I already know how to use and write. Now I want to learn using {get; set}.

    My intention is to study the use of auto-implemented property, to know when to use them. That's why I used {get; set;}

    If I want to work with {get; set;} only, where can I use {get; set;} and how to write correctly?
     
  6. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,010
    Property is not a shortcut to a variable of the same name. (it can be when you want it to, as you have with Health)
    When you do float Strength {get;set;} compiler will create underlying variable (with some "unknown name").
     
  7. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    The property will work as you wrote it, but it won't get the values entered from the Unity editor. This is a limitation of the editor.

    I believe there are extensions you can install to support this scenario, but that's just beyond my area of expertise.
     
  8. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
  9. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,926
    If you're trying to make a game, there's no reason to use the {get; set;} thing. It solves an obscure problem that Unity can't have.

    A regular variable: "public float strength;" is just fine. If you want to turn it into a property later (like Health, except have it do something), you can without a problem.
     
    Kurt-Dekker and Madgvox like this.
  10. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    387
    For me property is just another place where to write code, if i don't need i don't use it.
    protected,
    private (eventually [SerializeField]),
    public (eventually [HideInTheInspector]) seems to do the trick most of the time.
     
  11. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I think this is what the topic starter was looking for:
    Code (csharp):
    1.  
    2. public class PlayerStats {
    3.  
    4.     public float Strength { get; set; }
    5.  
    6.     public PlayerStats() {
    7.         Strength = 500f;
    8.     }
    9. }
    10.  
    Default values (=500f) are only supported in a higher C# version. For now you'll have to use the constructor to assign a value.

    When fully public like this the main advantage over a field is that you can turn it into an abstract definition, which you can't do with a field.

    You can also make the setter private or protected, which enables you to restrict the writing access while keeping the reading access public. This split in access is also not possible with a field.
     
  12. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,192
    Check this out code written by @TheZombieKiller.

    https://forum.unity.com/threads/c-7-3-field-serializefield-support.573988/#post-3944824

    With the code in that link this:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class Enemy : MonoBehaviour
    4. {
    5.     [field: SerializeField]
    6.     [field: RenameField(nameof(Health))]
    7.     public float Health { get; set; } = 1.0f;
    8. }
    Results in this:
    upload_2019-12-4_19-41-51.png

    Unity added support for C# 7.3 (the required version to use default values) with 2018.3.

    https://blogs.unity3d.com/2018/12/13/introducing-unity-2018-3/
     
    Last edited: Dec 5, 2019
    eisenpony and jvo3dc like this.
  13. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,010
    I would seriously watch out with
    Code (CSharp):
    1. public float Health { get; set; } = 1.0f;
    If you are using it inside scriptableobject.

    Since it looks like ScriptableObject is serializing private variables.
    It is going to overwrite your default value.