Sei sulla pagina 1di 98

Fsica

Para tener un comportamiento fsico convincente, un objeto en el juego debe acelerar


adecuadamente y ser afectado por colisiones, gravedad y otras fuerzas. El motor de fsica
integrado en Unity proporciona componentes que manejan la simulacin fsica para usted.
Con tan solo unos cuantos ajustes de parmetros, usted puede crear objetos que se
comporten de manera pasiva de manera realistic (ie, sern movidos por colisiones y
cadas pero no se comenzarn a moverse por s solos). Al controlar la fsica desde scripts,
usted puede darle un objeto las dinmicas de un vehculo, una maquina o incluso un
pedazo de tela movindose. Esta pgina da una vista general de los componentes
principales de fsica en Unity con links para lecturas posteriores.
Tenga en cuenta: que en realidad hay dos motores de fsica separados en Unity, uno para
fsicas de 3D y otro para fsicas de 2D. Los conceptos principales son idnticos entre los
dos motores (excepto por la dimensin extra en 3D) pero son implementados con
diferentes componentes. Entonces por ejemplo, hay un componente Rigidbody para
fsicas 3D y unRigidbody 2D anlogo para fsicas 2D.

Visin General de la Fsica


Estas pginas brevemente describen los componentes de la fsica principal disponibles en
Unity y da detalles de su uso y enlaces para una lectura ms profunda.

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.

Las acciones del script tomadas en la colisin


Cuando la colisin ocurre, el motor de fsica llamada las funciones con nombres
especficos en cualquier script adjuntado a los objetos involucrados. Usted puede colocar
cualquier cdigo que usted quiera en estas funciones para responder al evento de colisin.
Por ejemplo, usted podra reproducir un efecto de sonido que se estrella cuando un carro
se choca a un obstculo.
En la primera actualizacin de fsica dnde la colisin es detectada, la
funcin OnCollisionEnter es llamada. Durante las actualizaciones dnde el contacto
se mantiene, OnCollisionStay se llama y finalmente OnCollisionExit indica que el
contacto se ha roto. Los Trigger colliders llaman a las funciones
anlogas OnTriggerEnter, OnTriggerStay y OnTriggerExit. Tenga en cuenta que
para fsicas 2D, hay funciones equivalentes con 2D anexado al nombre,
eg, OnCollisionEnter2D. Detalles completos de estas funciones y ejemplos de cdigo
pueden ser encontrados en la pgina de referencia de script para la clase MonoBehaviour.

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.

Interacciones del Collider


Los Colliders interactan con cada uno de manera diferente dependiendo en cmo
sus Rigidbody components estn configurados. Las tres configuraciones importantes
son Static Collider (ie, ningn Rigidbody est adjunto), el Rigidbody Collidery el Kinematic
Rigidbody Collider.

Static Collider (Colisionador esttico)


Este es un GameObject que tiene un Collider pero sin Rigidbody. Los Static Colliders son
utilizados para nivela la geometra la cual siempre se mantiene en su mismo lugar y nunca
se mueve. Los objetos Rigidbody entrantes van a colisionar con el static collider pero no lo
mover.
El motor de fsica asume que los static collider nunca se mueven o cambian y pueden
hacer uso de optimizaciones basadas en esta asuncin. Consecuentemente, los static
colliders debera no ser activados/desactivados, movidos o escaladas durante el juego. Si
usted cambia un static collider entonces esto resultar en un re-computacin extra interna
por el motor de fsica que va a causar un grave problema en rendimiento. Peor aun, los
cambios a veces dejan el collider en un estado indefinido que produce a veces clculos
fsicos erroneos. Por ejemplo un raycast contra un static collider alterado puede fallar
detectarlo, o detectarlo en una posicin aleatoria en el espacio. Adicionalmente, los
Rigidbodies que son golpeados por un static collider en movimiento no necesariamente se
despertar y el static collider no va a aplicar friccin. Por estas razones, solo los colliders
que son Rigidibodies deberan ser alterados. Si usted quiere un objeto collider que no sea
afectado por rigidbodies entrantes pero todava moverse desde un script usted debera
adjuntar un componente Kinematic Rigidbody a ste.

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.

Kinematic Rigidbody Collider


Este es un GameObject con un Collider y un kinematic Rigidbody adjunto (ie, la
propiedad IsKinematic est activada). Usted puede mover un objeto kinematic ridibody
desde script modificando su componente Transform pero no responder a colisiones y
fuerzas como un no-kinematic rigidbody. Los Kinematic rigidbodies deberan ser utilizados
para colliders que pueden ser movidos o desactivados/activados ocasionalmente pero que
de otra manera debera comportarse como static colliders. Un ejemplo de esto es deslizar
una puerta que normalmente debera actuar como un obstculo fsico inmovible pero
puede se puede abrir cuando sea necesario. Al contrario de un static collider, un rigidoby
kinematico en movimiento va a aplicar friccin a otros objetos y despertar otros
rigidbodies cuando entren en contacto.
Incluso cuando kinematic rigidbody colliders inmovibles tienen diferente comportamiento a
static colliders. Por ejemplo, si el collider es configurado como un trigger entonces usted
tambin necesita agregar un rigidbody a l con el fin de que reciba eventos triggers en su
script. Si usted no quiere que el trigger caiga bajo de gravedad o de otra manera ser
afectado por fsica entonces usted puede configurar la propiedad IsKinematic en su
rigidbody.
Un componente Rigidbody pueden intercambiarse entre comportamiento normal y
kinematic en cualquier momento utilizando la propiedad IsKinematic.
Un Componente Rigidbody puede ser cambiado entre un comportamiento normal y
kinematic en cualquier momento utilizando la propiedad IsKinematic . Un ejemplo comn
de esto es el efecto ragdoll dnde un personaje normalmente se mueve con animaciones
pero es lanzado fsicamente por una explosin o una colisin fuerte. Las extremidades del
personaje pueden ser cada uno dados su propio componente Rigidbody
con IsKinematic activado por defecto. Las extremidades se movern por lo general por
animaciones hasta que IsKinematic se desactive para todos ellos e inmediatamente se
comportan como objetos de fsica. En este punto, una colisin o explosin va a mandar al
personaje volando con sus extremidades lanzadas de una manera convincente.

La matriz de accin de colisin


Cuando dos objetos colisionan, hay un nmero de diferente eventos de script que pueden
ocurrir dependiendo en las configuraciones de los rigidbodies de los objetos colisionando.
La tablas a continuacin dan detalles de qu funciones de eventos son llamadas
basndose en los componentes que estn adjuntos a los objetos. Algunas combinacin
solamente causas uno de los dos objetos a ser afectados por la colisin, pero la regla
general es que la fsica no ser aplicada al objeto que no tiene un componente Rigidbody
adjunto.

La deteccin de Colisin ocurre y los mensajes son mandados al momento


de colisionar

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

Los mensajes del trigger son mandas al momento de colisionar

Static

Rigidbod

Kinematic

Static

Rigidbody

Kinematic

Collide

y Collider

Rigidbody

Trigger

Trigger

Rigidbody

Collider

Collider

Collider

Trigger

Collider

Los mensajes del trigger son mandas al momento de colisionar

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

Controllers (Controladores de Personaje)

El personaje en un juego de primera o tercera persona a menudo requerir alguna fsica


basada en colisiones de tal forma que no se caiga a travs del suelo o camine a travs de
las paredes. Sin embargo, por lo general, la aceleracin y el movimiento del personaje no
sern fsicamente realistas, as que este puede que acelere, frene o cambie de direccin
casi instantneamente sin ser afectado por el momentum (cantidad de movimiento).
En fsicas 3D, este tipo de comportamiento puede ser creado usando un Character
Controller. Este componente le da al personaje un simple collider (colisionador) en forma
de capsula que siempre est en posicin vertical. El controlador tiene sus propias
funciones especiales para establecer la velocidad y direccin del objeto pero a diferencia
de los verdaderos colliders, un rigidbody no es requerido y los efectos del momentum no
son realistas.
Un character controller (controlador de personaje) no puede caminar a travs de colliders
estticos (static) en una escena, de igual forma seguir suelos y ser obstruido por
paredes. Puede empujar hacia un lado objetos con un rigidbody mientras se mueve, pero
no ser acelerado por colisiones entrantes. Esto significa que usted puede usar los
colliders 3D estndar para crear una escena alrededor de la cual el controlador caminar
pero usted no estar limitado por el comportamiento fsico realista en el personaje en s.
Puede encontrar ms acerca de los character controllers (controladores de personaje) en
la pgina de referencia.

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

