为什么团结忽略的非静态公共领域的初始值? [英] Why is Unity ignoring the initialized value of a non-static public field?

查看:157
本文介绍了为什么团结忽略的非静态公共领域的初始值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 InvokeRepeating() 来调用一个游戏的方法。我称之为 InvokeRepeating()游戏对象开始()方法code>类。要设置 InvokeRepeating的 repeatRate 参数(),我路过它称为一个公共领域 secondsBetweenBombDrops

I'm using InvokeRepeating() to call a method in a game. I call InvokeRepeating() in the Start() method of one of the GameObject classes. To set the repeatRate parameter for InvokeRepeating(), I am passing it a public field called secondsBetweenBombDrops.

团结忽略我的代码为 secondsBetweenBombDrops 指定的值,而是使用一些默认值(即1)当 secondsBetweenBombDrops 没有static修饰符声明:

Unity ignores the value I specify for secondsBetweenBombDrops in the code and instead uses some default value (i.e. 1) when secondsBetweenBombDrops is declared without a static modifier:

public float secondsBetweenBombDrops = 10f;
void Start() {
    InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}



但是,一旦我添加静态修改为 secondsBetweenBombDrops ,代码的行为与预期和10的正确值的方法有:

However, once I add the static modifier to secondsBetweenBombDrops, the code behaves as expected and the correct value of 10 is used:

public static float secondsBetweenBombDrops = 10f;
void Start() {
    InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}



为什么这个领域需要静态修改使用适当的价值?

Why does this field require the static modifier to use the appropriate value?

在统一检查,脚本组件说明 secondsBetweenBombDrops 1。无论我是否实例化预制的游戏开始或游戏运行时创建预制情况下,这种默认值为1存在。

In the Unity inspector, the script component shows that secondsBetweenBombDrops is 1. This default value of 1 is present regardless of whether I instantiate the prefab on game start or create prefab instances while the game is running.

推荐答案

团结想使事情变得更容易为每个人,包括有限的人编码知识(初学者,设计师)。

The double-edged sword of serialization

Unity wants to make things easier for everyone, including people with limited coding knowledge (beginners, designers).

要帮助他们,在检查统一显示数据。这允许编码器进行编码,并通过调整值,而无需打开MonoDevelop的/一个IDE设计的设计师

To help them out, Unity displays data in the inspector. This allows the coder to code and the designer to design by tweaking the values without opening MonoDevelop/an IDE.

有两种方式都有价值的检查显示:

There are two ways to have values display in the inspector:

public int myVar = 10;
[SerializeField] private int myOtherVar = 0; // Can also be protected

第二个是更好,因为它的封装原则的规定(变量是私人/保护,并通过方法或属性)修改。

当您在编辑器中显示的变量,在脚本中给定的值仅用于拖动脚本时。团结再序列的价值观,不关心任何脚本修改了。如果,例如, myVar的被设定为20的事实后脚本内,这可能导致混乱,就不会被使用。序列化被写入场景文件

When you display a variable in the Editor, the value given in the script is only used when dragging the script. Unity then serializes those values and does not care about any script modification anymore. This can lead to confusion if, for instance, myVar is set to 20 inside the script after the fact, it will not be used. The serialization is written in the scene file.

在恰好相同的方式的示例工作的两行

The two lines in the example work exactly in the same way.

有可能得到统一按上的脚本组件的设置复位轮要考虑在脚本中的新值。这也将复位组件的所有其它变量,因此,只有这样做,如果该意图。

It is possible to get Unity to consider new values in a script by pressing Reset on the settings wheel of the script component. That will also reset all the other variables of the component, so only do this if that is intended.

使私有变量和省略的属性 [SerializeField] 将禁止序列化过程,因此统一将不再看在一个值显示场景文件 - 相反,该值将在运行时由脚本创建。

Making the variable private and omitting the attribute [SerializeField] will disable the serialization process, so Unity will no longer look in the scene file for a value to display - instead, the value will be created at runtime by the script.

