问题描述
我有这段代码,我的目标是修改要在抽象类中的任何方法中使用的字段值。 我的理解是:
- 您可以创建一个字段(例如
private int speed
) - 创建属性以修改其值(
public int Speed {get;set;}
或public int Speed {get => speed ; set => speed = value;}
但是编辑器(那里没有修改变量,它是硬代码)不会抛出预期的结果,而是修改 speed
字段值。
一个清晰和简洁的解释表示赞赏。
解决方法
在您的代码中,fireRate
和 FireRate
是完全独立的字段/属性以及 speed
和 Speed
。修改 fireRate
不会影响 FireRate
,反之亦然。
SerializeField
用于序列化字段而不是属性。在这两种情况下,只有字段(fireRate
和 speed
)被序列化。
试试下面的代码:
[SerializeField] public int a;
[SerializeField] public int b { get; set; }
[SerializeField] public int c => a;
Unity 默认不会序列化属性,只会序列化 a
。
您混淆了术语 "field" 和 "property"。属性可以在 getter 和 setter 中实现额外的行为。
首先:Unity 做了not serialize properties!
这将 Unity 中属性的用途限制为运行时。
所以大多数时候会想要一个像
这样的模式[SerializeField] private int a;
public int A => a;
这例如其目的是您可以通过编辑器分配值,由类本身对其进行编辑,但仅允许其他人只读访问 => 封装。
当然,为了完整性,它可以执行额外的健全性检查,例如
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);
}
}
几乎不需要自动属性(在我看来)除非你想直接限制访问
public int b { get; private set;}
这仅允许此类写入,但其他所有人都可以读取此值
因此,什么时候有用是主观的,取决于具体情况。
现在查看您的代码,Speed
- speed
和 FireRate
-fireRate
之间绝对没有关系!它们是完全独立的字段和属性。
这里的混淆可能是由于 Inspector 创建的显示名称。它会自动使所有字段名称大写,以便
[SerializeField] private int _example;
将显示为 Example
。
你很可能只会选择
[SerializeField] protected float Speed;
[SerializeField] protected float FireRate;