Si est habilitada, este Collider ser usado para eventos de triggering, y


ser ignorado por el motor de fsica.

Material

Referencia al Physics Material que determina en qu forma este Collider


inteacta con otros.

Center

La posicin del Collider en el espacio local del objeto.

Size

El tamao del Collider en las direcciones X, Y, Z.

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

Si est habilitada, este Collider ser usado para eventos de triggering, y

Propiedad
:

Funcin:

ser ignorado por el motor de fsica.

Material

Referencia al Physics Material que determina en qu forma este Collider


inteacta con otros.

Center

La posicin del Collider en el espacio local del objeto.

Radius

El radio del ancho local del Collider

Height

La altura total del Collider.

Direction

El eje de orientacin longitudinal de la capsula en el espacio local del


objeto.

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.

Un Capsule Collider Estndar

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.

Visin General de Scripting


Aunque Unity utiliza una implementacin de un tiempo de ejecucin estndar Mono para
scripting, ste todava tiene sus propias prcticas y tcnicas para acceder al motor desde
scripts. Esta seccin explica cmo los objetos creados en el editor de Unity son
controlados desde scripts y detalla la relacin entre las caractersticas de juego de Unity y
el tiempo de ejecucin de Mono.

Creando y usando scripts


El comportamiento de GameObjects es controlado por los Components los cuales estn
adjunto. Aunque los Componentes integrados de Unity pueden ser muy versatiles, usted
encontrar que va a necesitar ir ms all de lo que pueden proporcionar para implementar
las propia caractersticas de su juego. Unity le permite a usted crear su propio
Componente utilizandoscripts. Estos le permite a usted trigger eventos de juego, modificar
propiedades del Componente en el tiempo y responder al input del usuario de la forma que
usted quiera.
Unity soporta dos lenguajes nativamente:

C# (pronunciado C-sharp), un lenguaje de la industria estndar similar a Java o C+


+;

UnityScript, un lenguaje diseado especficamente para uso con Unity y modelado


tras JavaScript;
Adicional a estos, otros lenguajes .NET pueden ser utilizados con Unity si estos compilan
un DLL compatible - ver aqu para ms detalles.
Aprender el arte de programar y el uso de estos lenguajes en particular, va ms all del
alcance de esta introduccin. Sin embargo, hay muchos libros, tutoriales y otros recursos
para aprender cmo a programar con Unity. Vea la Learning sectionde nuestra pgina web
para ms detalles.

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.

Anatomia de un archivo Script.


Cuando usted hace doble click en un asset de script en Unity, ste se abrir en el editor de
texto. Por defecto, Unity va a utilizar MonoDevelop, pero usted puede seleccionar cualquier
editor que a usted le guste desde el panel Externa Tools en las preferencias de Unity.
Los contenidos iniciales del archivo se vern algo como esto:

using UnityEngine;
using System.Collections;

public class MainPlayer : MonoBehaviour {

// Use this for initialization


void Start () {

// Update is called once per frame


void Update () {

}
}

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

adjuntado a GameObjects. Cada vez que usted adjunte un componente script a un


GameObject, ste crea una nueva instancia del objeto definido por el plano. El nombre de
la clase es tomado desde el nombre que usted proporciona cuando el archivo es creado.
El nombre de la clase y archivo se debi suministrar cuando el archivo fue creado. El
nombre de la clase y archivo debe ser el mismo para permitirle al componente script en ser
adjuntado al GameObject.
La primera cosa para tener en cuenta, sin embargo, son dos funciones definidas dentro de
la clase. La funcin Update es el lugar para colocar cdigo que se encargar de la
actualizacin por cuadro (Frame) para el GameObject. Este puede incluir movimiento,
acciones de trigger y responder al input del usuario, bsicamente cualquier cosa que
necesite ser manejado en el tiempo durante el gameplay. Para que la funcin Update haga
su trabajo, a veces es til ser capaz de configurar variables, leer preferencias y hacer
conexiones con otros GameObjects antes de que cualquier accin del juego tome lugar. La
funcin Startva a ser llamada por Unity antes de que el gameplay comience (ie, antes de
que la funcin Update sea llamada por la primera vez) y es un lugar ideal para hacer
cualquier inicializacin.
Recomendacin para programadores con experiencia: Usted puede sorprenderse que la
inicializacin de un objeto no es hecho utilizando una funcin constructora. Esto se debe a
que la construccin de los objetos es manejado en el editor y no toma lugar al comienzo
del gameplay como usted podra suponer. Si usted intenta definir un constructor para un
componente script, ste va a interferir con la operacin normal de Unity y puede causar
problemas mayores con el proyecto.
Una script de UnityScript funciona un poco diferente a un script de C#:

#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:-

// Use this for initialization


void Start () {
Debug.Log("I am alive!");
}

Debug.Log es un simple comando que imprime un mensaje al output de consola de Unity.


Si usted presiona Play ahorita, usted debera ver el mensaje en la parte inferior de la
ventana principal del editor de Unity y en la ventana de la consola (menu: Window >
Console).

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;

public class MainPlayer : MonoBehaviour {


public string myName;

// Use this for initialization


void Start () {
Debug.Log("I am alive and my name is " + myName);
}

// Update is called once per frame


void Update () {

}
}

Este cdigo crea un campo editable en el Inspector llamado My Name.

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

private var invisibleVar: int;

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.

Controlar GameObjects utilizando Componentes


En el editor de Unity, usted hace cambios a las propiedades del Componente utilizando el
Inspector. Entonces, por ejemplo, los cambios a los valores de posicin del Componente
Transform resultarn en un cambio en la posicin del GameObject. Similarmente, usted
puede cambiar el color del material del Renderer o la masa del Rigidbody con un efecto
correspondiente en la apariencia o comportamiento del GameObject. Para la mayora de
parte, scripting tambin es acerca de modificar las propiedades del Componente para
manipular GameObjects. La diferencia, en cambio, es que un script puede variar el valor
de la propiedad gradualmente sobre el tiempo o en una respuesta al input del usuario. Al
cambiar, crear y destruir objetos en el tiempo adecuado, cualquier modo de juego puede
ser implementado.

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>();
}

En UnityScript, la sintaxis es un poco diferente:

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>();

// Change the mass of the object's Rigidbody.

rb.mass = 10f;
}

Una caracterstica extra la cual no est disponible en el Inspector es la posibilidad de


llamar funciones o instancias de Componente:

void Start () {
Rigidbody rb = GetComponent<Rigidbody>();

// Add a force to the Rigidbody.


rb.AddForce(Vector3.up * 10f);
}

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.

Accediendo Otros Objetos


Aunque a veces operan en aislamiento, es comn para script de mantener registro de
otros objetos. Por ejemplo, un enemigo que est persiguiendo podra necesitar saber la
posicin del jugador. Unity proporciona un nmero de diferente formas de recuperar otros
objetos, cada una apropiada a ciertas situaciones.

Enlazando Objetos con Variables


La manera ms directa de encontrar un GameObject relacionado es agregar una variable
public GameObject a un script:

public class Enemy : MonoBehaviour {


public GameObject player;

// Other variables and functions...


}

Esta variable estar visible en el Inspector como cualquier otra:

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:

public class Enemy : MonoBehaviour {


public GameObject player;

void Start() {
// Start the enemy ten units behind the player
character.

transform.position = player.transform.position Vector3.forward * 10f;


}
}

Adicionalmente, si una variable public es declarada de un tipo de Componente en su script,


usted puede arrastrar cualquier GameObject que tiene un Componente adjunto. Esto va a
acceder el componente directamente en vez del GameObject en s mismo.

public Transform playerTransform;

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.

Encontrando Child Objects (Objetos Hijos)


A veces, una escena de juego har uso de un nmero de objetos del mismo tipo, como lo
son los enemigos, puntos de inters, y obstculos. Estos pueden necesitar ser rastreados
por un script en particular que supervise o reaccione a estos (eg, todos los puntos de
inters pueden necesitar estar disponible para un script pathfinding). Utilizar variables para
vincular estos objetos es una posibilidad pero eso har que el proceso de diseo sea
tedioso si cada nuevo punto de inters tiene que ser arrastrado a una variable en una
script. Del mismo modo, si un punto de inters es eliminado entonces es una molestia
tener que quitar la variable que referencia al objeto que falta. En casos como estos, a
veces es mejor manejar el conjunto de objetos al hacerlos todos hijos de un objeto padre.
Los objetos hijos pueden recuperarse utilizando el Componente del Transform del padre
( ya que todos los GameObjects implicitamente tienen un Transform):