当添加到统一的成分,将创建的组件的类型的新对象。所显示的值是来自该对象的序列的值。由于这个原因,只有成员值可以显示和静态变量都没有,因为它们不是可序列化。 (这是一个.NET的规范,不严格具体到Unity)。因为团结不序列静态字段,这就是为什么添加静态修改似乎解决问题。

When adding a component to Unity, a new object of the type of the component is created. The values that are displayed are the serialized values from that object. For this reason, only member values can be displayed and static variables are not, as they are not serializable. (This is a .NET specification, not strictly specific to Unity.) Because Unity does not serialize static fields, this is why adding the static modifier seemed to solve the problem.

在OP情况下,基于的意见,你的公共领域是显示在编辑器中值为1。你以为这个值默认的一种,当它实际上是你最有可能给到现场时,原本宣布它的价值。当你添加脚本作为一个组件,您所做的值10,并认为这是因为它仍然使用的值为1。你现在应该明白,它工作得很好,因为设计的车。

In the OP case, based on the comments, your public field was showing a value of 1 in the editor. You thought this value was a default one, when it was actually the value you most likely gave to the field when originally declaring it. After you added the script as a component, you made the value 10 and thought it was buggy as it was still using the value of 1. You should now understand that it was working just fine, as designed.

在默认情况下,统一将系列化和显示值类型(整型,浮点,枚举等),以及作为字符串,数组列表和MonoBehaviour。 (这是可以修改其与编辑器脚本的外观,但是这是题外话。)

By default, Unity will serialize and display value types (int, float, enum and so on) as well as string, array, List and MonoBehaviour. (It is possible to modify their appearance with Editor scripts, but this is off-topic.)

以下

public class NonMonoBehaviourClass{
   public int myVar;
}



默认情况下不序列化。这里再一次,这是.NET规范。统一序列化MonoBehaviour默认情况下为发动机的要求(这将保存内容到场景文件)的一部分。如果你想在编辑器中显示一个经典类,只是这么说:

is not serialized by default. Here again, this is .NET specification. Unity serializes MonoBehaviour by default as part of the engine requirement (this will save the content to the scene file). If you wish to display a "classic" class in the editor, just say so:

[System.Serializable]
public class NonMonoBehaviourClass{
   public int myVar = 10;
}



显然,你不能这样,你需要在使用添加到游戏对象一个MonoBehaviour:

Obviously, you cannot add it to a game object so you need to use within a MonoBehaviour:

public class MyScript:MonoBehaviour{
     public NonMonoBehaviourClass obj = new NonMonoBehaviourClass();
}

这将显示在检查对象,并允许修改 myVar的变量 NonMonoBehaviourClass 的实例。再次,在脚本中以 myVar的的任何更改将不考虑之后的值被序列化并存储到现场。

this will display the object in the inspector and allow modifications to the myVar variable in the instance of NonMonoBehaviourClass. And again, any changes to myVar within the script will not be considered after the value is serialized and stored to the scene.

要完成,接口不显示在检查或者因为它们不包含任何变量 - 只是方法和属性。在调试模式,属性默认不显示。您可以使用按钮三行在检查的右上角改变这种模式。前两个设置是正常/调试。第一个是默认的,第二还将显示私有变量。这是看他们的价值观有用,但不能从编辑修改。

To finish, interfaces are not displayed in the inspector either since they don't contain any variables - just methods and properties. In debug mode, properties are not displayed by default. You can change this mode using the button with three lines in the top right corner of the Inspector. The first two settings are Normal/Debug. The first one is the default one, the second will also display private variable. This is useful to watch their values but cannot be altered from editor.

所以如果你需要一个接口来显示,你就必须要考虑的一个抽象类,因为它提供。一个类似的功能(除了多继承)但也可以是一个MonoBehaviour

So if you need an interface to be displayed, you would have to consider an abstract class as it offers a similar functionality (except for multi inheritance) but can be a 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

这篇关于为什么团结忽略的非静态公共领域的初始值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