unity tamaño tag que prefabs prefab objetos objeto instantiate instanciar crear coordenadas cambiar c# serialization unity3d access-modifiers

c# - tamaño - ¿Por qué Unity ignora el valor inicializado de un campo público no estático?



static unity (1)

Estoy usando InvokeRepeating() para llamar a un método en un juego. Llamo a InvokeRepeating() en el método Start() de una de las clases de GameObject . Para establecer el parámetro repeatRate para InvokeRepeating() , le estoy pasando un campo público llamado secondsBetweenBombDrops .

Unity ignora el valor que especifico durante secondsBetweenBombDrops en el código y en su lugar utiliza algún valor predeterminado (es decir, 1) cuando se declara secondsBetweenBombDrops sin un modificador estático:

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

Sin embargo, una vez que agregue el modificador static a secondsBetweenBombDrops , el código se comporta como se esperaba y se usa el valor correcto de 10:

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

¿Por qué este campo requiere que el modificador static use el valor apropiado?

En el inspector de Unity, el componente script muestra que secondsBetweenBombDrops es 1. Este valor predeterminado de 1 está presente independientemente de si instancia el prefab en el inicio del juego o crea instancias prefabricadas mientras el juego se está ejecutando.


La espada de doble filo de la serialización

Unity quiere facilitar las cosas para todos, incluidas las personas con conocimientos limitados de codificación (principiantes, diseñadores).

Para ayudarlos, Unity muestra datos en el inspector. Esto permite que el codificador codifique y el diseñador lo diseñe ajustando los valores sin abrir MonoDevelop / a IDE.

Hay dos formas de mostrar los valores en el inspector:

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

El segundo es mejor ya que cumple con el principio de encapsulación (las variables son privadas / protegidas y modificadas mediante métodos o propiedades).

Cuando visualiza una variable en el Editor, el valor dado en el script solo se usa al arrastrar el script. Unity luego serializa esos valores y ya no le importa ninguna modificación de script. Esto puede generar confusión si, por ejemplo, myVar se establece en 20 dentro del script después del hecho, no se usará. La serialización está escrita en el archivo de escena.

Las dos líneas en el ejemplo funcionan exactamente de la misma manera.

Soluciones posibles

Es posible hacer que Unity considere nuevos valores en una secuencia de comandos presionando Restablecer en la rueda de configuración del componente de secuencia de comandos. Eso también restablecerá todas las demás variables del componente, por lo tanto, solo hazlo si eso es lo que quieres.

Convertir la variable en privada y omitir el atributo [SerializeField] deshabilitará el proceso de serialización, por lo que Unity ya no buscará en el archivo de escena un valor para mostrar; en su lugar, el script creará el valor en tiempo de ejecución.

Al agregar un componente a Unity, se crea un nuevo objeto del tipo del componente. Los valores que se muestran son los valores serializados de ese objeto. Por este motivo, solo se pueden mostrar los valores de los miembros y las variables estáticas no, ya que no son serializables. (Esta es una especificación .NET, no estrictamente específica para Unity.) Debido a que Unity no serializa los campos estáticos , esta es la razón por la cual agregar el modificador static pareció resolver el problema.

Explicando el OP

En el caso de OP, según los comentarios, su campo público mostraba un valor de 1 en el editor. Creías que este valor era el predeterminado, cuando en realidad era el valor que probablemente le diste al campo cuando lo declaraste originalmente. Después de agregar la secuencia de comandos como un componente, hizo el valor 10 y pensó que tenía errores ya que aún usaba el valor de 1. Ahora debería comprender que funcionaba correctamente, tal como estaba diseñado.

¿Qué serializa Unity?

Por defecto, Unity serializará y mostrará tipos de valores (int, float, enum, etc.), así como string, array, List y MonoBehaviour. (Es posible modificar su apariencia con los scripts del Editor, pero esto está fuera de tema).

El seguimiento:

public class NonMonoBehaviourClass{ public int myVar; }

no está serializado por defecto. Aquí nuevamente, esta es la especificación .NET. Unity serializa MonoBehaviour por defecto como parte del requisito del motor (esto guardará el contenido en el archivo de escena). Si desea mostrar una clase "clásica" en el editor, solo dígalo:

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

Obviamente, no puedes agregarlo a un objeto del juego, por lo que debes usarlo dentro de un MonoBehaviour:

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

esto mostrará el objeto en el inspector y permitirá modificaciones a la variable myVar en la instancia de NonMonoBehaviourClass . Y nuevamente, cualquier cambio en myVar dentro del script no será considerado después de que el valor sea serializado y almacenado en la escena.

Consejos adicionales para mostrar cosas en el inspector

Para finalizar, las interfaces no se muestran en el inspector ya que no contienen ninguna variable, solo métodos y propiedades. En modo de depuración, las propiedades no se muestran de forma predeterminada. Puede cambiar este modo usando el botón con tres líneas en la esquina superior derecha del Inspector. Las primeras dos configuraciones son Normal / Depuración. El primero es el predeterminado, el segundo también mostrará la variable privada. Esto es útil para ver sus valores, pero no se puede modificar desde el editor.

Por lo tanto, si necesita que se muestre una interfaz, debería considerar una clase abstracta, ya que ofrece una funcionalidad similar (a excepción de la herencia múltiple), pero puede ser un comportamiento en mono.

Referencias

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