using UnityEngine;

public class WaypointManager : MonoBehaviour {


public Transform[] waypoints;

void Start() {
waypoints = new Transform[transform.childCount];
int i = 0;

foreach (Transform t in transform) {


waypoints[i++] = t;
}
}
}

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.

Encontrando Objetos por Name (nombre) o Tag (Etiqueta)


Siempre es posible ubicar GameObjects dnde sea en la Jerarqua de la escena mientras
usted tenga alguna informacin para identificarlos. Objetos individuales pueden ser
recuperados por nombre utilizando la funcin GameObject.Find.

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");
}

Event Functions (Funciones de Evento)


Un script en Unity no es como cualquier otra idea tradicional de un programa dnde el
cdigo corre continuamente en un ciclo hasta que complete su tarea. En vez, Unity pasa el
control a un script de forma intermitente al llamar ciertas funciones que estn declaradas
dentro de l. Una vez una funcin haya finalizado de ejecutarse, el control es devuelto a
Unity. Estas funciones son conocidas como event function (funciones de evento) ya que
son activadas por Unity en respuesta a eventos que ocurren durante el tiempo de juego.
Unity utiliza un esquema de nombramiento para identificar qu funciones llamar para un
evento en particular. Por ejemplo, usted ya habr visto la funcin Update (llamada antes
que una actualizacin de cuadro ocurra) y la funcin Start (llamada justo antes de la
primera actualizacin de cuadro del objeto). Muchas ms funciones de evento estn
disponibles en Unity; la lista completa puede ser encontrada en la pgina de referencia
script para la clase MonoBehaviour junto con los detalles de su uso. Las siguientes son
algunas de las ms comunes e importantes.

Eventos Actualizados Regularmente


Un juego es como una animacin dnde los cuadros de animacin son generado en la
marcha. Un concepto clave en la programacin de juegos es el de hacer cambios a la
posicin, estados, y comportamientos de objetos en el juego justo antes de cada cuadro es
renderizado. La funcin Update es el lugar principal para este tipo de cdigo en Unity.
Update es llamado antes de que el cuadro sea renderizado y tambin antes de que las
animaciones sean calculadas.

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

resultado ms preciso de cdigo de fsica si usted lo coloca en la funcin de FixedUpdate


en vez de Update.

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

actualizacin de fsica y entonces un parmetro es pasado a la funcin dando detalles de


la colisin (posicin, identidad del objeto que llega, etc).

void OnCollisionEnter(otherObj: Collision) {


if (otherObj.tag == "Arrow") {
ApplyDamage(10);
}
}

Administrador del Tiempo y Framerate


La funcin Update le permite a usted monitorear inputs y otros eventos regularmente
desde un script y tomar una accin apropiada. Por ejemplo, usted podra mover un
personaje cuando la tecla hacia adelante est presionada. Una cosa importante para
acordarse cuando maneje acciones basadas en el tiempo coomo sta es que el framerate
del juego no es constante y tampoco lo es el periodo de tiempo entre llamados de
funciones Update.
Un ejemplo de esto, considere la tarea de mover un objeto gradualmente hacia adelante,
un cuadro a la vez. Podra parecer a primera que usted puede simplemente trasladar el
objeto por una distancia fija cada cuadro:

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {

public float distancePerFrame;

void Update() {
transform.Translate(0, 0, distancePerFrame);
}
}

//JS script example


var distancePerFrame: float;

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:

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


public float distancePerSecond;

void Update() {
transform.Translate(0, 0, distancePerSecond *
Time.deltaTime);
}
}

//JS script example


var distancePerSecond: float;

function Update() {

transform.Translate(0, 0, distancePerSecond *
Time.deltaTime);
}

Tenga en cuenta que el movimiento es ahora dado en distancePerSecond en vez


de distancePerFrame. A medida que el framerate cambia, el tamao de la etapa de
movimiento cambiar de acuerdo y as la velocidad del objeto ser constante.

Fixed Timestep (Timestep fijo)


A diferencia de la actualizacin principal del cuadro, el sistema de fsica de
Unity funciona a un timestep fijo, el cual es importante para la precisin y consistencia de
la simulacin. Al comienzo de la actualizacin de fsica, Unity configura una alarma al
agregar el valor del timestep fijo al tiempo dnde termino la ltima actualizacin de fsica.
El sistema de fsica luego va a realizar clculos hasta que la alarme se apague.
Usted puede cambiar el tamao del timestep fijo desde el Time Manager

Mximo Timestep Permitido


El timestep fijo sigue la simulacin de fsica de manera precisa en tiempo real pero puede
causar problemas en casos dnde el juego hace un uso fuerte de fsica y el framerate del
gameplay puede tambin volverse bajo (debido a un gran nmero de objetos en
reproduccin, digamos). El procesamiento de la actualizacin de cuadro(frame update)
principal tiene que ser apretado entre las actualizaciones de fsica regulares y si hay
mucho procesamiento entonces varias actualizaciones de fsica pueden tomar lugar
durante un solo frame. Debido al frame time, posiciones de objetos y otras propiedades
son congeladas en el comienzo del frame, las grficas pueden perder sincronizacin con la
actualizacin de fsica con ms frecuencia.
Naturalmente, hay bastante poder de CPU disponible pero Unity tiene una opcin que le
permite a usted efectivamente disminuir el tiempo de fsica para permitir que el
procesamiento de frame alcance. La configuracin Maximum Allowed Timestep (en el Time
Manager) pone un limite en la cantidad de tiempo Unity va a gastar procesando llamados
de fsica y FixedUpdate durante un update (Actualizacin) del frame dado. Si una
actualizacin del cuadro toma ms que el Maximum Allowed Timestep para procesar, el
motor de fsica va a parar el tiempo y le va a permitir al procesamiento de cuadros que
alcance. Una vez la actualizacin de cuadro ha finalizado, la fsica va a resumir como si no
hubiera pasado tiempo desde que paro. El resultado de esto es que los rigidbodies no se
movern perfectamente en el tiempo real como debera pero sern un poco ms lentos.

Sin embargo, el reloj de fsica va a comenzar hacer un seguimiento de estos como si se


estuvieran moviendo de manera normal. La disminucin del tiempo de fsica usualmente
no se nota y es un cambio aceptable contra el rendimiento del gameplay.

Time Scale (Escala del tiempo)


Para efectos especiales, como bullet-time, a veces es til disminuir el tiempo de juego
para que las animaciones y respuestas de script ocurran en una velocidad reducida.
Adicionalmente, usted podra querer a veces congelar el tiempo del juego completamente,
como cuando el juego es pausado. Unity tiene una propiedad Time Scale que controla qu
tan rpido el tiempo de juego ocurre relativo al tiempo real. Si la escala est configurada a
1.0 entonces el tiempo de juego concuerda con el tiempo real. Un valor de 2.0 hace que el
tiempo pase el doble de rpdio que en Unity (ie, la acin va a aumentar) mientras un valor
de 0.5 va a disminuir el gameplay a la mitad de la velocidad. Un valor de cero har que el
tiempo pare completamente. Tenga en cuenta que la escala del tiempo no disminuye la
ejecucinpero simplemente cambia el time step reportado a las funcones Update y
FixedUpdate va Time.deltaTime y Time.fixedDeltaTime. La funcin Update es probable
que sea llamada ms a menudo que o usual cuando el tiempo de juego ha sido disminuido
pero el step de deltaTime reportado cada cuadro va a simplemente ser reducido. Otras
funciones de sript no estn afectadas por la escala de tiempo por lo que usted puede, por
ejemplo, mostrar un GUI con una interaccin normal cuando el juego est pausado.
El Time Manager tiene una propiedad que le permite a usted configurar la escala de tiempo
globalmente pero por lo general es ms til configurarlo al valor desde un script utilizando
la propiedad Time.timeScale.

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


void Pause() {
Time.timeScale = 0;

void Resume() {
Time.timeScale = 1;
}
}

//JS script example


function Pause() {
Time.timeScale = 0;
}

function Resume() {
Time.timeScale = 1;
}

Capture Framerate (Capturar el Framerate)


Un caso muy especial del time management (administrador de tiempo) es dnde usted
quiere grabar el gameplay como un video. Debido a que la tarea de guardar las imgenes
de pantalla toman un tiempo considerable, el framerate usual del juego ser drsticamente

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:

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


