0

I have this code and my objective is to modify the field value to be used in any method in the abstract class. What I understand is that:

  • You can create a field (e.g. private int speed)
  • Create a property to modify its value (public int Speed {get;set;} or public int Speed {get => speed ; set => speed = value;}

But the editor (variables are not modified there, it is hard code) doesn't throw the expected result, it is, to modify the speed field value. A clear and concise explanation is appreciated. enter image description here

Hernando N
  • 305
  • 3
  • 7

3 Answers3

3

In your code, fireRate and FireRate are completely separate field/property as well as speed and Speed. Modifying fireRate won't affect FireRate and vice versa.

SerializeField is used to serialize fields not properties. In both cases only fields(fireRate and speed) are serialized.

Try below code:

    [SerializeField] public int a;
    [SerializeField] public int b { get; set; }
    [SerializeField] public int c => a;

Unity doesn't serialize property by default and only a will be serialized.

MarkSouls
  • 982
  • 4
  • 13
  • 1
    Not the answerer, but if it solved your question, make sure to accept the question as answered (the little check mark) below the upvote/downvote part. – gbe May 11 '21 at 02:56
  • Got it [ken](https://stackoverflow.com/users/15667460/ken). Still waiting for an answer about "what the auto-implemented property is useful for" – Hernando N May 11 '21 at 03:13
  • 1
    @HernandoN Usefulness of property is a whole new domain of discussion so I'll just leave the link: https://stackoverflow.com/questions/9304/c-sharp-3-0-auto-properties-useful-or-not – MarkSouls May 11 '21 at 04:29
  • @HernandoN to answer your question in simple terms: Unity did hijack C#, a language that wasn't made for it and is not even used properly by the engine. Auto properties make sense in scenarios where you are not working with Unity. – Max Play May 11 '21 at 12:06
3

[SerializeField] marks fields.

Properties are syntactic sugar for methods getting/setting a value.

When you declare a property like public int Speed {get;} a hidden backing field is generated by the compiler which is where the value is actually stored, this field is private and so will not be serialized automatically by Unity's serializer. (Additionally the compiler will generate a method public int get_Speed() which is the implementation of the property's get you can verify this by declaring this method yourself, the compiler should complain about a member with the same signature already existing.)

C# 7.3 added Auto-implemented property field-targeted attributes, allowing you to do this:

[field:SerializeField] public int Speed {get;}

This will apply the SerializeField attribute to the hidden generated field and Unity should serialize it normally. Note that the name of this hidden field will have the special name <Speed>k__BackingField something to keep in mind if you plan to implement a custom inspector or property drawer.

1

You are confusing the terms "field" and "property". Properties can implement additional behavior in the getter and setter.

First of all: Unity does not serialize properties!

This limits the purposes of properties in Unity to the runtime.

So most of the time will want to go for a pattern like

[SerializeField] private int a;
public int A => a;

This e.g. serves the purpose that you can assign a value via the editor, edit it by the class itself but allow others only readonly access => Encapsulation.

And of course for completeness it can perform additional sanity checks like e.g.

private const int min = -3;
private const int max = 17;
private bool allowSet;

[SerializeField] private int a;
public int A 
{
    get => a;
    set 
    {
        if(allowSet) a = Mathf.Clamp(a, min, max);
    }
}

An auto-property (in my eyes) is barely needed except you want to directly limit the access like

public int b { get; private set;}

This allows only this class to write but everyone else to read this value

So when something is useful is mostly subjective and depends on the situation.


Now looking at your code there is absolutely no relationship between Speed - speed and FireRate-fireRate! They are completely independent fields and properties.

The confusion here is probably due to the display names that the Inspector creates. It automatically makes all field names capitalized so

[SerializeField] private int _example;

will be displayed as Example.

You most probably would simply go for

[SerializeField] protected float Speed;
[SerializeField] protected float FireRate;
derHugo
  • 83,094
  • 9
  • 75
  • 115