Yve*_*omb 37 c# serialization access-modifiers unity-game-engine
我InvokeRepeating()
用来在游戏中调用方法.我调用其中一个 类InvokeRepeating()
的Start()
方法GameObject
.要设置repeatRate
参数InvokeRepeating()
,我传递一个名为的公共字段secondsBetweenBombDrops
.
Unity忽略了我secondsBetweenBombDrops
在代码中指定的值,而是在secondsBetweenBombDrops
没有静态修饰符的情况下声明时使用了一些默认值(即1):
public float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
Run Code Online (Sandbox Code Playgroud)
但是,一旦我添加static
修饰符secondsBetweenBombDrops
,代码就会按预期运行,并使用正确的值10:
public static float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
Run Code Online (Sandbox Code Playgroud)
为什么此字段要求static
修饰符使用适当的值?
在Unity检查器中,脚本组件显示secondsBetweenBombDrops
为1.无论是在游戏开始时实例化预制件还是在游戏运行时创建预制实例,都会显示此默认值1.
Eve*_*rts 38
Unity希望让每个人都能更轻松,包括编码知识有限的人(初学者,设计师).
为了帮助他们,Unity在检查器中显示数据.这允许编码器编码和设计者通过调整值来设计,而无需打开MonoDevelop/IDE.
有两种方法可以在检查器中显示值:
public int myVar = 10;
[SerializeField] private int myOtherVar = 0; // Can also be protected
Run Code Online (Sandbox Code Playgroud)
第二个更好,因为它符合封装原则(变量是私有的/受保护的,并通过方法或属性进行修改).
在编辑器中显示变量时,脚本中给出的值仅在拖动脚本时使用.然后,Unity会对这些值进行序列化,而不再关心任何脚本修改.例如,如果myVar
在脚本内部设置为20之后,这可能会导致混淆,因为它不会被使用.序列化写在场景文件中.
示例中的两行完全以相同的方式工作.
通过在脚本组件的设置轮上按Reset,可以让Unity在脚本中考虑新值.这也将重置组件的所有其他变量,因此只有这样做才有意义.
将变量[SerializeField]
设为私有并省略该属性将禁用序列化过程,因此Unity将不再在场景文件中查找要显示的值 - 而是由脚本在运行时创建该值.
向Unity添加组件时,会创建组件类型的新对象.显示的值是该对象的序列化值.因此,只能显示成员值而不能显示静态变量,因为它们不可序列化.(这是一个.NET规范,并不是Unity特有的.)因为Unity不会序列化静态字段,所以添加static
修饰符似乎可以解决问题.
在OP案例中,根据注释,您的公共字段在编辑器中显示值1.您认为这个值是默认值,当它实际上是您最初声明时最有可能给该字段的值.在您将脚本添加为组件之后,您将值设置为10并认为它是错误的,因为它仍然使用值1.您现在应该理解它按照设计正常工作.
默认情况下,Unity将序列化并显示值类型(int,float,enum等)以及string,array,List和MonoBehaviour.(可以使用编辑器脚本修改它们的外观,但这是偏离主题的.)
下列:
public class NonMonoBehaviourClass{
public int myVar;
}
Run Code Online (Sandbox Code Playgroud)
默认情况下未序列化.这也是.NET规范.Unity默认将MonoBehaviour序列化为引擎要求的一部分(这会将内容保存到场景文件中).如果您希望在编辑器中显示"经典"类,只需这样说:
[System.Serializable]
public class NonMonoBehaviourClass{
public int myVar = 10;
}
Run Code Online (Sandbox Code Playgroud)
显然,您无法将其添加到游戏对象中,因此您需要在MonoBehaviour中使用:
public class MyScript:MonoBehaviour{
public NonMonoBehaviourClass obj = new NonMonoBehaviourClass();
}
Run Code Online (Sandbox Code Playgroud)
这将在检查器中显示对象,并允许修改myVar
实例中的变量NonMonoBehaviourClass
.同样,myVar
在序列化值并将其存储到场景后,将不会考虑脚本内的任何更改.
要完成,接口不会显示在检查器中,因为它们不包含任何变量 - 只是方法和属性.在调试模式下,默认情况下不显示属性.您可以使用检查器右上角有三行的按钮来更改此模式.前两个设置是Normal/Debug.第一个是默认值,第二个也显示私有变量.这对于观察它们的值很有用,但不能从编辑器中更改.
因此,如果您需要显示一个接口,则必须考虑一个抽象类,因为它提供了类似的功能(多继承除外),但可以是MonoBehaviour.
参考文献:
http://docs.unity3d.com/ScriptReference/SerializeField.html
http://docs.unity3d.com/Manual/script-Serialization.html
https://www.youtube.com/watch?v=9gscwiS3xsU
https://www.youtube.com/watch?v=MmUT0ljrHNc
归档时间: |
|
查看次数: |
7804 次 |
最近记录: |