// Capture frames as a screenshot sequence. Images are
// stored as PNG files in a folder - these can be
combined into
// a movie using image utility software (eg, QuickTime
Pro).
// The folder to contain our screenshots.
// If the folder exists we will append numbers to create
an empty folder.
string folder = "ScreenshotFolder";

int frameRate = 25;

void Start () {
// Set the playback framerate (real time will not
relate to game time after this).
Time.captureFramerate = frameRate;

// Create the folder


System.IO.Directory.CreateDirectory(folder);
}

void Update () {
// Append filename to folder name (format is '0005
shot.png"')
string name = string.Format("{0}/{1:D04} shot.png",
folder, Time.frameCount );

// Capture the screenshot to the specified file.


Application.CaptureScreenshot(name);

}
}

//JS script example

// Capture frames as a screenshot sequence. Images are


// stored as PNG files in a folder - these can be combined
into
// a movie using image utility software (eg, QuickTime Pro).
// The folder to contain our screenshots.
// If the folder exists we will append numbers to create an
empty folder.
var folder = "ScreenshotFolder";
var frameRate = 25;

function Start () {
// Set the playback framerate (real time will not relate
to game time after this).

Time.captureFramerate = frameRate;

// Create the folder


System.IO.Directory.CreateDirectory(folder);
}

function Update () {
// Append filename to folder name (format is '0005
shot.png"')
var name = String.Format("{0}/{1:D04} shot.png", folder,
Time.frameCount );

// Capture the screenshot to the specified file.


Application.CaptureScreenshot(name);
}

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.

Creando y destruyendo GameObjects.

Algunos juegos mantienen un nmero constante de objetos en la escena, pero es muy


comn para los personajes, tesoros y otros objetos ser creados y eliminados a la hora de
jugar (gameplay). En Unity, un GameObject puede ser creado utilizando la
funcin Instantiate la cual crea una nueva copia de un objeto existente:

public GameObject enemy;

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:

void OnCollisionEnter(Collision otherObj) {


if (otherObj.gameObject.tag == "Missile") {
Destroy(gameObject,.5f);

}
}

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.

Carpetas Especiales y Orden de Compilacin de Script (Script Compilation Order)


Para la mayora de tiempo, usted puede escoger cualquier nombre que usted le guste para
las carpetas de su proyecto pero Unity reserva algunos nombres para indicar que el
contenido tiene un propsito especial. Algunas de estas carpetas tienen un efecto en el
orden de compilacin de script. Esencialmente, hay cuatro fases separadas de compilacin
de script y en la fase dnde el script va a compilar ser determinado por la carpeta padre.
Este es uno de los casos significantes dnde un script debe referir clases definidas en
otros scripts. La regla bsica es que cualquier cosa que sea compilada en una
fase despus de que el actual no puede ser referencia. Cualquier cosa que sea compilada
en la fase actual o en una fase ms temprana est completamente disponibles.
Otra situacin ocurre cuando un script es escrito en otro lenguaje y debe ser referenciado
a una clase definida en otro lenguaje (dijamos, en un archivo UnityScript que declere
variables de una clase definida en script C#). La regla aqu es que la clase siendo
referencia debe ser compilada en una fase temprana.
Las fases de compilacin son como siguen:
Fase 1: Los scripts en tiempo de ejecucin en carpetas llamadas Standard Assets, Pro
Standard Assets y Plugins.
Fase 2: Los scripts del editor en carpetas llamadas Standard Assets/Editor, Pro
Standard Assets/Editor y Plugins/Editor.

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 {
...
}

public class Controller2 : MonoBehaviour {


...
}
}

En cdigo, estas clases son referenciadas


como Enemy.Controller1 y Enemy.Controller2, respectivamente. Esto es mejor
que mantener las clases en medida a que las declaraciones de namespace puedan ser
metidas entrecorchetes alrededor de declaraciones de clases existentes (ie, no es
necesariamente que cambie los nombres de las clases individualmente). Adicionalmente,
usted puede utilizar muchas secciones entrecorchetes de namespace alrededor de clases
dnde sea que ocurran, incluso si esas clases son diferentes archivos fuentes.
Puedes evitar tener que teclear varias veces el prefijo del namespace aadiendo una
directiva using al comienzo del archivo.

using Enemy;

La linea indica que dnde el nombre de la clases Controller1 y Controller2 sean


encontradas, estas deberan ser tomadas para que

signifiquen Enemy.Controller1 y Enemy.Controller2, respectivamente. Si el script tambin


necesita referenciar otras clase con el mismo nombre desde un diferente namespace (una
llamada Player, digamos), luego el prefijo puede todava ser utilizado. Si los dos
namespaces que contienen nombres de clases que choquen son importados utilizando las
directivas al mismo tiempo, el compilador va a reportar un error.

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.

Execution Order of Event Functions (Orden de Ejecucin de Funciones de Evento)


En el scripting de Unity, hay un nmero de funciones de evento que no son ejecutadas en
el orden predeterminado como un script ejecuta. Este orden de ejecucin es descrito
abajo:

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.

First Scene Load (Cuando carga la primera escena)


Estas funciones son llamadas cuando la escena comienza (una para cada objeto en la
escena).

Awake: Esta funcin siempre es llamada antes de cualquier funcin Start y


tambin justo despus de que un prefab es instanciado. (Si un GameObject est inactivo
durante el comienzo Awake no es llamado hasta que se vuelva activo, o una funcin en

cualquier script adjunto a l sea llamada.)


OnEnable: (solamente es llamado si el Objeto est activo): Esta funcin es
llamada justo despus de que el objeto es activado. Esto sucede cuando una instancia de
MonoBehaviour es creada, tal como cuando un nivel es cargado o un GameObject con un
componente script es instanciado.
Tenga en cuenta que para todos los objetos agregados a la escena, las funciones Awake y
OnEnable para todos los scripts sern llamados antes de que Start, Update, etc sean
llamados en cualquiera de ellos. Naturalmente, esto no se puede lograr cuando un objeto
es instanciado durante el gameplay.

Antes de la actualizacin del primer frame

Start: Start es llamado antes de la primera actualizacin de frame solo si la


instancia del script est activada.
Para objetos agregados a la escena, la funcin Start ser llamada en todos los scripts
antes que Update , etc sean llamadas para cualquier de ellos. Naturalmente, esto no
puede suceder cuando un objeto es instanciado durante gameplay.

Entre frames

OnApplicationPause: Esto es llamado al final del frame dnde la pausa es


detectada, efectivamente entre actualizaciones de frame normales. Un frame extra ser
despachado despus de que OnApplicationPause sea llamado para permitirle al juego
mostrarle grficas que indican el estado pausado.

Update Order (Orden de Actualizacin)


Cuando usted hace seguimiento de la lgica de juego y las interacciones, animaciones,
posiciones de cmara, etc., hay unos eventos diferentes que usted puede utilizar. El patrn
comn es realizar la mayora de tareas dentro de la funcin Update, pero tambin hay
otras funciones que usted puede utilizar.

FixedUpdate: FixedUpdate a veces es ms llamada que Update. Puede ser


llamada mltiples veces por frame, si la velocidad de frame es baja y puede no ser llamada
entre frames en absoluto si la velocidad de frame es alta. Todos los clculos de fsica y
actualizaciones ocurren inmediatamente despus de FixedUpdate. Cuando aplique
clculos de movimiento dentro de FixedUpdate, usted no necesita multiplicar sus valores
por Time.deltaTime. Esto se debe a queFixedUpdate en un temporizador fiable,
independiente de la velocidad de frames.

Update: Update es llamada una vez por frame. Es la funcin principal para las
actualizaciones de frames.

LateUpdate: LateUpdate es llamada una vez por frame, despus de


que Update haya finalizado. Cualquier clculo que sea realizado en Update ser
completado cuando LateUpdate comience. Un uso comn para LateUpdate sera una
cmara de tercera persona que sigue. Si usted hace que su personaje se mueva y
gire, Update, usted puede realizar todos los clculos de movimientos de cmara y
rotacin en LateUpdate. Esto asegurara que el personaje haya sido movido
completamente antes de que la cmara haga un seguimiento a su posicin.

Rendering (Renderizacin)

OnPreCull: Llamado antes de que la cmara corte (culls) la escena . Culling


determina qu objetos son visibles a la cmara. OnPreCull es llamado justo antes de que

el culling tome lugar.


OnBecameVisible/OnBecameInvisible: Llamado cuando un objeto se vuelve

visible/invisible a cualquier cmara.


OnWillRenderObject: Llama una vez para cada cmara si el objeto es visible.

OnPreRender: Llamado antes de que la cmara comience a renderizar la escena.

