InvokeRepeating()
を使用して、ゲームのメソッドを呼び出しています。 GameObject
クラスの1つのInvokeRepeating()
メソッドでStart()
を呼び出します。 InvokeRepeating()
のrepeatRate
パラメーターを設定するには、secondsBetweenBombDrops
というパブリックフィールドを渡します。
Unityは、コードでsecondsBetweenBombDrops
に指定した値を無視し、代わりにsecondsBetweenBombDrops
が静的修飾子なしで宣言されている場合、デフォルト値(つまり1)を使用します。
public float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
ただし、static
修飾子をsecondsBetweenBombDrops
に追加すると、コードは期待どおりに動作し、正しい値の10が使用されます。
public static float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
適切な値を使用するために、このフィールドにstatic
修飾子が必要なのはなぜですか?
Unityインスペクターで、スクリプトコンポーネントはsecondsBetweenBombDrops
が1であることを示します。このデフォルト値の1は、ゲームの開始時にプレハブをインスタンス化するか、ゲームの実行中にプレハブインスタンスを作成するかに関係なく存在します。
Unityは、コーディングの知識が限られている人(初心者、デザイナー)を含め、すべての人にとって物事を簡単にしたいと考えています。
それらを助けるために、Unityはインスペクターにデータを表示します。これにより、コーダーはコードを作成し、デザイナーはMonoDevelop/an IDEを開かずに値を調整して設計できます。
インスペクターに値を表示するには、2つの方法があります。
public int myVar = 10;
[SerializeField] private int myOtherVar = 0; // Can also be protected
2つ目は、カプセル化の原則に準拠しているため、より優れています(変数はプライベート/保護され、メソッドまたはプロパティを介して変更されます)。
エディターで変数を表示すると、スクリプトで指定された値は、スクリプトをドラッグするときにのみ使用されます。 Unityはこれらの値をシリアル化し、スクリプトの変更を気にしません。例えば、myVar
が事後のスクリプト内で20に設定されている場合、これは混乱につながる可能性があり、使用されません。シリアル化はシーンファイルに書き込まれます。
この例の2行は、まったく同じように機能します。
スクリプトコンポーネントの設定ホイールで[リセット]を押すと、Unityにスクリプト内の新しい値を考慮させることができます。これにより、コンポーネントの他のすべての変数もリセットされるため、意図されている場合にのみこれを行ってください。
変数をプライベートにして属性[SerializeField]
を省略すると、シリアル化プロセスが無効になるため、Unityはシーンファイル内で表示する値を探しません。代わりに、実行時にスクリプトによって値が作成されます。
コンポーネントをUnityに追加すると、コンポーネントのタイプの新しいオブジェクトが作成されます。表示される値は、そのオブジェクトのシリアル化された値です。このため、メンバー値のみを表示でき、静的変数はシリアル化できないため表示できません。 (これは.NET仕様であり、Unityに厳密には固有ではありません。) nityは静的フィールドをシリアル化しない であるため、static
修飾子を追加することで問題が解決したようです。
OPケースでは、コメントに基づいて、エディターでパブリックフィールドに値1が表示されていました。この値は、最初に宣言したときに実際にフィールドに与えた可能性が最も高い値であるにもかかわらず、デフォルト値であると考えました。スクリプトをコンポーネントとして追加した後、値10を作成し、まだ値1を使用しているためバグがあると考えました。これで、設計どおりに正常に動作していることを理解できます。
デフォルトでは、Unityは値の型(int、float、enumなど)と文字列、配列、リスト、MonoBehaviourをシリアル化して表示します。 (エディタスクリプトを使用して外観を変更することは可能ですが、これはトピック外です。)
以下:
public class NonMonoBehaviourClass{
public int myVar;
}
デフォルトではシリアル化されません。ここでも、これは.NET仕様です。 Unityは、エンジン要件の一部としてMonoBehaviourをデフォルトでシリアル化します(これにより、コンテンツがシーンファイルに保存されます)。エディターで「クラシック」クラスを表示する場合は、次のように言ってください。
[System.Serializable]
public class NonMonoBehaviourClass{
public int myVar = 10;
}
明らかに、ゲームオブジェクトに追加できないため、MonoBehaviour内で使用する必要があります。
public class MyScript:MonoBehaviour{
public NonMonoBehaviourClass obj = new NonMonoBehaviourClass();
}
これにより、インスペクターにオブジェクトが表示され、myVar
のインスタンスのNonMonoBehaviourClass
変数を変更できます。繰り返しますが、スクリプト内のmyVar
への変更は、値がシリアル化されてシーンに保存された後は考慮されません。
最後に、インターフェイスには変数が含まれていないため、インスペクタにも表示されません。メソッドとプロパティだけです。デバッグモードでは、プロパティはデフォルトでは表示されません。このモードは、インスペクターの右上隅に3本の線があるボタンを使用して変更できます。最初の2つの設定はNormal/Debugです。最初のものはデフォルトのもので、2番目のものもプライベート変数を表示します。これは値を監視するのに便利ですが、エディターから変更することはできません。
したがって、表示するインターフェイスが必要な場合、抽象クラスは同様の機能を提供します(多重継承を除く)が、MonoBehaviourになる可能性があるため、抽象クラスを検討する必要があります。
参照:
http://docs.unity3d.com/ScriptReference/SerializeField.html
http://docs.unity3d.com/Manual/script-Serialization.html