Física Unity
Física Unity
Física Unity
Rigidbodies
Un Rigidbody es el componente principal que permite el comportamiento fsico para un
objeto. Con un Rigidbody adjunto, el objeto inmediatamente responder a la gravedad. Si
uno o ms componentes Collider son tambin agregados entonces el objeto ser movido
por colisiones entrantes.
Debido a que un componente Rigidbody asume el movimiento del objeto el cual est
adjunto, usted no debera intentar moverlo desde un script cambiando las propiedades
del Transform como lo son la posicin y rotacin. En vez, usted debera
aplicar forces para empujar el objeto y permitirle al motor de fsica calcular los resultados.
Hay algunos casos dnde usted podra querer que un objeto tenga un Rigidbody sin que
sus movimientos sean controlados por el motor de fsica. Por ejemplo, usted podra querer
controlar su personaje directamente desde cdigo script pero tambin permitirle ser
detectado por triggers (ve Triggers a continuacin). Este tipo de movimiento no-fsico
producido desde un script es conocido como movimiento kinematic. El componente
Rigidbody tiene una propiedad llamada Is Kinematic que lo quitar del control del motor
de fsica y le permite moverlo cinemticamente desde un script. Es posible cambiar el valor
deIs Kinematic desde un script para permitirle a la fsica activarse y desactivarse para un
objeto, pero esto viene con una carga de rendimiento y debera ser utilizada escasamente.
Ver las pginas de referencia Rigidbody y Rigidbody 2D para ms detalles acerca de los
ajustes y las opciones de scripting para estos componentes.
Sleeping (Durmiendo)
Una vez un rigidbody se est moviendo menos que una cierta cantidad minima lineal, o
velocidad de rotacin, el motor de fsica asumir que ha parado. Cuando esto suceda, el
objeto no se mover ms hasta que reciba una colisin o fuerza y por lo tanto se
configurar al modo sleeping. Esta optimizacin significa que ningn tiempo de
procesamiento ser gastado actualizando el rigidbody hasta la prxima vez que se
despierte (ie, configurado en movimiento nuevamente). Para la mayora de propsitos, el
adormecimiento y la despertada de los rigidbodies suceden transparentemente. Sin
embargo, un objeto podra fallar despertarse si un collider esttico (ie, uno sin un
rigidbody) sea movido hacia el interior o hacia afuera modificando la posicin del
transform. Esto puede resulta, digamons, en que el objeto del rigidbody se mantenga en el
aire cuando el piso se ha movido debajo de l. En casos como ste, el objeto puede ser
despertado de manera explcita utilizando la funcin WakeUp. Vea las pginas de
componente Rigidbody y Rigidbody 2D para ms informacin acerca de dormir.
Colliders
Collider components define the shape of an object for the purposes of physical collisions.
A collider, which is invisible, need not be the exact same shape as the objects mesh and in
fact, a rough approximation is often more efficient and indistinguishable in gameplay.
The simplest (and least processor-intensive) colliders are the so-called primitive collider
types. In 3D, these are the Box Collider, Sphere Collider and Capsule Collider. In 2D, you
can use the Box Collider 2D and Circle Collider 2D. Any number of these can be added to a
single object to create compound colliders.
With careful positioning and sizing, compound colliders can often approximate the shape of
an object quite well while keeping a low processor overhead. Further flexibility can be
gained by having additional colliders on child objects (eg, boxes can be rotated relative to
the local axes of the parent object). When creating a compound collider like this, there
should only be one Rigidbody component, placed on the root object in the hierarchy.
Note, that primitive colliders will not work correctly with shear transforms - that means that if
you use a combination of rotations and non-uniform scales in the tranform hierarchy so that
the resulting shape would no longer match a primitive shape, the primitive collider will not
be able to represent it correctly.
Hay algunos casos, sin embargo, dnde incluso los compound colliders no son lo
suficiente precisos. En 3D, usted puede utilizar Mesh Colliders para encajar la figura del
mesh del objeto exactamente. En 2D, el Polygon Collider 2D va a generalmente no encajar
con la figura del grfico sprite perfectamente pero usted puede re-definir la figura a
cualquier nivel de detalle que quiera. Estos colliders son mucho ms intensivos al
procesador que los tipos primitivos, no obstante, usted puede utilizarlos de manera escasa
para mantener un buen rendimiento. Tambin, un mesh collider va a normalmente ser
incapaz de colisionar con otro mesh collider (ie, nada va suceder cuando entren en
contacto). Usted puede pasar alrededor de esto en algunos casos al marcar el mesh
collider como Convex en el inspector Esto va a generar la figura del collider como un
convex hull que es como el mesh original pero con cualquier hueco llenado. El beneficio
de esto es que un convex mesh collider puede colisionar con cualquier otro mesh colliders
entonces usted puede utilizar esta caracterstica cuando usted tenga un personaje
movindose con figuras adecuadas. Sin embargo, una buena regla general es utilizar
mesh colliders para la geometra de escena y aproximar la figura de objetos movindose
utilizando colliders primitivos compound.
Los colliders pueden ser agregados a un objeto sin un componente Rigidbody para crear
pisos, paredes y cualquier otro elemento sin movimiento en la escena. Estos son
referenciados como static colliders. En general, usted no debera reposicionar colliders
estticos cambiando la posicin del Transform ya que esto va a impactar fuertemente el
rendimiento del motor de fsica. Los Colliders en un objeto que tiene un Rigidbody son
conocidos como dynamic colliders. Los Colliders estticos pueden interactuar con los
colliders dinmicos pero debido a que estos no tienen Rigidbody, no se movern en
respuesta a las colisiones.
La pgina de referencia para los varios tipos de colliders estn linkiados arriba para ms
informacin acerca de sus propiedades y usos.
Materiales de Fsica
Cuando los colliders interactan, sus superficies necesitan simular las propiedades del
materia el cual supuestamente representan. Por ejemplo, un pedazo de hielo ser
resbaloso mientras una bola de caucho va a ofrecer bastante friccin y ser de mucho
rebote. Aunque la figura de los colliders no es deformada durante las colisiones, su friccin
y rebote puede ser configurado utilizando Physics Materials. Obteniendo los parmetros
como se debe puede involucrar un poco de intento y error pero un material de hielo, por
ejemplo, tendr cero (o muy poca) friccin y un material de caucho tendr mucha friccin y
casi un perfecto reboto. Vea las pginas de referencia de Physic Material y Physics
Material 2D para ms detalles en los disponibles parmetros. Tenga en cuenta que por
razones histricas, el assset 3D es llamado Physic Material (sin la S) pero el equivalente
2D es llamado Physics Material 2D (con la S).
Triggers
El sistema de scripting puede detectar cuando colisiones suceden e instanciar acciones
utilizando la funcinOnCollisionEnter. Sin embargo, usted puede tambin utilizar el
motor de fsica simplemente para detectar cuando un collider entra al espacio de otro sin
crear una colisin. Un collider configurado como Trigger (utilizando la propiedad Is
Trigger) no se comporta como un objeto solido y simplemente le permitir a otros colliders
pasar a travs de l. Cuando un collider entra su espacio, un trigger va a llamar la
funcin OnTriggerEnter en los scripts del trigger del objeto.
Con colisiones normales, y no-trigger, hay un detalle adicional y es que al menos uno de
los objetos involucrados debe tener un non-kinematic Rigidbody (ie, Is Kinematic se debe
apagar). Si ambos objetos son Kinematic Rigidboodies entoncesOnCollisionEnter, etc,
no ser llamado. Con colisiones con trigger, esta restriccin no aplica y ambos kinematic y
no-kinematic rigidbodies van a realizar una llamada a OnTriggerEnter cuando entren a
un trigger collider.
Rigidbody Collider
Este es un GameObject con un Collider y un no-kinematic Rigidbody normal adjunto. Los
Rigidbody colliders son completamente simulados por el motor de fsica y pueden
reaccionar a colisiones y fuerzas aplicadas desde un script. Estos pueden colisionar con
otros objetos (incluyendo static colliders) y son la configuracin Collider ms comnmente
utilizada en juegos que utilizan fsica.
Static
Rigidbod
Kinematic
Static
Rigidbody
Kinematic
Collide
y Collider
Rigidbody
Trigger
Trigger
Rigidbody
Collider
Collider
Collider
Trigger
Collider
Static
Collider
Rigidbody
Collider
Kinematic
Rigidbody
Collider
Static
Trigger
Collider
Rigidbody
Trigger
Collider
Kinematic
Rigidbody
Trigger
Collider
Static
Rigidbod
Kinematic
Static
Rigidbody
Kinematic
Collide
y Collider
Rigidbody
Trigger
Trigger
Rigidbody
Collider
Collider
Collider
Trigger
Collider
Static
Collider
Rigidbody
Collider
Kinematic
Rigidbody
Collider
Static
Trigger
Collider
Rigidbody
Trigger
Collider
Kinematic
Rigidbody
Trigger
Collider
Joints (Articulaciones)
Usted puede adjuntar un objeto rigidbody a otro o a un punto fijo en el espacio utilizando un
componente Joint. Por lo general, usted quiere que un joint (articulacin) le permita alguna libertad
de movimiento por lo que Unity proporciona diferente componentes Joint que hacen cumplir
diferentes restricciones. Por ejemplo, un Hinge Joint le permite girar alrededor de un especifico
punto y eje mientras que un Spring Joint mantiene el objeto a parte pero permite que la distancia
entre ellos se estire un poco. Como es usual, los componentes 2D tienen 2D al final del nombre,
eg, Hinge Joint 2D.
Los joints tambin tienen otras opciones que se pueden activar para diferentes efectos. Por ejemplo,
usted puede configurar un joint para romperse cuando una fuerza aplicada a este exceda cierto
umbral. Algunos joints tambin permiten un drive force que ocurra entre los objetos conectados
para configurarlos en movimiento automticamente.
Vea la pgina de referencia para las clases Joint para leer ms acerca de sus propiedades.
=Character
Referencia de fsica en 3D
Esta seccin da detalles de los componentes utilizados con fsicas de 3D. Vea esta
seccin para lo equivalente a los componentes 2D.
Box Collider
Un Box Collider es una primitiva bsica de colisin en forma de cubo.
Propiedades
Propiedad
:
Funcin:
Is Trigger
Material
Center
Size
Detalles
Los Box Colliders son evidentemente tiles para cualquier objeto con forma cbica, como
una caja o un cofre. No obstante, una caja delgada puede ser usada como piso, muro o
rampa; y la forma en cubo tambin es un elemento til en un collider compuesto.
Capsule Collider
El Capsule Collider est hecho de dos semi-esferas juntadas por un cilindro. Tiene la
misma forma que la primitiva Capsule.
Propiedades
Propiedad
:
Funcin:
Is Trigger
Propiedad
:
Funcin:
Material
Center
Radius
Height
Direction
Detalles
Usted puede ajustar el Radius y la Height del Capsule Collider independientemente entre
ellos. Es utilizado en Character Controller y funciona bien para polos, o puede ser
combinado con otras colisiones para formas inusuales.
Scripting
La programacin de scripts es un ingrediente esencial en todos los juegos. Incluso el juego
ms simple necesitar scripts para responder a entradas del jugador y asegurar que los
eventos del juego se ejecutan en el momento adecuado. Adems, los scripts pueden ser
usados para crear efectos grficos, controlar el comportamiento fsico de objetos o incluso
implementar un sistema de inteligencia artificial para los personajes del juego.
La programacin de scripts es una habilidad que toma tiempo y esfuerzo para aprender; la
intencin de esta seccin no es ensearle en cmo escribir cdigo script desde 0 pero ms
bien explicarle los conceptos principales que aplican al scripting en Unity.
Creando Scripts
A diferencia de la mayora de otros assets, los scripts son usualmente creados dentro de
Unity directamente. Usted puede crear un nuevo script desde el men Create en la parte
superior izquierda del panel del Proyecto o seleccionando Assets > Create > C#
Script (o JavaScript) desde el men principal.
El nuevo script ser creado en la carpeta que usted haya seleccionado en el Panel del
Proyecto. El nuevo nombre del archivo script ser seleccionado, pidindole a usted que
ingrese otro nuevo nombre.
Es una buena idea ingresar el nombre del nuevo script en este punto en vez de editarlo
despus. El nombre que usted ingrese ser utilizado para crear el texto inicial dentro del
archivo, como es descrito abajo.
using UnityEngine;
using System.Collections;
}
}
Un script hace sus conexiones con el funcionamiento interno de Unity al implementar una
clase que deriva desde la clase integrada llamada MonoBehaviour. Usted puede pensar
de una clase como un tipo de plano para crear un nuevo tipo de Component que puede ser
#pragma strict
function Start () {
function Update () {
Aqu, las funciones Start y Update tienen el mismo significado pero la clase no est
explcitamente declarada. El script en s mismo es asumido para definir la clase; ste va a
derivar implcitamente desde MonoBehaviour y toma su nombre desde el nombre del
archivo (filename) del asset script.
Controlando un GameObject
Como es dicho arriba, un script solo define un plano para un Component por lo que nada
de su cdigo ser activado hasta que una instancia del script es adjuntada al GameObject.
Usted puede adjuntar un script al arrastrar el script asset a un GameObject en el panel de
la jerarqua o al inspector del GameObject el cual est actualmente seleccionado. Tambin
hay un sub-men de Scripts en el men del Componente que va a contener todos los
scripts disponibles en el proyecto, incluyendo aquellos que usted ha creado usted mismo.
La instancia de script se ve mucho como cualquier otro Componente en el Inspector:
Una vez adjuntado, el script va a comenzar a funcionar cuando usted presione Play y corra
el juego. Usted puede revisar esto al agregar el siguiente cdigo en la funcin Start:-
Variables y el Inspector
Cuando cree un script, usted est esencialmente creando su nuevo propio tipo de
componente que puede ser adjuntado a Game Objects como cualquier otro componente.
Al igual que otros Componentes tienen propiedades que son editables en el inspector,
usted puede permitir valores en su script a ser editados desde el Inspector tambin.
using UnityEngine;
using System.Collections;
}
}
Unity crea la etiqueta del Inspector introduciendo un espacio dnde una mayscula ocurra
en el nombre de la variable. Sin embargo, esto es para propsitos netamente de pantalla y
usted debera siempre utilizar el nombre de la variable dentro de su cdigo. Si usted edita
el nombre y presiona Reproducir, usted ver que el mensaje incluye el texto que usted
ingreso.
En C#, usted debe declarar una variable como pblica para verla en el Inspector. En
UnityScript, las variables son pblicas por defecto al menos de que usted especifique de
que deberan ser privadas:
#pragma strict
function Start () {
Unity le va a permitir a usted cambiar el valor de las variables del script mientras el juego
est corriendo. Esto es muy til para ver los efectos de cambios directos sin tener que
parar y reiniciar. Cuando el modo de juego termine, los valores de las variables se van a
reset a lo que sea que estaban antes de que usted pusiera Reproducir. Esto asegura que
usted est libre de ajustar las configuraciones de sus objetos sin miedo de hacer un dao
permanente.
Accediendo Componentes
El caso ms simple y comn es dnde un script necesita acceder otros Componentes
adjuntos al mismo GameObject. Como es mencionado en la seccin de Introduccin, un
Componente es una instancia de una clase por lo que el primer paso es coger una
referencia a la instancia del Componente con el cual usted quiere trabajar. Esto es hecho
con la funcinGetComponent. Tpicamente, usted quiere asignar el objeto del Componente
a una variable la cual est hecha en C# utilizando la siguiente sintaxis:
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
}
function Start () {
var rb = GetComponent.<Rigidbody>();
}
Una vez usted tenga una referencia a la instancia del Componente, usted puede configurar
los valores de sus propiedades como usted quiera en el Inspector:
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
rb.mass = 10f;
}
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
Tenga en cuenta que no hay razn para que usted no pueda tener ms de un script
personalizado adjunto al mismo objeto. Si usted necesita acceder un script desde otro,
usted puede utilizar GetComponente y simplemente utilizar el nombre de la clase script (o
nombre del archivo) para especificar el tipo de Componente que usted quiere.
Si usted intenta recuperar un Componente que no ha sido agregado al GameObjecto
entonces GetComponent va a devolver null; usted va a obtener una referencia nula de
error en el tiempo de ejecucin si usted intentar cambiar cualquier valor en el objeto nulo.
Usted puede ahora arrastrar un objeto desde la escena o panel de Jerarqua a esta
variable para asignarlo. La funcin GetComponent y las variables de acceso a
Componentes estn disponibles para este objeto como cualquier otro, entonces usted
puede utilizar cdigo como el siguiente:
void Start() {
// Start the enemy ten units behind the player
character.
Enlazar objetos juntos con variables es de gran ayuda cuando usted est tratando con
objetos individuales que tienen conexiones permanentes. Usted puede utilizar una variable
array para enlazar varios objetos del mismo tipo, pero la conexin debe todava estar
hecha en el editor de Unity en vez que sea en el tiempo de ejecucin. A veces es ms
conveniente ubicar objetos en el tiempo de ejecucin y Unity proporciona dos maneras
bsicas para hacer esto, como es descrito abajo.
using UnityEngine;
void Start() {
waypoints = new Transform[transform.childCount];
int i = 0;
Usted tambin puede ubicar un objeto hijo especifico por el nombre utilizando la
funcin Transform.Find :
transform.Find("Gun");
Esto puede ayudar cuando un objeto tiene un hijo que puede ser agregado y quitado
durante el tiempo de juego. Un arma que puede ser recogida y dejada en el suelo es un
buen ejemplo de esto.
GameObject player;
void Start() {
player = GameObject.Find("MainHeroCharacter");
}
Un objeto o una coleccin de objetos tambin pueden ser ubicadas por su tag (etiqueta)
utilizando las
funcionesGameObject.FindWithTag y GameObject.FindGameObjectsWithTag .
GameObject player;
GameObject[] enemies;
void Start() {
player = GameObject.FindWithTag("Player");
enemies = GameObject.FindGameObjectsWithTag("Enemy");
}
void Update() {
float distance = speed * Time.deltaTime *
Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * distance);
}
El motor de fsica tambin actualiza en pasos de tiempo discretos de una manera similar al
renderizado de cuadros. Una funcin separada de evento llamada FixedUpdate se llama
justo antes de cada actualizacin de fsica. Debido a que las actualizaciones de fsica y
actualizaciones de cuadro no ocurren en la misma frequencia, usted va a obtener un
void FixedUpdate() {
Vector3 force = transform.forward * driveForce *
Input.GetAxis("Vertical");
rigidbody.AddForce(force);
}
Tambin es a veces til ser capaz de hacer cambios adicionales en un punto despus de
que funciones Update y FixedUpdate han sido llamadas para todos los objetos en la
escena y despus de que todas las animaciones hayan sido calculadas. Un ejemplo es
dnde una cmara debera permanecer adiestrado en un objeto destino; el ajuste a la
orientacin de la cmara debera ser hecho despus de que el objeto destino haya sido
movido. Otro ejemplo es dnde el cdigo script debera anular el efecto de una animacin
(digamos, para hacer la cabeza del objeto mirar hacia un objeto destino en la escena). La
funcinLateUpdate puede ser utilizada para este tipo de situaciones.
void LateUpdate() {
Camera.main.transform.LookAt(target.transform);
}
Eventos de Inicializacin
A veces es til ser capaz de llamar cdigo de inicializacin con anterioridad de cualquier
actualizacin que ocurra en el tiempo de juego. La funcin Start es llamada antes de la
actualizacin del primer cuadro o de fsica de un objeto. La funcin Awake es llamada para
cada objeto en la escena en el tiempo cuando la escena carga. Tenga en cuenta que
aunque las funciones varias del objeto Start y Awake son llamadas en un orden arbitrario,
todos los Awakes habrn finalizado antes de que el primer Start es llamado. Esto significa
que el cdigo en la funcin Start puede hacer uso de otras inicializaciones previamente
llevadas en la fase Awake.
Eventos GUI
Unity tiene un sistema para renderizar los controles GUI sobre la accin principal en la
escena y responder a clicks hechos por estos controles. Este cdigo es manejado algo
diferente de la actualizacin por cuadro normal por lo que debera ser colocado en la
funcin OnGUI, que ser llamada periodicamente.
void OnGUI() {
GUI.Label(labelRect, "Game Over");
}
Usted tambin puede detectar eventos de mouse que ocurren sobre un GameObject a
medida que aparece en la escena. Este puede ser utilizado para focalizar armas o mostrar
informacin acerca del personaje que est actualmente debajo del apuntador del mouse.
Un conjunto de funciones de evento OnMouseXXX (eg, OnMouseOver, OnMouseDown)
est disponible para permitirle a un script reaccionar a las acciones del usuario con el
mouse. Por ejemplo, si el botn del mouse est presionado mientras el apuntador est
sobre un objeto en particular entonces la funcin OnMouseDown en el script de ese objeto
ser llamada si existe.
Eventos de Fsica
El motor de fsica va a reportar colisiones contra un objeto al llamar funciones de evento en
el script de ese objeto. Las
funciones OnCollisionEnter, OnCollisionStay y OnCollisionExit sern llamadas a medida
que haya un contacto hecho, mantenido o roto. Las funciones
correspondientes OnTriggerEnter, OnTriggerStay y OnTriggerExit sern llamadas cuando
el collider del objeto est configurado como un Trigger (ie, un collider que simplemente
detecta cuando algo lo entra en vez que reaccionar fsicamente). Estas funciones pueden
ser llamadas varias veces en sucesiones si un contacto o ms es detectado durante la
void Update() {
transform.Translate(0, 0, distancePerFrame);
}
}
function Update() {
transform.Translate(0, 0, distancePerFrame);
}
Sin embargo, dado que el tiempo de cuadros (frame time) no es constante, el objeto va a
aparecer moverse a una velocidad irregular. Si el frame time es 10 mili-segundos entonces
el objeto se mover hacia adelante por distancePerFrame cien veces por segundo. Pero, si
el tiempo aumenta a 25 mili-segundos (debido a una sobrecarga de CPU, digamos)
entonces solo va a ir hacia adelante cuarenta veces por segundo y por lo tanto va a cubrir
menos distancia. La solucin es escalar el tamao del movimiento por el frame time que
usted puede leer desde la propiedad Time.deltaTime:
void Update() {
transform.Translate(0, 0, distancePerSecond *
Time.deltaTime);
}
}
function Update() {
transform.Translate(0, 0, distancePerSecond *
Time.deltaTime);
}
void Resume() {
Time.timeScale = 1;
}
}
function Resume() {
Time.timeScale = 1;
}
reducido si usted intenta hacer esto durante un gameplay normal. Esto dar como
resultado en un video que no refleja el rendimiento verdadero del juego.
Afortunadamente, Unity proporciona una propiedad Capture Framerate que le permite a
usted solucionar este problema. Cuando el valor de la propiedad es configurado a
cualquier cosa en vez de cero, el game time (tiempo de juego) ser reducido y las
actualizaciones de cuadro sern emitidas en intervalos regulares preciso. El intervalo entre
cuadro es igual a 1 / Tiempo.captureFramerate, entonces si el valor es configurado a 5.0
entonces las actualizaciones ocurren cada quinto de segundo. Con las demanda de
framerate efectivamente siendo reducida, usted tiene el tiempo en la funcin Update para
guardar capturas de pantalla o realizar otras acciones:
void Start () {
// Set the playback framerate (real time will not
relate to game time after this).
Time.captureFramerate = frameRate;
void Update () {
// Append filename to folder name (format is '0005
shot.png"')
string name = string.Format("{0}/{1:D04} shot.png",
folder, Time.frameCount );
}
}
function Start () {
// Set the playback framerate (real time will not relate
to game time after this).
Time.captureFramerate = frameRate;
function Update () {
// Append filename to folder name (format is '0005
shot.png"')
var name = String.Format("{0}/{1:D04} shot.png", folder,
Time.frameCount );
Aunque el video grabado utilizando esta tcnica tpicamente se ve muy bien, el juego
puede ser difcil de reproducir cuando es disminuido drasticamente. Usted puede necesitar
experimentar con el valor de Time.captureFramerate para permitirle a usted un tiempo de
grabacin ms amplia sin excesivamente complicar la tarea del reproductor prueba.
void Start() {
for (int i = 0; i < 5; i++) {
Instantiate(enemy);
}
}
Observe que el objeto del cual la copia es realizada no requiere estar presente en la
escena. Es ms comn usar un prefab arrastrado a una variable pblica desde el Project
panel (panel del Proyecto) en el editor. Tambin, crear instancias de un GameObject
copiar todos los Componentes presentes en el original.
Tambin hay una funcin Destroy que permite destruir un objeto despus que la
actualizacin del frame haya terminado u opcionalmente despus de un retraso de tiempo
corto:
}
}
Observe que la funcin Destroy puede destruir componentes individuales sin afectar el
GameObject en s. Un error comn es escribir algo como:
Destroy(this);
lo cual realmente solo destruir el componente del script que le llama en vez de destruir
el GameObject al cual el script est atado.
Corrutinas
Cuando usted llama a una funcin, esta se ejecuta en su totalidad antes de retornar. Esto
significa efectivamente que cualquier accin tomando lugar en una funcin debe suceder
en una sola actualizacin de frame (cuadro); un llamado a una funcin no puede ser usado
para contener una animacin procedimental o una secuencia de eventos en el tiempo.
Como un ejemplo, considere la tarea de reducir gradualmente el valor alfa (alpha) de un
objeto (opacidad) hasta que se convierta completamente invisible.
void Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
}
Tal como est, la funcin Fade (Desvanecer) no tendr el efecto que usted espera. Para
que el desvanecimiento sea visible, el alfa debe ser reducido sobre una secuencia de
frames (cuadros) para mostrar los valores intermedios siendo renderizados. Sin embargo,
la funcin se ejecutar en su totalidad en una sola actualizacin de cuadro. Los valores
intermedios nunca se vern y el objeto desaparecer instantneamente.
Es posible manejar situaciones como estas agregando cdigo a la funcin Update que
ejecuta el desvanecer en una base cuadro-a-cuadro (frame-by-frame). Sin embargo, es
usualmente mas conveniente usar una coroutine (corrutina) para este tipo de tarea.
Una corrutina es una funcin que tiene la habilidad de pausar su ejecucin y devolver el
control a Unity para luego continuar donde lo dej en el siguiente frame. En C#, una
corrutina es declarada as:
IEnumerator Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return null;
}
}
Es esencialmente una funcin declarada con un tipo de retorno IEnumerator y con una
instruccin de retorno yield incluida en algn lugar de su cuerpo. La linea con la instruccin
de retorno yield es el punto en el cual la ejecucin se pausar y reanudar en el siguiente
frame. Para establecer una corrutina en ejecucin, necesitas usar la funcin StartCoroutine
void Update() {
if (Input.GetKeyDown("f")) {
StartCoroutine("Fade");
}
}
En UnityScript, las cosas son ligeramente mas simples. Cualquier funcin que incluya una
instruccin yield se entiende que es una corrutina y el tipo de retorno IEnumerator no
requiere ser declarado explicitamente:
function Fade() {
for (var f = 1.0; f >= 0; f -= 0.1) {
var c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield;
}
Adems, una corrutina puede ser iniciada en UnityScript llamndola como si fuese una
funcin normal:
function Update() {
if (Input.GetKeyDown("f")) {
Fade();
}
}
Notar que el contador en el bucle de la funcin Fade mantiene su valor correcto durante
el tiempo de vida de la corrutina. De hecho, cualquier variable o parametro ser
preservado correctamente entre los yields.
Por defecto, una corrutina es reanudada en el siguiente frame despus de haberse
interrumpido (yield), pero tambin es posible introducir un tiempo de retardo
usando WaitForSeconds:-
IEnumerator Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return new WaitForSeconds(.1f);
}
}
y en UnityScript:
function Fade() {
for (var f = 1.0; f >= 0; f -= 0.1) {
var c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield WaitForSeconds(0.1);
}
}
Esta puede usarse como una forma de propagar un efecto durante un periodo de tiempo
pero tambin es una til optimizacin. Muchas tareas en un juego necesitan ser llevadas a
cabo peridicamente y la forma mas obvia de hacer esto es incluirlas en la funcin Update.
Sin embargo, esta funcin normalmente ser llamada muchas veces por segundo. Cuando
una tarea no necesita ser repetida tan frecuentemente, puedes ponerla en una corrutina
para obtener una actualizacin regularmente pero no en cada frame. Un ejemplo de esto
puede ser una alarma que alerta al usuario si un enemigo est cerca. El cdigo podra
parecerse a esto:
function ProximityCheck() {
for (int i = 0; i < enemies.Length; i++) {
if (Vector3.Distance(transform.position,
enemies[i].transform.position) < dangerDistance) {
return true;
}
}
return false;
}
Si hay muchos enemigos, entonces llamar a esta funcin en cada frame podra introducir
una sobrecarga significativa. Sin embargo, podra usar una corrutina para llamarla cada
dcima de segundo:
IEnumerator DoCheck() {
for(;;) {
ProximityCheck;
yield return new WaitForSeconds(.1f);
}
}
Esto reducir en gran cantidad el nmero de comprobaciones llevados a cabo sin ningn
efecto notable en la experiencia de juego.
Fase 3: Todas los otros scripts que no estn dentro de una carpeta llamada Editor.
Fase 4: Todos los scripts que falten (ie, los que estn dentro de una carpeta
llamada Editor).
Adicionalmente, cualquier script dentro de una carpeta llamada WebPlayerTemplates en
el nivel superior de la carpeta de Assets no ser compilada en absoluto. Este
comportamiento es un poco diferente del nombre de otras carpetas especiales que
tambin funcionan dentro de sub-carpetas (eg, Scripts/Editor funcionan como una carpeta
de script de editor pero Scripts/WebPlayerTemplates no previene compilacin).
Un ejemplo comn es dnde un archivo UnityScript necesita referenciar una clase definida
en un archivo C#. Usted puede lograr esto colocando el archivo C# dentro de una carpeta
de Plugins y el archivo UnityScript en una carpeta que no sea especial. Si usted no hace
esto, usted obtendr un error diciendo que la clase C# no puede ser encontrada.
Tenga en cuenta. Los Standard Assets no funcionan en la carpeta raiz de los Assets.
Namespaces
A medida que los proyectos se hacen ms grandes y el nmero de scripts aumente, la
probabilidad de tener choques entre nombres de clases de script aumenta aun ms. Esto
en especial es verdad cuando varios programadores estn trabajando en diferentes
aspectos del juego de manera separada y van a eventualmente combinar sus esfuerzos en
un proyecto. Por ejemplo, un programador puede estar escribiendo el cdigo para controlar
el personaje principal del jugador mientras otro escribe el cdigo equivalente para el
enemigo. Ambos programadores pueden escoger llamar su clase principal de
scriptController, pero esto puede causar un choque cuando sus proyectos sean
combinados.
Hasta cierto punto, este problema puede ser evitado adoptando una convencin de
nombre o al renombrar las clases cuando un choque sea descubierto (eg, las clases de
arriba podran tener nombres como PlayerController y EnemyController). Sin embargo,
esto es un problema cuando hay varias clases con nombres que choquen, o cuando las
variables son declaradas utilizando esos nombres - cada mencin del nombre de la clase
vieja debe ser remplazado para que el cdigo compile.
El lenguaje C# ofrece una caracterstica llamada namespaces que resuelve este problema
de manera robusta. Un namespace es simplemente una coleccin de clases que son
referenciadas por utilizar un prefijo escogido en el nombre de la clase. En el ejemplo de
abajo, las clases Controller1 y Controller2 son miembros del namespace llamado Enemy:
namespace Enemy {
public class Controller1 : MonoBehaviour {
...
}
using Enemy;
Atributos
Attributes son marcadores que pueden ser colocados sobre una clase, propiedad o
funcin en un script indicando un comportamiento especial. Por ejemplo, el
atributo HideInInspector puede ser agregado sobre una declaracin de propiedad para
prevenir que esta propiedad sea mostrada en el inspector, incluso si es pblica. En
JavaScript, el nombre de un atributo comienza con un signo @, mientras que en C# y
Boo, est contenido entre corchetes:-
// JS
@HideInInspector
var strength: float;
// C#
[HideInInspector]
public float strength;
Unity provee un nmero de atributos que son listados en la referencia de script (seleccione
la seccin Editor or Runtime Attributes (Editor Atributos en tiempo de ejecucin) desde el
men emergente en la barra lateral). Hay tambin atributos definidos en las libreras .NET
que pueden en ocasiones ser tiles en el cdigo de Unity.
Nota: el atributo ThreadStatic definido en la librera .NET no debe ser usado ya que
ocasiona un fallo del software (crash) si es agregado a un script de Unity.
Editor
Reset: El reset es llamado para inicializar las propiedades de script cuando es por
primera vez adjuntado al objeto y tambin cuando el comando Reset es utilizado.
Entre frames
Update: Update es llamada una vez por frame. Es la funcin principal para las
actualizaciones de frames.
Rendering (Renderizacin)
escena.
OnRenderImage: Llamado despus de que la renderizacin de escena est
Coroutines (Corrutinas)
Actualizaciones normales de Coroutines (corrutinas) son ejecutadas despus del return
que hace la funcin Update. Una coroutine es una funcin que puede suspender su
ejecucin (yield) hasta que la YieldInstruction finalice. Diferentes usos de Coroutines:
despus de que todas las funciones Update hayan sido llamadas para el frame
yield WaitForFixedUpdate Continua despus de que todos los FixedUpdate
Cuando Salga
Estas funciones son llamadas en todos los objetos activos en su escena:
cerrada.
OnDisable: Esta funcin es llamada cuando el comportamiento se vuelve inactivo
o deshabilitado.
Optimizacin
La recoleccin de basura (Garbage collection) es automtica e invisible para el
programador; pero detrs de escena, el proceso de recoleccin requiere en realidad de un
tiempo de CPU significativo. Cuando se usa correctamente, la gestin automtica de
memoria por lo general igualar o superar a la asignacin manual en trminos de
rendimiento global. Sin embargo, es importante que el programador evite errores que
accionen el recolector ms frecuentemente de lo que es necesario, a fin de evitar
interrupciones en la ejecucin.
Hay algunos algoritmos famosos que son verdaderas pesadillas para el recolector, aunque
parezcan inocentes a primera vista. Un ejemplo clsico es la concatenacin repetida de
cadenas:-
return line;
}
}
return line;
}
El detalle clave aqu es que los nuevos pedazos no estn siendo agregados uno por uno a
la cadena en el mismo sitio en que est. Lo que realmente ocurre es que cada vez que se
repite el ciclo, el contenido previo de la variable line se marca como muerto, y una nueva
cadena completa es asignada para que contenga el pedazo original ms la nueva parte al
final. Dado que la cadena se vuelve ms larga a medida que el valor de i se incrementa, la
suma del espacio en la pila (tambin conocido como espacio de almacenamiento
dinmico) que est siendo consumido tambin se incrementa, por lo que fcilmente son
empleados cientos de bytes de espacio libre en la pila cada vez que esta funcin es
invocada. Si necesitas concatenar juntas muchas cadenas, una opcin mucho mejor es la
clase System.Text.StringBuilder de la librera de Mono.
Sin embargo, incluso la concatenacin repetida no causar muchos problemas si no es
llamada con frecuencia, y en Unity esto usualmente implica la actualizacin de frames.
Algo como:-
void Update() {
string scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;
}
}
function Update() {
var scoreText: String = "Score: " + score.ToString();
scoreBoard.text = scoreText;
asignar nuevas cadenas cada vez que Update sea invocado, y generar una filtracin
constante de basura nueva. Gran parte de esto puede ser evitado actualizando el texto
slo cuando el puntaje cambie:-
void Update() {
if (score != oldScore) {
scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;
oldScore = score;
}
}
}
function Update() {
if (score != oldScore) {
scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;
oldScore = score;
}
}
Otro problema potencial ocurre cuando una funcin devuelva un valor de array:-
return result;
}
return result;
}
Este tipo de funcin es muy elegante y conveniente cuando se crea un nuevo array que es
ocupado con valores. No obstante, si es llamado repetidamente entonces va a ser
asignado un nuevo espacio en la memoria en cada ocasin. Dado que los arrays pueden
ser muy grandes, el espacio libre en la pila puede quedar utilizado rpidamente, resultando
en frecuentes recolecciones de basura. Una forma de evitar este problema es hacer uso
del hecho que un array es un tipo de referencia. Un array pasado a una funcin en forma
de un parmetro puede ser modificado dentro de esta funcin, y el resultado permanecer
despus que la funcin retorne y concluya. Una funcin como la de arriba con frecuencia
puede ser reemplazado con algo como:-
}
}
Lo que esto hace es slo reemplazar el contenido existente del array con valores nuevos.
Aunque esto requiere que la asignacin inicial del array sea hecho en el cdigo que invoca
a la funcin (que no pareciera ser tan elegante), esta funcin no generar basura nueva
cuando sea ejecutada.
if (Time.frameCount % 30 == 0)
{
System.GC.Collect();
}
Sin embargo, debes usar esta tcnica con precaucin y verificar las estadsticas del profiler
para asegurarte que realmente se est reduciendo el tiempo de recoleccin para tu juego.
// release reference
tmp = null;
}
}
// release reference
tmp = null;
Una pila suficientemente grande no deber quedar completamente llena al estar realizando
una recoleccin durante las pausas en el ritmo del juego. Cuando una pausa ocurre,
puedes solicitar una recoleccin de forma explcita:-
System.GC.Collect();
Una vez ms, debes tener cuidado al usar esta estrategia, y pon atencin a las
estadsticas del profiles en lugar de slo asumir que est teniendo el efecto deseado.
Ms informacin
La gestin de memoria es un tema sutil y complejo al cual se le ha dedicado una gran
cantidad de esfuerzo acadmico. Si ests interesado en aprender ms sobre esto, la
pgina memorymanagement.org es un excelente recurso que agrupa muchas
publicaciones y artculos en lnea. Ms informacin sobre pooling de objetos puede ser
encontrada en esta pgina de Wikipedia y tambin en Sourcemaking.com.
Defines de plataforma
Los defines de plataforma que soportes Unity para sus scripts son:
Propiedad:
Funcin:
UNITY_EDITOR
UNITY_EDITOR_WIN
UNITY_EDITOR_OSX
UNITY_STANDALONE_O
SX
UNITY_STANDALONE_
WIN
UNITY_STANDALONE_LI
NUX
UNITY_STANDALONE
UNITY_WEBPLAYER
UNITY_WII
UNITY_IOS
UNITY_IPHONE
Propiedad:
Funcin:
UNITY_ANDROID
UNITY_PS3
UNITY_PS4
UNITY_XBOX360
UNITY_XBOXONE
UNITY_BLACKBERRY
UNITY_TIZEN
UNITY_WP8
UNITY_WP8_1
UNITY_WSA
UNITY_WSA_8_0
UNITY_WSA_8_1
UNITY_WSA_10_0
Propiedad:
Funcin:
UNITY_WINRT
UNITY_WINRT_8_0
UNITY_WINRT_8_1
UNITY_WINRT_10_0
UNITY_WEBGL
UNITY_ANALYTICS
UNITY_2_6
UNITY_2_6_1
UNITY_3_0
UNITY_3_0_0
UNITY_3_1
UNITY_3_2
UNITY_3_3
UNITY_3_4
UNITY_3_5
UNITY_4_0
UNITY_4_0_1
UNITY_4_1
UNITY_4_2
UNITY_4_3
UNITY_4_5
UNITY_4_6
UNITY_5_0
Tenga en cuenta: Para versiones anteriores a 2.6.0 no hay defines de plataformas ya que
esta caracterstica fue aadida en esa versin.
Usted tambin puede utilizar la DEVELOPMENT_BUILD definida para identificar si su
script se est ejecutando en un reproductor el cual fue construido con la opcin
Development Build activada.
Primero que todo, seleccione la plataforma en la cual usted quiere probar su cdigo al click
en File -> Build Settings. Esto va a traer la ventana de los ajustes del build
(construccin) para seleccionar su plataforma deseada.
L
a ventana de los Ajustes con el WebPlayer seleccionada como la plataforma
deseada.
Seleccione la plataforma con la cual usted quiere probar su cdigo pre-compilado y
presione el botn Switch Platform para decirle a Unity qu plataforma usted tiene como
objetivo.
Cree un script y copie/pegue este cdigo:-
// JS
function Awake() {
#if UNITY_EDITOR
Debug.Log("Unity Editor");
#endif
#if UNITY_IPHONE
Debug.Log("Iphone");
#endif
#if UNITY_STANDALONE_OSX
Debug.Log("Stand Alone OSX");
#endif
#if UNITY_STANDALONE_WIN
Debug.Log("Stand Alone Windows");
#endif
}
// C#
using UnityEngine;
using System.Collections;
#if UNITY_EDITOR
Debug.Log("Unity Editor");
#endif
#if UNITY_IPHONE
Debug.Log("Iphone");
#endif
#if UNITY_STANDALONE_OSX
Debug.Log("Stand Alone OSX");
#endif
#if UNITY_STANDALONE_WIN
Debug.Log("Stand Alone Windows");
#endif
}
}
#if UNITY_EDITOR
Debug.Log("Unity Editor");
#elif UNITY_IPHONE
Debug.Log("Unity iPhone");
#else
Debug.Log("Any other platform");
#endif
Aqu, usted puede ingresar los nombres de los smbolos que usted quiere definir para esa
plataforma en particular, separada por punto y comas. Estos smbolos pueden ser
utilizados como condiciones para directivas #if como las que estn integradas.
C#
<Project Path>/Assets/smcs.rsp
<Project Path>/Assets/gmcs.rsp
UnityScript
<Project Path>/Assets/us.rsp
Funciones genricas
Algunas funciones en la referencia de script (por ejemplo, las varias funciones
GetComponent) son listadas con una variante que tiene una letra de T o un tipo de nombre
en corchetes de ngulo despus del nombre de la funcin:
//C#
void FuncName<T>();
//JS
function FuncName.<T>(): T;
Estas son conocidas como funciones genericas. El significado que estas tienen para el
scripting es que usted puede especificar estos tipos de parmetros y/o el tipo de return
cuando usted llame la funcin. En JavaScript, esto puede ser utilizado para darle vuelta a
las limitaciones de escritura dinmica (dynamic typing):-
Rigidbody rb = go.GetComponent<Rigidbody>();
Rigidbody rb = (Rigidbody)
go.GetComponent(typeof(Rigidbody));
Cualquier funcin que tiene una variante genrica lista en su pgina script de referencia le
va a permitir esta sintaxis especial de llamado.
Serializacin de Script
La serializacin de cosas est en el ncleo de Unity. Muchas de nuestras caractersticas
estn construidas encima del sistema de serializacin:
Cargando. Puede no resultar una sorpresa, pero para una carga al revs
compatible es un sistema que est integrado encima de la serializacin tambin. En el
editor yaml, cargar utiliza el sistema de serializacin, pero tambin la carga de escenas,
assets y assetbundles en el tiempo de ejecucin utilizan el sistema de serializacin.
Cargar nuevamente el cdigo del editor. Cuando usted cambia el script del editor,
nosotros serializamos todas las ventanas del editor (ellas deriva
de UnityEngine.Object!). Luego nosotros destruimos todas las ventanas. Nosotros
descargamos el cdigo C# viejo, nosotros cargamos el nuevo cdigo C#, nosotros
recreamos las ventanas, y luego nosotros deserializamos los flujos de informacin de las
ventanas a las nuevas ventanas.
no ser static
no ser const
no ser readonly
[Serializable]
class Animal
{
public string name;
}
Si usted llena el arreglo de animales con tres referencias a un solo objeto Animal, en el
flujo de serializacin (serialization stream), usted encontrar 3 objetos. Cuando sea
deserializado, ahora hay tres diferentes objetos. Si usted necesita serializar un objeto de
grfica complejo con referencias, usted no puede depende de que el serializador de Unity
haga todo esto automticamente para usted, y necesite hace algo de trabajo para obtener
la grfica objeto serializada por usted mismo. Vea el ejemplo a continuacin en cmo
serializar cosas que Unity no serializa por s.
Tenga en cuenta que esto es solo verdad para clases personalizadas, ya que estas fueron
serializadas en linea, debido a que su informacin se vuelve parte de los datos completos
serializados para el MonoBehaviour en el cual son utilizados. Cuando usted tiene campos
que tienen una referencia a lgo que es una clase derivada de UnityEngine.Object,
como un public Camera myCamera, los datos de esa cmara no son serializados en
linea, y una referencia actual al UnityEngine.Object de la cmara es serializado,
[Serializable]
class Trouble
{
public Trouble t1;
No sera raro esperar 1 alocacin. Esa para el objeto Test. Tampoco sera raro esperar 2
alocaciones. Una para el objeto Test, y una para el objeto Trouble. La respuesta correcta
es 729. El serializado no soporta null. Si serializa un objeto, y un campo es null, nosotros
podemos instanciar un nuevo objeto de ese tipo, y serializar eso. Obviamente esto puede
llevar a ciclos infinitos, por lo que tenemos un limite de profundidad mgica relativo de 7
niveles. En este punto nosotros simplemente paramos los campos de serializacin que
tienen tipos de struct/clases personalizadas y listas y arreglos
Debido a que muchos de nuestros sub-sistemas construidos encima del sistema de
serializacin, este inesperado flujo de serializacin (serialization stream) para el Test
monobehaviour va a causar que estos subsistemas sean ms lentos de lo necesario.
Cuando nosotros investiguemos los problemas de rendimiento en nuestros proyectos
personalizados, casi siempre nosotros encontramos este problema. Nosotros hemos
agregado una advertencia para esta situacin en Unity 4.5.
using UnityEngine;
using System.Collections.Generic;
using System;
void OnGUI()
{
Display (root);
}
node.interestingValue =
GUILayout.TextField(node.interestingValue,
GUILayout.Width(200));
GUILayout.BeginHorizontal ();
GUILayout.Space (20);
GUILayout.BeginVertical ();
GUILayout.EndVertical ();
GUILayout.EndHorizontal ();
}
}
Ms bien, usted le dice a Unity que no serialize el rbol directamente, y usted hace un
campo separado para almacenar el rbol en formato serializado, adecuado para el
serializador de Unity:
using UnityEngine;
using System.Collections.Generic;
using System;
void AddNodeToSerializedNodes(Node n)
{
var serializedNode = new SerializableNode () {
interestingValue = n.interestingValue,
childCount = n.children.Count,
indexOfFirstChild = serializedNodes.Count+1
};
serializedNodes.Add (serializedNode);
foreach (var child in n.children)
AddNodeToSerializedNodes (child);
}
if (serializedNodes.Count > 0)
root = ReadNodeFromSerializedNodes (0);
else
root = new Node ();
}
children.Add(ReadNodeFromSerializedNodes(serializedNode.index
OfFirstChild + i));
interestingValue =
serializedNode.interestingValue,
children = children
};
}
void OnGUI()
{
Display (root);
}
GUILayout.BeginHorizontal ();
GUILayout.Space (20);
GUILayout.BeginVertical ();
GUILayout.EndVertical ();
GUILayout.EndHorizontal ();
}
}
Tenga cuidado que el serializador, incluyendo estos callbacks viniendo del serializador
usualmente suceden no en el thread principal, por lo cual usted est muy limitado en lo
que usted puede hacer en trminos de invocar el Unity API. Usted, sin embargo, puede
hacer las transformaciones necesarias de datos para obtener sus datos desde un formato
serializado no amigable para Unity a un formato serializado amigable para Unity.
Sistemas de desacoplamiento
Callbacks persistentes
Utilizando UnityEvents
Para configurar un callback en el editor hay varios pasos para realizar:
1.
2.
3.
4.
5.
Estticas. Llamadas estticos son llamadas pre-configuradas, con valores preconfigurados que son configurados en el UI. Esto significa que cuando el callback sea
UnityEvents Genricos
Por defecto un UnityEvent en un Monobehaviour se une de forma dinmica a una
funcin void. ste no debe ser el caso debido a que la invocacin dinmica de los
UnityEvents soportan la union a funciones con ms de 4 argumentos. Para hacer esto,
usted necesita definir una clase personalizada UnityEvent que soporte mltiples
argumentos. Esto es muy fcil de hacer:
[Serializable]
Al agregar una instancia de esto a su clase en vez del base UnityEvent , esto le va a
permitir el callback a que se una dinmicamente a funciones string.
Esto puede luego ser invocado al agregar la funcin Invoke() con un string como
argumento.
Los UnityEvents pueden ser definidos hasta con 4 argumentos en su definicin genrica.
//c# example
using UnityEngine;
using System.Collections;
El cdigo simplemente busca un game object llamado wibble. En este ejemplo no hay
game object con ese nombre, por lo que la funcin Find() devuelve null. En la siguiente
linea (Linea 9) nosotros utilizamos la variable go e intentamos e imprimimos el nombre del
game object el cual referencia. Debido a que estamos accediendo un game object que no
existe, el tiempo de ejecucin nos da una NullReferenceException
Revisiones de Null
Aunque puede ser frustrante cuando esto pase, esto solo significa que el script necesita
ser ms cuidados. La solucin en este ejemplo sencillo es cambiar el cdigo a algo as:
using UnityEngine;
using System.Collections;
void Start () {
GameObject go = GameObject.Find("wibble");
if (go) {
Debug.Log(go.name);
} else {
Debug.Log("No game object called wibble found");
}
}
Ahora, antes de que intentemos hacer algo con la variable go, nosotros revisamos que no
est null. Si es null, entonces nosotros mostramos un mensaje.
Bloques Try/Catch
Otra causa para NullReferenceException es utilizar una variable que debera ser
inicializada en el Inspector. Si usted se le olvida hacer esto, entonces la variable
ser null. Una manera diferente de solucionar la NullReferenceException son los
bloques try/catch. Por ejemplo, este cdigo:
using UnityEngine;
using System;
using System.Collections;
void Start () {
try {
myLight.color = Color.yellow;
}
catch (NullReferenceException ex) {
Debug.Log("myLight was not set in the
inspector");
}
}
En este ejemplo de cdigo, la variable llamada myLight es una Light que debera ser
configurada en la ventana del Inspector. Si esta variable no es configurada, entonces va
por defecto a ser null. Intentar cambiar el color de la luz en el bloque try va a causar
una NullReferenceException que es recogida por el bloque catch. El
bloque catch muestra un mensaje que podra ser de gran ayuda a artistas y diseadores
de juego, y les recuerda configurar las luces en el inspector.
Resumen
el problema sucede.
NullReferenceException puede ser evitado al escribir cdigo que revise
por null antes de acceder un objeto, o utilizar bloques try/catch.
Importando Clases
Estas son algunas de las clases ms importantes que usted estar utilizando cuando
programe en Unity. Estas cubre la mayora de reas principales del sistema de
programacin de Unity y proporcionan un buen punto de inicia para mirar qu funciones y
eventos son disponibles.
Clase:
Descripcin:
MonoBehaviour
Transform
Rigidbody /Rigidbody2