OnRenderObject: Llamado despus de que toda la renderizacin regular de la


escena es hecha. Usted puede utilizar GL class o Graphics.DrawMeshNow para dibujar
geometra personalizada en este punto.

OnPostRender: Llamado despus de que una cmara finalice de renderizar la

escena.
OnRenderImage: Llamado despus de que la renderizacin de escena est

completa para permitirle un post-procesamiento de la imagen de la pantalla.


OnGUI: Llamado mltiples veces por frame en respuesta a los eventos GUI. El
Layout y los eventos de Repaint son procesado primero, seguidos por un evento de Layout

y de teclado/mouse para cada evento de input.


OnDrawGizmos Utilizado para dibujar Gizmos en la vista de escena por
propsitos de visualizacin.

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:

yield La coroutine va a continuar despus de que todas las funciones Update

hayan sido llamadas en el siguiente frame.


yield WaitForSeconds Contina despus de un retraso de un tiempo especfico,

despus de que todas las funciones Update hayan sido llamadas para el frame
yield WaitForFixedUpdate Continua despus de que todos los FixedUpdate

hayan sido llamadas en todos los scripts.


yield WWW Contina despus de que una descarga WWW haya sido completada

yield StartCoroutine Encadenada la coroutine, y va a esperar para que la


coroutine MyFunc haya sido completado primero.

Cuando el Objeto es Destruido

OnDestroy: Esta funcin es llamada despus de que todas las actualizaciones de


frame para el ltimo frame de la existencia del objeto (el objeto puede ser destruido en
respuesta a Object.Destroy o al cerrarse la escena).

Cuando Salga
Estas funciones son llamadas en todos los objetos activos en su escena:

OnApplicationQuit: Esta funcin es llamada en todos los game objects antes de


que se salga de la aplicacin. En el editor es llamada cuando el usuario para el modo de
reproduccin. En el web player (Reproductor web) es llamada cuando la vista de web es

cerrada.
OnDisable: Esta funcin es llamada cuando el comportamiento se vuelve inactivo
o deshabilitado.

Diagrama de Flujo del Ciclo de Vida de Script


El siguiente diagrama resume el orden y repeticin de funciones de evento durante la vida
de script.

Entender la Gestin Automtica de Memoria


Cuando un objeto, cadena o array es creado, la memoria requerida para almacenarlo se
asigna desde un pool central llamada la pila. Cuando el tem ya no est ms en uso, la
memoria que una vez ocupaba puede ser recuperada y usada para otras cosas ms. En el
pasado, era responsabilidad del programador el asignar y liberar estos bloques de
memoria de la pila en forma explcita usando las llamadas de funcin apropiadas. Hoy en
da, los sistemas en tiempo de ejecucin como el motor Mono de Unity gestionan la
memoria automticamente. La gestin automtica de memoria requiere menos esfuerzo de
escritura de cdigo que asigne/libera explcitamente, y reduce enormemente la posibilidad
de una fuga de memoria (situacin en donde la memoria es asignada, pero nunca es
liberada despus).

Tipos de valor y tipos de referencia


Cuando una funcin es llamada, los valores de sus parmetros son copiados a un rea de
la memoria que es reservada para este llamado en especfico. Los tipos de datos que
ocupan slo unos pocos bytes pueden ser copiados en forma muy rpida y fcil. Sin
embargo, es comn que los objetos, cadenas y arrays sean muy grandes, y sera muy
ineficiente si estos tipos de datos fueran copiados con regularidad. Afortunadamente, esto
no es necesario; el verdadero espacio de almacenamiento para un tem grande es
asignado desde la pila y un pequeo valor de apuntador es usado para recordar su
ubicacin. A partir de entonces, slo el apuntador necesita ser copiado durante el paso de
parmetros. Siempre que el sistema en tiempo de ejecucin pueda localizar el tem
identificado por el apuntador, una copia sencilla de los datos puede ser usada tan a
menudo como sea necesario.
Los tipos que son almacenados directamente y copiados durante el paso de parmetros
son llamados tipos de valor (value types). Entre estos estn los integers, floats, booleans y
los tipos de estructuras de Unity (p.ej. Color y Vector3). Los tipos que son asignados en
la pila y luego accesados por medio de un puntero son llamados tipos de referencia
(reference types), dado que el valor almacenado en la variable slo se refiere a los datos
reales. Ejemplos de tipos de referencia son los objetos, las cadenas y los arrays.

Asignacin y recoleccin de basura


El gestor de memoria realiza un seguimiento de las reas de la pila que se sepa que no
estn siendo usadas. Cuando un nuevo bloque de memoria es solicitado (digamos, cuando
un objeto es instanciado), el gestor escoge un rea no usada a la que se le asigna el
bloque y luego remueve la asignacin de memoria en el espacio no usado conocido.
Solicitudes posteriores son manejadas del mismo modo hasta que no hayan suficientes

reas libres y grandes para asignar el tamao de bloque solicitado. Es altamente


improbable en este punto que toda la memoria asignada de la pila est todava en uso. Un
tem por referencia en la pila nicamente puede ser accedido en la medida que todava
hayan variables por referencia que puedan localizarlo. Si todas las referencias a un bloque
de memoria se han ido (es decir, las variables por referencia han sido reasignadas, o hay
variables locales que estn fuera de alcance) entonces la memoria que ocupan puede ser
reasignada en forma segura.
Para determinar cules bloques de la pila no estn ms en uso, el gestor de memoria
busca a travs de todas las variables por referencia activas y marca los bloques que stas
estn sealando como bloques vivos. Al final de la bsqueda, cualquier espacio entre los
bloques vivos es considerado como vaco por el gestor de memoria y puede ser usado
para posteriores asignaciones. Por motivos obvios, el proceso de localizar y liberar
memoria no usada es conocido como recoleccin de basura (o abreviadamente, GC por
Garbage Collection).

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:-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {

void ConcatExample(int[] intArray) {


string line = intArray[0].ToString();

for (i = 1; i < intArray.Length; i++) {


line += ", " + intArray[i].ToString();
}

return line;
}
}

//JS script example


function ConcatExample(intArray: int[]) {
var line = intArray[0].ToString();

for (i = 1; i < intArray.Length; i++) {

line += ", " + intArray[i].ToString();


}

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:-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {

public GUIText scoreBoard;


public int score;

void Update() {
string scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;
}
}

//JS script example


var scoreBoard: GUIText;
var score: int;

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:-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


public GUIText scoreBoard;
public string scoreText;
public int score;
public int oldScore;

void Update() {
if (score != oldScore) {
scoreText = "Score: " + score.ToString();
scoreBoard.text = scoreText;

oldScore = score;
}
}
}

//JS script example


var scoreBoard: GUIText;
var scoreText: String;
var score: int;
var oldScore: int;

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:-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


void RandomList(int numElements) {
var result = new float[numElements];

for (int i = 0; i < numElements; i++) {


result[i] = Random.value;
}

return result;
}

//JS script example


function RandomList(numElements: int) {
var result = new float[numElements];

for (i = 0; i < numElements; i++) {


result[i] = Random.value;
}

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:-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


void RandomList(float[] arrayToFill) {
for (int i = 0; i < arrayToFill.Length; i++) {
arrayToFill[i] = Random.value;
}
}
}

//JS script example


function RandomList(arrayToFill: float[]) {
for (i = 0; i < arrayToFill.Length; i++) {
arrayToFill[i] = Random.value;

}
}

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.

Solicitar una Recoleccin


Como fue mencionado arriba, es mejor evitar asignaciones tanto como sea posible. Sin
embargo, dado que no pueden ser completamente eliminadas, hay dos estrategias
principales que puedes usar para minimizar su intrusin en la jugabilidad:-

Mantener la pila pequea con recolecciones frecuentes


Esta estrategia es usualmente mejor para juegos que tengan periodos largos de juego en
donde la velocidad de cuadros sea la preocupacin principal. Un juego de este tipo
tpicamente asigna bloques pequeos con frecuencia, pero estos bloques slo estarn en
uso brevemente. El tamao tpico de la pila al usar esta estrategia en iOS es alrededor de
los 200KB y la recoleccin de basura tomar unos 5ms en un iPhone 3G. Si la pila se
incrementa a 1MB, la recoleccin tomar unos 7ms. Por tanto, puede ser ventajoso en
ocasiones solicitar una recoleccin de basura a un intervalo de frames regular. Esto por lo
general hace que las recolecciones ocurran ms frecuente de lo que estrictamente
necesario, pero sern procesadas ms rpido y con un efecto mnimo sobre la jugabilidad:-

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.

Dejar grande la pila con recolecciones lentas y poco


frecuentes
Esta estrategia funciona mejor en juegos donde las asignaciones (y por tanto, las
recolecciones) sean relativamente poco frecuentes y puedan ser manejadas cuando hayan
pausas en el ritmo del juego. Es til que la pila sea tan grande como sea posible, pero sin
llegarlo a ser demasiado como para que tu app sea cancelada por el sistema operativo
debido a que est agotando la memoria del sistema. Sin embargo, el sistema en tiempo de
ejecucin de Mono evita en lo posible que el tamao de la pila se expanda. Puedes
expandir la pila en forma manual, pre-asignando un espacio de reserva durante el
arranque (es decir, puedes instanciar un objeto intil que es asignado meramente para
efectos del gestor de memoria):-

//C# script example


using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {


void Start() {
var tmp = new System.Object[1024];

// make allocations in smaller blocks to avoid them


to be treated in a special way, which is designed for large
blocks
for (int i = 0; i < 1024; i++)
tmp[i] = new byte[1024];

// release reference
tmp = null;
}
}

//JS script example


function Start() {
var tmp = new System.Object[1024];

// make allocations in smaller blocks to avoid them to be


treated in a special way, which is designed for large blocks
for (var i : int = 0; i < 1024; i++)
tmp[i] = new byte[1024];

// 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.

Pools de Objetos Reutilizables


Hay muchos casos donde puedes evitar la produccin de basura con slo reducir el
nmero de objetos que son creados y destruidos. Hay ciertos tipos de objetos en los
juegos, tales como proyectiles, que pueden ser encontrados una y otra vez aunque slo un
pequeo nmero estar siempre en el juego en ese instante. En casos como este, a
menudo es posible reutilizar los objetos en vez de destruir los viejos y reemplazarlos con
nuevos.

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.

Compilacin Dependiente a la Plataforma


Unity incluye una caracterstica llamada Platform Dependent Compilation. Esto consiste
de algunas directivas de pre-procesamiento que le permite a usted particin de sus script
para ser compiladas y ejecutar una seccin de cdigo exclusivo para una de las
plataformas soportadas.
Adicionalmente, usted puede correr este cdigo dentro del Editor, para que usted puede
compilar cdigo especifico para su consola/mobil y lo pruebe en el Editor!

Defines de plataforma
Los defines de plataforma que soportes Unity para sus scripts son:

Propiedad:

Funcin:

UNITY_EDITOR

Define para llamar scripts del Editor de Unity desde su


cdigo de juego.

UNITY_EDITOR_WIN

Define de Plataforma para cdigo de editor en Windows

UNITY_EDITOR_OSX

Define de Plataforma para cdigo de editor en Mac OSX.

UNITY_STANDALONE_O

Define de Plataforma para la compilacin/ejecucin de

SX

cdigo especficamente para Mac OS (esto incluye


arquitecturas Universal, PPC e Intel).

UNITY_STANDALONE_

Utilice esto cuando usted quiere compilar/ejecutar cdigo

WIN

para aplicaciones stand alone de Windows.

UNITY_STANDALONE_LI

Utilice esto cuando usted quiere compilar/ejecutar cdigo

NUX

para aplicaciones stand alone Linux.

UNITY_STANDALONE

Utilice esto para compilar/ejecutar cdigo para cualquier


plataforma standalone (Mac, Windows, o Linux).

UNITY_WEBPLAYER

Define de Plataforma para el contenido del reproductor


web (esto incluye ejecutables de Reproductores Web de
Windows y Mac).

UNITY_WII

Define de Plataforma para la compilacin/ejecucin de


cdigo para la consola Wii.

UNITY_IOS

Define de Plataforma para la compilacin/ejecucin de


cdigo para la plataforma iOS.

UNITY_IPHONE

Deprecado. Utilice UNITY_IOS ms bien.

Propiedad:

Funcin:

UNITY_ANDROID

Define de Plataforma para la plataforma Android

UNITY_PS3

Define de Plataforma para correr cdigo de Playstation 3.

UNITY_PS4

Define de Plataforma para correr cdigo de Playstation 4.

UNITY_XBOX360

Define de Plataforma para la ejecucin de cdigo de Xbox


360.

UNITY_XBOXONE

Define de Plataforma para la ejecucin de cdigo de Xbox


One.

UNITY_BLACKBERRY

Define de Plataforma para el dispositivo Blackberry10.

UNITY_TIZEN

Define de Plataforma para la plataforma Tizen.

UNITY_WP8

Define de Plataforma para Windows Phone 8.

UNITY_WP8_1

Define de Plataforma para Windows Phone 8.1.

UNITY_WSA

Define de Plataforma para Apps de la Windows Store


(adicionalmente NETFX_CORE est definida cuando
compile archivos C# contra .NET Core).

UNITY_WSA_8_0

Define de Plataforma para Apps de la Windows Store


cuando se apunte al SDK 8.0.

UNITY_WSA_8_1

Define de Plataforma para Apps de la Windows Store


cuando se apunte a SDK 8.1.

UNITY_WSA_10_0

Define de Plataforma para Apps de la Windows Store


(adicionalmente NETFX_CORE est definida cuando
compile archivos C# contra .NET Core).

Propiedad:

Funcin:

UNITY_WINRT

Equivalente a UNITY_WP8 | UNITY_WSA.

UNITY_WINRT_8_0

Equivalente a UNITY_WP8 | UNITY_WSA_8_0.

UNITY_WINRT_8_1

Equivalente a UNITY_WP_8_1 | UNITY_WSA_8_1.


Tambin est definida cuando se compile contra Universal
SDK 8.1.

UNITY_WINRT_10_0

Igual que UNITY_WSA_10_0

UNITY_WEBGL

Define de Plataforma para WebGL.

UNITY_ANALYTICS

Define para llamar mtodos de Unity Analytics desde su


cdigo de juego. Versiones 5.2 y posteriores.

Tambin usted puede compilar cdigo selectivamente dependiendo en la versin de de su


motor en la cual est trabajando. Actualmente las soportadas son:

UNITY_2_6

Define de Plataforma para la versin mayor de Unity2.6.

UNITY_2_6_1

Define de Plataforma para la versin especfica 2.6.1.

UNITY_3_0

Define de Plataforma para la versin mayor de Unity 3.0.

UNITY_3_0_0

Define de Plataforma para la versin especfica 3.0.0.

UNITY_3_1

Define de Plataforma para la versin mayor de Unity 3.1.

UNITY_3_2

Define de Plataforma para la versin mayor de Unity 3.2.

UNITY_3_3

Define de Plataforma para versin mayor de Unity 3.3.

UNITY_3_4

Define de Plataforma para la versin mayor de Unity 3.4.

UNITY_3_5

Define de Plataforma para la versin mayor de Unity 3.5.

UNITY_4_0

Define de Plataforma para la versin mayor de Unity 4.0.

UNITY_4_0_1

Define de Plataforma para la versin especifica 4.0.1.

UNITY_4_1

Define de Plataforma para la versin mayor de Unity 4.1.

UNITY_4_2

Define de Plataforma para la versin mayor de Unity 4.2.

UNITY_4_3

Define de Plataforma para la versin mayor de Unity 4.3.

UNITY_4_5

Define de Plataforma para la versin mayor de Unity 4.5.

UNITY_4_6

Define de Plataforma para la versin mayor de Unity 4.6.

UNITY_5_0

Define de Plataforma para la versin mayor de 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.

Probando cdigo pre-compilado


Nosotros vamos a mostrar un pequeo ejemplo de cmo utilizar el cdigo pre-compilado.
ste simplemente va a imprimir un mensaje que depende en la plataforma que usted tiene
seleccionada para construir su objetivo.

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;

public class PlatformDefines : MonoBehaviour {


void Start () {

#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

}
}

Luego, dependiendo en qu plataforma usted haya seleccionado, uno de los mensajes


ser impreso en la consola de Unity cuando usted presione reproducir.
Tenga en cuenta que en C# usted puede utilizar un atributo CONDITIONAL que es ms
limpio, menos propenso a errores de despojar funciones,
vea http://msdn.microsoft.com/en-us/library/4xssyw96(v=vs.90).aspx.
En adicin a la directiva del compilador bsica #if , usted puede tambin utilizar una
prueba de multiples vas en C# y JavaScript:-

#if UNITY_EDITOR
Debug.Log("Unity Editor");

#elif UNITY_IPHONE
Debug.Log("Unity iPhone");

#else
Debug.Log("Any other platform");

#endif

Defines de Plataforma Personalizados


Tambin es posible agregar a la seleccin integrada de definiciones al proporcionar el de
uno. En el panel Other Settings delPlayer Settings, usted va a ver la caja de texto
Scripting Define Symbols.

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.

Defines Personalizados Globales


Usted puede definir sus propias directivas del pre-procesador para controlar que cdigo es
incluido cuando es compilado. Para hacer esto, usted debe agregar un archivo texto con
una directiva extra a la carpeta Assets/. El nombre del archivo depende en el lenguaje
que usted est utilizando, y la extensin es .rsp:

C#

<Project Path>/Assets/smcs.rsp

C# - Scripts del Editor

<Project Path>/Assets/gmcs.rsp

UnityScript

<Project Path>/Assets/us.rsp

Como un ejemplo, si usted incluye la linea sola -define:UNITY_DEBUG en su


archivo smcs.rsp el define UNITY_DEBUG va a existir como una global define para scripts
C#, excepto para scripts del Editor.
Cada vez que usted hace cambios a sus archivos .rsp usted va a necesitar re-compilarlos
para ser efectivo. Usted puede hacer esto al actualizar o re-importar un solo archivo script
(.js o .cs).
Si usted quiere modificar solo global defines, usted debera utilizar Scripting Define
Symbols en Los Ajustes del Reproductor, debido a que esto va a cubrir todos los
compiladores. Si usted escoge los archivos .rsp ms bien, usted tendr que proporcionar
un archivo para cada compilador que Unity utiliza, y usted no sabr cundo uno o otro
compilador es utilizado.
El uso de archivos .rsp es descrito en la seccin de ayuda (help= de la
aplicacin smcs que es incluida en la carpeta de instalacin del Editor. Usted puede
obtener ms informacin al correr smcs -help. Tambin, tenga en cuenta que el archivo
.rsp necesita coincidir el compilador siendo invocado. Por ejemplo, cuando tenga como
objetivo el reproductor web, smcs es utilizado con smcs.rsp; cuando tenga como objetivo
reproductores standalone, gmcs es utilizado con gmcs.rsp; cuando tenga como objetivo un
compilador MS, csc es utilizado con csc.rsp; y as.

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):-

// The type is correctly inferred since it is defined in the


function call.
//In C#
var obj = GetComponent<Rigidbody>();
//In JS
var obj = GetComponent.<Rigidbody>();

En C#, esto puede guardar muchas pulsaciones de teclado y casts :

Rigidbody rb = go.GetComponent<Rigidbody>();

// ...as compared with:

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:

Ventana del Inspector. La ventana del inspector no le habla al API de C# para


averiguar qu valores de las propiedades de lo que se est viendo. Le pregunta al objeto a
serializarse en s mismo, y mostrar la informacin serializada.

Prefab. Internamente, un prefab es el flujo de datos serializado ( serialized data


stream) de uno (o ms) game objects y componentes. Una instancia de prefab es una lista
de modificaciones que deberan ser hechas en la informacin serializada de esta instancia.
El prefab concepto solo existe en el tiempo del editor. Las modificaciones del prefab son
baked a un flujo de serializacin (serialization stream) normal cuando Unity hace una
construccin, y cuando eso es instanciando, los game objects instanciados no tienen idea
de que eran un prefab cuando estaban en el editor.

Instanciacin. Cuando usted llama Instantiate() ya sea en un prefab, o un


gameobject que est vivo en la escena, o cualquier otra cosa (cualquier cosa que derive
de UnityEngine.Object puede ser serializado), nosotros serializamos el objeto, luego
creamos un nuevo objeto, y luego deserializamos la informacin al nuevo objeto.
(Nosotros luego corremos el mismo cdigo de serializacin en una diferente variante,
dnde nosotros lo utilizamos para reportar qu otrosUnityEngine.Objects estn
siendo referenciados. Luego revisamos para todos
los UnityEngine.Objects referenciados, si son parte de la informacin
siendo Instantiated(). Si la referencia est apuntando a algo externo (como una
textura) nosotros mantenemos esa referencia como est, si est apuntando a algo

interno (como un hijo gameobject), nosotros conectamos la referencia a la copia


correspondiente).

Guardando. Si usted abre un archivo de escena .unity con un editor de texto, y


tiene configurado Unity a force text serialization, nosotros corremos el serializador con un
yaml backend.

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.

Resource.GarbageCollectSharedAssets(). Este es nuestro nativo


recolector de basura (garbage collector). Es una cosa diferente que el recolector de C#. Es
la cosa que corremos despus de que cargue una escena, para encontrar qu cosas de la
escena anterior no son referenciadas, para que las podamos descargar. El recolector de
basura nativo corre el serializador en una variacin dnde nosotros lo utilizamos para que
los objetos reporten todas las referencias aUnityEngine.Objects externos. Esto es lo
que hace que las texturas que fueron utilizadas por la escena1, sean descargadas cuando
usted cargue la escena2.
El sistema de serializacin est escrito en C++. Nosotros lo utilizamos para todos nuestros
tipos de objetos internos. (Texturas, Clip de Animacin (AnimationClip), Cmara, etc). La
serializacin ocurre en el nivel de UnityEngine.Object.
CadaUnityEngine.Object es siempre serializado como un entero. Estos pueden
contener referencias a otrosUnityEngine.Objects, y esas referencias son serializadas
de manera adecuada.
Ahora usted dice que ninguno de esto lo afecta a usted, y que est feliz que funcione y
quiere seguir a crear algo de contenido.
Dnde le va a importar usted es que nosotros utilizamos este mismo serializador para
serializar componentesMonoBehaviour, que son respaldados por sus scripts. Debido a
los altos requerimientos de rendimiento que el serializador tiene, ste en todos los casos
no se comporta como un desarrollador en C# se esperara que un serializador funcionara.
En esta parte de los docs, nosotros describiremos cmo el serializador funciona, y algunas
de las mejores prcticas de cmo sacarle el mejor uso.

Qu es lo que tiene que tener un capo de mi script para ser


serializado?

ser public, o tener un atributo [SerializeField]

no ser static

no ser const

no ser readonly

el fieldtype necesita ser de un tipo el cual podemos serializar.


Qu fieldtypes podemos serializar?

clases no abstractas personalizadas con el atributo [Serializable].

structs personalizados con el atributo [Serializable]. (Agregado en Unity 4.5)

Referencias a los objetos que derivan del UnityEngine.Object

Tipos primitivos de datos (int, float, double, bool, string, etc.)

arreglo de un fieldtype el cual podemos serializar

List<T> de un fieldtype el cual podemos serializar

Cules son estas situaciones dnde el serializado se comporta


diferente de lo que yo esperaba?
Clases personalizadas se comportan como structs

[Serializable]
class Animal
{
public string name;
}

class MyScript : MonoBehaviour


{
public Animal[] animals;
}

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,

No hay soporte para clases personalizadas null


Quiz Sorpresa: Cuntas alocaciones son hechas cuando se deserializa un MonoBehaviour
que utiliza este script:

class Test : MonoBehaviour


{
public Trouble t;
}

[Serializable]
class Trouble
{
public Trouble t1;

public Trouble t2;


public Trouble t3;
}

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.

No hay soporte para polimorfismos


si usted tiene un public Animal[] animals y lo coloca en una instancia de un perro, o
gato y una jirafa, despus de la serializacin, usted tendr tres instancias de Animal.
Una manera de manejar esta limitacin es darse cuenta que solo aplica a clases
personalizadas, las cuales son serializadas en linea. Referencias a
otros UnityEngine.Objects son serializados como referencias actuales, y para estos
los polimorfismos de verdad funciona. Usted hace un ScriptableObject derivado de
una clase o otro MonoBehaviour derivado de una clase, y referencia esto. La desventaja
de esto es que usted necesita almacenar ese objeto monobehaviour o scriptable en alguna
parte, y no puede serializar en linea de manera optima.
La razn para estas limitaciones es que una de las bases fundamentales del sistema de
serializacin es que el diseo del flujo de informacin (datastream) para un objeto es
conocido antes de tiempo, y depende en los tipos de los campos de la clase, en vez de lo
que pasa a ser almacenado dentro de los campos.

Yo quiero serializar algo que el serializador de Unity no soporta. Qu hago?


En la mayora de casos el mejor acercamiento es utilizar callbacks de serializacin. Estas
le permiten a usted ser notificado antes de que el serializador lea informacin de los capos
y despus que es hecho, escribir en ellos. Usted puede utilizar esto para tener diferentes
representaciones de su data difcil de serializar en el tiempo de ejecucin cuando usted de
verdad serializa. Usted utiliza estas para transformar sus datos a algo que Unity entienda
justo antes de que Unity quiera serializarlo, y usted lo utilice para transformar la forma del
serializado a la forma que usted quiere tener sus datos en el tiempo de ejecucin justo
despus de que Unity ha escrito datos a sus campos.
Digamos que usted quiere tener una estructura de datos rbol. Si usted le permite a Unity
directamente serializar la estructura de datos, la limitacin de no support for null (No hay
soporte para null) va a causar que su flujo de datos (datastream) se vuelva muy grande,
llevando a una degradacin de rendimiento en muchos sistemas:

using UnityEngine;
using System.Collections.Generic;
using System;

public class VerySlowBehaviourDoNotDoThis : MonoBehaviour


{
[Serializable]
public class Node
{
public string interestingValue = "value";

//The field below is what makes the serialization


data become huge because
//it introduces a 'class cycle'.
public List<Node> children = new List<Node>();
}

//this gets serialized


public Node root = new Node();

void OnGUI()
{
Display (root);
}

void Display(Node node)


{
GUILayout.Label ("Value: ");

node.interestingValue =
GUILayout.TextField(node.interestingValue,
GUILayout.Width(200));

GUILayout.BeginHorizontal ();
GUILayout.Space (20);
GUILayout.BeginVertical ();

foreach (var child in node.children)


Display (child);
if (GUILayout.Button ("Add child"))
node.children.Add (new Node ());

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;

public class BehaviourWithTree : MonoBehaviour,


ISerializationCallbackReceiver
{
//node class that is used at runtime
public class Node
{
public string interestingValue = "value";
public List<Node> children = new List<Node>();
}

//node class that we will use for serialization


[Serializable]
public struct SerializableNode
{

public string interestingValue;


public int childCount;
public int indexOfFirstChild;
}

//the root of what we use at runtime. not serialized.


Node root = new Node();

//the field we give unity to serialize.


public List<SerializableNode> serializedNodes;

public void OnBeforeSerialize()


{
//unity is about to read the serializedNodes field's
contents. lets make sure
//we write out the correct data into that field "just
in time".
serializedNodes.Clear();
AddNodeToSerializedNodes(root);

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);
}

public void OnAfterDeserialize()


{
//Unity has just written new data into the
serializedNodes field.

//let's populate our actual runtime data with those


new values.

if (serializedNodes.Count > 0)
root = ReadNodeFromSerializedNodes (0);
else
root = new Node ();
}

Node ReadNodeFromSerializedNodes(int index)


{
var serializedNode = serializedNodes [index];
var children = new List<Node> ();
for(int i=0; i!= serializedNode.childCount; i++)

children.Add(ReadNodeFromSerializedNodes(serializedNode.index
OfFirstChild + i));

return new Node() {

interestingValue =
serializedNode.interestingValue,
children = children
};
}

void OnGUI()
{
Display (root);
}

void Display(Node node)


{
GUILayout.Label ("Value: ");
node.interestingValue =
GUILayout.TextField(node.interestingValue,
GUILayout.Width(200));

GUILayout.BeginHorizontal ();

GUILayout.Space (20);
GUILayout.BeginVertical ();

foreach (var child in node.children)


Display (child);
if (GUILayout.Button ("Add child"))
node.children.Add (new Node ());

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.

UnityEvents (Eventos de Unity)


Los UnityEvents son maneras de permitirle a los callbacks hechos por el usuario a ser
persistidos desde un tiempo de edicin a un tiempo de ejecucin sin la necesidad de
programacin adicional y configuracin de script.
Los UnityEvents son tiles para un nmero de cosas:

Callbacks guiados por Contenido (Content Driven Callbacks)

Sistemas de desacoplamiento

Callbacks persistentes

Eventos de llamada Preconfigurados


Los UnityEvents pueden ser agregados a cualquier MonoBehaviour y son ejecutados
desde cdigo como un .net delegado estndar. Cuando UnityEvent es agregado a
un MonoBehaviour ste aparece en el Inspector y callbacks persistentes pueden ser
agregados.
UnityEvents have similar limitations to standard delegates. That is, they hold references
to the element that is the target and this stops the target being garbage collected. If you
have a UnityEngine.Object as the target and the native representation disappears the
callback will not be invoked.

Utilizando UnityEvents
Para configurar un callback en el editor hay varios pasos para realizar:
1.

Asegrese de que su script importe/utilice UnityEngine.Events.

2.

Seleccione el cono + para agregar una casilla para su callback.

3.

Seleccione el UnityEngine.Object que usted desea recibir el callback (Usted puede


utilizar el selector del objeto para esto)

4.

Seleccione la funcin que usted desea que sea llamada

5.

Usted puede agregar ms de un callback para el evento


Cuando configure un UnityEvent en el Inspector hay dos tipos de llamadas a funciones
que son soportadas:

Estticas. Llamadas estticos son llamadas pre-configuradas, con valores preconfigurados que son configurados en el UI. Esto significa que cuando el callback sea

invocado, la funcin objeto es invocada con el argumento que ha ingresado en el UI.


Dinmico. Llamadas dinmicas son invocadas utilizando un argumento que es
enviado desde cdigo, y este est unido al tipo de UnityEvent que est siendo invocado. El
UI filtra los callbacks y solo muestra las llamadas dinmicas que son vlidas para el
UnityEvent.

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]

public class StringEvent : UnityEvent <string> {}

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.

Qu es una Null Reference Exception? (Excepcin con Referencia Null)


Una NullReferenceException sucede cuando usted intenta acceder una variable de
referencia que no est referenciando ningn objeto. Si una variable de referencia no est
referenciando un objeto, entonces ser tratada como null. El tiempo de ejecucin le va a
decir a usted que usted est intentando acceder un objeto, cuando la variable es null al
emitir unaNullReferenceException.
Variables referenciadas en C# y JavaScript son similares en concepto a apuntadores en C
y C++. Los tipos de referencia por defecto son null para indicar que no estn
referenciando a ningn objeto. Por lo tanto, si usted intenta y accede a un objeto que est
referenciado y no hay un objeto, usted obtendr una NullReferenceException.
Cuando usted obtiene una NullReferenceException en su cdigo significa que usted
ha olvido configurar una variable antes de utilizarla. El mensaje de error se ver algo as:

NullReferenceException: Object reference not set to an


instance of an object
at Example.Start () [0x0000b] in
/Unity/projects/nre/Assets/Example.cs:10

Este mensaje de error dice que una NullReferenceException sucede en la linea 10


del archivo script Example.cs. Tambin, el mensaje dice que la excepcin sucede dentro
de la funcin Start(). Esto hace que la Null Reference Exception fcil de encontrar y
arreglar. En este ejemplo, el cdigo es:

//c# example
using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

// Use this for initialization


void Start () {
GameObject go = GameObject.Find("wibble");
Debug.Log(go.name);
}

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;

public class Example : MonoBehaviour {

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;

public class Example2 : MonoBehaviour {

public Light myLight; // set in the inspector

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

NullReferenceException sucede cuando su cdigo script intenta utilizar una

variable que no est configurada (referenciada) y object.


El mensaje de error que aparece le dice a usted mucho acerca dnde en el cdigo

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

La clase base para todos los nuevos Unity scripts, la


referencia MonoBehaviour le proporciona a usted una lista de
todas las funciones y eventos que son disponibles para
scripts estndar adjuntos a Game Objects. Comience aqu si
usted est buscando por cualquier interaccin o control sobre
objetos individuales en su juego.

Transform

Cada Game Object tiene una posicin, rotacin y escala en


espacio (ya sea 3D o 2D), y esto es representando por el
componente Transform. Al igual que proporcionar esta
informacin, el componente transform tiene muchas
funciones tiles que pueden ser utilizadas para mover,
escalar, girar, re-apadrinar y manipular objetos, al igual que
convertir coordenadas desde un espacio a otro.

Rigidbody /Rigidbody2

Para la mayora de elementos del gameplay, el motor de

fsica proporciona el conjunto de herramientas ms fcil para


mover objetos alrededor, detectando triggers y colisiones, y
aplicando fuerzas. La clase Rigidbody (o su equivalente en
2D, Rigidbody2D) proporciona todas las propiedades y
funciones que usted va a necesitar para jugar con la
velocidad, masa, friccin, fuerza, torque, colisin y ms.

Potrebbero piacerti anche