Você está na página 1de 237

0.

PRELIMINARES Y ALGUNOS PRESUPUESTOS

Bienvenid@s a unityscript. Antes de entrar en materia y para que nadie se lleve a engao, considero honesto advertir a los hipotticos lectores de que el autor de estas lneas no es programador profesional, ni ha creado ninguno de los cien videojuegos ms vendidos de la historia. e hecho, si he de ser totalmente sincero, hace menos de tres aos este que os est escri!iendo no ha!a escrito ni una sola lnea de c"digo. #uede parecer por lo tanto un atrevimiento $y de hecho lo es$ que un tipo como yo, un autodidacta sin ninguna !ase acadmica, se atreva a inaugurar un !log de estas carcteristicas, y comprender perfectamente que alguien con conocimientos profundos so!re programaci"n en general o %nity en particular salga corriendo de este site. &econo'co ya de antemano, por lo e(puesto, que muy pro!a!lemente algunas de las cosas que os vaya e(plicando en las lecciones que vendrn a continuaci"n puedan contener errores, y pido disculpas anticipadas por ello. )uelga decir que agradecer cualquier correcci"n por parte de personas con ms conocimientos. *e gustara e(plicaros !revemente las ra'ones por las cuales me he decidido a crear este !log, las ra'ones por las que creo que este !log es necesario+ ,o aterric en el universo %nity hace unos cuatro meses. *s o menos como todos, me di una vuelta por la interfa' grfica, estuve pelendome con las cmaras, encend las luces y puse nie!la a la escena, traste con el terrain hasta crear algo parecido a una isla, import algunos modelos de Blender -todava ando !uscando las te(turas de esos modelos. y cosas parecidas. /uego empec a leerme todos los li!ros que pill so!re %nity, que no es que sean demasiados. , cuando me los hu!e ledo todos, ya domina!a ms o menos decentemente la interfa' del engine, pero segua sin tener ni idea so!re la A#0 de %nity. 1n los li!ros que en la actualidad hay so!re la materia la parte relativa a los scripts $que en el fondo es la ms importante$ se deja en un segundo trmino. 2e incluyen, un poco a !oleo, varios scripts, pero de una manera totalmente desordenada y sin ning3n inters pedag"gico, pareciera que ms para impresionar al respeta!le o para copiar y pegar en otros proyectos sin sa!er a ciencia cierta qu se est haciendo, que para realmente e(plicar de d"nde sale cada cosa, cules son las clases principales, su cometido y relaci"n de herencia entre ellas, qu demonios en un cuaterni"n, etc. /a 3nica va para hacerse con la A#0 de %nity pasa!a pues por ir al manual de referencia de la propia pgina 4e! del engine, la cual presenta un triple inconveniente+ 5.1st en ingls. 6.1st escrito ms como manual de consulta que como instrumento de aprendi'aje. 7.2igue un orden alfa!tico, no un orden l"gico. 1l primer inconveniente no lo fue tanto, ya que hace cuatro aos -uno antes de empe'ar a aprender informtica. segu al pie de la letra el consejo de un amigo+ $ 2i quieres aprender a programar, antes aprende ingls. , como este que os ha!la suple su falta de talento con una !uena dosis de ca!e'onera, a estudiar ingls que me puse. e esta manera y gracias al consejo de mi amigo $que ruego os apliquis los que no os llevis !ien con la lengua de 2ha8espeare$ durante estas 3ltimas semanas he traducido la casi totalidad de las clases, estructuras y enumeraciones de %nity al castellano. 9o es que sea una traducci"n muy pulida, aviso desde ya, pero para nuestros fines !astar. e los otros dos inconvenientes nos tendremos que ir ocupando poco a poco, por el viejo procedimiento de prue!a y error y usando el sentido com3n y la constancia donde el resto falle. :engo el firme prop"sito de ir haciendo vuestros los avances que a su ver yo vaya haciendo en mi propio aprendi'aje, y aunque ello entrae ir a un ritmo lento y en ocasiones nos implique tener que retroceder para revisitar alg3n concepto, tam!in creo que puede ser interesante para alquien que empie'a en esto escuchar las e(plicaciones y;u opiniones de otro que recin est aprendiendo tam!in y que $al contrario que algunos autores con ms conocimientos$ no da nada por supuesto. As que no esperis scripts de cuatro pginas -no al menos el primer ao., con todo lo !ueno y lo malo que eso pueda conllevar. ,, por supuesto, sera muy positivo que hu!iera la suficiente retroalimentaci"n con todo aqul que est interesado en hacer com3n el camino de aprendi'aje. 1so s, para no tener que hacer una parada conjunta antes de dar siquiera el primer paso, esto es, para poder seguir este <curso< -por llamarlo de alguna manera. presupongo que quien lea esto tiene una serie de conocimientos de !ase ya adquiridos, a sa!er+ 5. Algo de programaci"n en general, y de =avascript en particular. ->aria!les, funciones, !ucles, condicionales, etc..

6. ?onocimientos rudimentarios de #@@ -#rogramaci"n @rientada a @!jetos. 7. )a!erle dado unas cuantas vueltas a la interfa' de %nity y estar familiari'ado con su terminologa -gameo!jects, assets, y esas cosas. 2i no tenis esos conocimientos previos, ni podris seguir las e(plicaciones ni podris hacer juego alguno -desde ya les aseguro a los amigos de los atajos que no e(iste un soft4are mgico que o!edeciendo a tus impulsos cere!rales te construya de la nada un juego online multijugador listo para ser distri!uido.. , sin ms prem!ulos, creo que podemos dar la introducci"n por aca!ada y meternos en materia.

1. ALGUNAS PECULIARIDADES DE UNITY


Antes de adentrarnos en la A#0 de %nity, conviene sa!er que el engine admite tres lenguajes de programaci"n para sus scripts+ ?A, Boo -una variante de #ython. y algo muy parecido a =avascript, que es lo que vamos a usar nosotros en este curso. =avascript es de los tres lenguajes indicados el ms sencillo, y si !ien algunos programadores con un cierto nivel aseguran que ?A les ofrece ms control, para nuestros fines y nivel con =avascript vamos ms que so!rados. %na de las cosas que choca de entrada en %nity para los que tuvieran un conocimiento previo de =avascript es la forma de declarar las varia!les. A diferencia del =avascript standard, en %nity hemos de declarar el tipo de la varia!le, un poco a la antigua usan'a de ? y ?BB. #or ejemplo, para declarar la varia!le numero de tipo int hariamos+ var numero + intC numero D 5EC , si la quisiramos iniciali'ar en la declaraci"n, sera+ var numero + int D 5EC 1sto es, pala!ra reservada <var< para indicar que vamos a declarar una nueva varia!le, el nom!re que le demos a sta seguido de dos puntos y el tipo de la varia!le declarada.

1n otro orden de cosas, hemos de decir que la A#0 de %nity est orientada a o!jetos y se compone de algo ms de un centenar de clases, de las cuales una tercera parte ms o menos estn relacionadas entre s en trminos de herencia y el resto o son conjuntos de funciones au(iliares -clase tiempo, de funciones matematicas, etc. o !ien meramente permiten funcionalidades especiales no contempladas en lo que podramos llamar las clases troncales -clases relativas a la F%0 o para conectarse a un servidor, por ejemplo. 1ntendiendo que las clases que estn vinculadas entre s son a su ve' las que nos pueden dar una idea ms precisa del mecanismo de funcionamiento de %nity, son con vuestro permiso $y con alguna e(cepci"n que iremos haciendo$ por las que me gustara empe'ar. , ya que $salvo error$ nadie se ha tomado la molestia de hacer un esquema del sistema de herencia de estas clases, me tom la li!ertad de hacerlo yo. 1st incompleto, ya que una veintena de clases de las que estuve mirando cuando esta!a llevando a ca!o la traducci"n no me parecieron demasiado importantes, o por lo menos no a estas alturas, pero en esencia este sera el ar!olito de clases con que nos va a tocar lidiar durante una !uena temporada.

#ara agrandar la imagen pulsa AG%H &ecomiendo imprimir este esquema, ya que lo vamos a usar de referencia para, por ejemplo, sa!er qu funciones hereda una determinada clase, o qu clase tiene un atri!uto que es una instancia de otra clase. #or e(periencia $poca, pero e(periencia al ca!o$ os digo que o tenis una referencia a mano o todo os aca!ar sonando igual y al final os quedaris sin el que de!iera ser vuestro o!jetivo, que no es aprenderse todas las funciones de memoria, sino entender por qu la A#0 de %nity est estructurada de una manera y no de otra. ?omo podris o!servar, he incluido en el esquema las varia!les, funciones y funciones de clase -o atri!utos y mtodos,

si prefers la terminologa de la #@@. de la clase !ase -@!ject., la principal de las que derivan de aqulla -?omponent. y la que a su ve' hereda de sta y es heredada por otro n3mero de clases. 1sto nos permite, como deca antes, seguir la pista a las varia!les y funciones heredadas por $pongamos un ejemplo$ la clase ?amera, que hereda de Behaviour y por tanto tam!in de ?omponent y por 3ltimo de @!ject. As, podemos presuponer que esto es vlido+ var camara e2eguridad + ?ameraC camara e2eguridad.name D <*i camara<C 1sto es, nuestro o!jeto camera de!era ha!er heredado una varia!le name de la clase @!ject. :eniendo a mano el esquema nos podemos evitar andar re!uscando por el manual de referencia. , con esto finali'amos esta lecci"n. #ara la pr"(ima nos tocar ya a!rir %nity.

2. DONDE VAN LOS SCRIPTS?


Bueno, tras un par de captulos con los proleg"menos, creo que ya podemos entrar en materia, para lo cual vamos a a!rir %nity. 9ota+ 1n principio, y salvo que diga lo contrario, todas las caractersticas y scripts que vamos a utili'ar sirven para la versi"n free como para la #&@, as que me da igual la versi"n que tengis. >amos a crear un proyecto nuevo, que podis llamar como os d la gana y guardar donde queris, que para eso e ordenador es vuestro. 9o vamos a importar de momento ning3n asset, as que dejamos desmarcadas todas las casillas y creamos el proyecto. /o 3nico que nos aparecer en la interfa', por tanto, ser la cmara principal. /a marcamos y en el inspector, la colocamos en las siguientes coordenadas+ IDE, ,D5, J D$K. Ahora vamos a introducir un cu!o en la escena. 9os vamos al men3 superior, Fameo!ject DL ?reate other DL ?u!e. Al cu!o primero lo vamos a castellani'ar, y en consecuencia le llamaremos ?u!o. /e podemos cam!iar el nom!re en el inspector, o !ien pulsando M6 en la jerarqua con ?u!e seleccionado. >amos a u!icar nuestro cu!o en las coordenadas E,E,E. >amos a salvar la escena. Mile DL2ave 2cene. #ara no liarnos, recomiendo que le pongis el mismo nom!re que yo, esto es, 1jemploN5. 2i todo ha ido !ien, de!is tener algo parecido a esto+

Ahora, en la vista #roject, en un espacio li!re de!ajo de donde est la escena guardada, hacemos clic8 derecho con el rat"n, y en el men3 emergente seleccionamos ?reate DL Molder. A la carpeta que aparecer le llamaremos *is scripts. ?on el puntero del rat"n so!re dicha carpeta vamos a hacer de nuevo clic8 derecho, y esta ve' seleccionamos ?reateDL=avascript. 9os aparecer un icono representando al nuevo script con el nom!re por defecto <9e4Behaviour2cript<. /o renom!ramos, llamndolo *i#rimer2cript, y le damos a return para que nos conserve el cam!io.

?omo podemos o!servar, en el inspector al seleccionar nuestro script aparece una funci"n por defecto, la cual nos ser 3til en un !uen n3mero de casos. 2era lo que se conoce como una funci"n so!reescri!i!le, que quiere decir que %nity decide cundo se va a llamar -la funci"n %pdate, que es la que sale por defecto, es llamada por %nity cada frame. y nosotros decidimos qu har cuando sea llamada, introduciendo c"digo en su interior. #ara poder editar y;o crear nuestros scripts, hemos de acceder al editor que viene con %nity, y la mejor manera para hacerlo es hacer do!le clic8 so!re el nom!re de nuestro script. 2e nos a!rir -en 4indo4s. esto+

>amos a aprovechar que tenemos el editor a!ierto para e(plicar otra caracterstica de los scripts en %nity. %nity permite asignar;modificar los valores a las varia!les glo!ales desde la propia interfa' de usuario, y concretamente desde el inspector, !ien asignando esos valores <a mano<, o !ien arrastrando un o!jeto o componente del tipo de dicha varia!le glo!al. #ara que podamos hacer eso es preciso, como digo, que la varia!le tenga un m!ito glo!al, y para ello es preciso que la misma se declare fuera de cualquier funci"n. /o veremos mejor con un ejemplo+ en el editor de scripts, encima de donde pone function %pdate, escri!iremos lo siguiente+ var camara e2eguridad + ?ameraC camara e2eguridad.name D <*i camara<C e!ug./og-camara e2eguridad.name.C 1s un miniscript parecido al que veamos en el captulo anterior. 1n l declaramos una varia!le glo!al -est fuera de cualquier funci"n. de tipo <?amera<, y lo que hacemos a continuaci"n es $va herencia$ asignarle un nom!re a la varia!le, que ser <*i camara<. /a tercera declaraci"n de momento nos !asta con sa!er que muestra en pantalla -imprime. el valor de lo que est entre sus parntesis. Fuardamos el script -si no, no funcionar. en el editor de scipts. e vuelta a la interfa' de %nity, si seleccionamos el nom!re del script vemos que en el inspector se ha actuali'ado dicho script con el c"digo que hemos introducido. 9o o!stante, nuestro script a3n no es funcional, ya que no lo hemos vinculado a ning3n o!jeto de nuestra escena. #ensemos que los scripts por s s"los no hacen nada, de la misma forma que cualquier asset que est en la carpeta;vista del proyecto -por ejemplo, una te(tura. no participar de alguna manera en una escena de nuestro juego si no lo arrastramos a esa escena, convirtindolo en parte de cualquier gameo!ject. 1n consecuencia, vamos a vincular nuestro script a uno de los game o!jects de nuestra escena, y en concreto al cu!o. #ara hacer eso meramente hemos de arrastrar el script desde la vista de proyecto hasta el propio o!jeto cu!o, !ien sea so!re su nom!re en la jerarqua, !ien so!re la propia imagen del cu!o en la escena. :ras arrastrar el script, y con el cu!o seleccionado en la jerarquia, en el inspector de!eramos estar viendo lo siguiente+

@!srvese que en el inspector aparece ahora el nom!re de nuestro script como una parte ms del ?u!o que tenemos en la escena. , daros cuenta de que la varia!le glo!al queda e(puesta en el inspector, de tal forma que no necesitamos ir al editor de scripts para asignarle un valor. 2i la varia!le hu!iera sido, por ejemplo, de tipo float, podramos ha!er introducido o cam!iado su valor meramente esc!i!indolo en el inspector. 2i en cam!io la varia!le fuera de tipo !ool, nos aparecera en el inspector con un chec8!o( al lado del nom!re, !ien marcado -true. o sin marcar -false. para que lo cam!iramos a conveniencia. #ero como en este caso la varia!le es de tipo ?amera, lo 3nico que podemos hacer para iniciali'arla es proveerla de un o!jeto de ese tipo. ado que en nuestra escena precisamente tenemos una cmara -la main camera., meramente tendremos que arrastrarla desde la jerarqua hasta el lugar del inspector donde se consigna el valor de la varia!le,y que ahora mismo pone <none<. :ras arrastrar la cmara, el inspector lucir as+

,a tenemos, por lo tanto, nuestro script asignado a un gameo!ject -nuestro cu!o. y la 3nica varia!le glo!al iniciali'ada con otro o!ject -la cmara principal.. #rocedamos ahora a darle al play y ver qu sucede. 2i nos fijamos, de!ajo de la ventana game nos aparecer impreso el nom!re que le asignamos a nuestra cmara.

Antes de aca!ar me gustara que practicramos un pequeo ejercicio que nos permitir comprender las diferentes

maneras -correctas e incorrectas. en que se puede declarar una varia!le. Borremos todo el contenido de nuestro script *i#rimer2cript y tecleemos lo siguiente+ var sin:ipo9i0niC var con:ipo2in0ni + intC var sin:ipo?on0ni D 5EC var con:ipo?on0ni + int D 5EC var a#la'os + intC a#la'os D 5EC private var mi2ecreto + intC var arrastrame + Fame@!jectC function %pdate-. O var en/aMuncion + intC P

2alvamos el script y, con el ?u!o seleccionado -recordemos que este script est todava vinculado al cu!o que tenemos en la escena. echamos un vista'o al inspector. #odemos de manera emprica llegar a las siguientes conclusiones para cada manera de declarar una varia!le+ /a varia!le sin:ipo9i0ni, que como su nom!re apunta hemos declarado sin indicar ni el tipo de datos que de!era contener, ni la hemos iniciali'ado conjuntamente con la declaraci"n, no aparece en el inspector, porque ste no tiene forma de sa!er qu tipo de varia!le estamos declarando. /a varia!le con:ipo2in0ni s es tenida en cuenta por el inspector, ya que aunque no la hemos iniciali'ado, s que hemos indicado el tipo de dato que queremos almacenar en ella. /a varia!le sin:ipo?on0ni s aparece en el inspector, ya que aunque no hemos declarado el tipo que contendr, al estar iniciali'ada permitimos a %nity deducir en !ase al valor en tipo de varia!le apropiado. Mijmonos que adems de aparecer la varia!le en el inspector, lo hace con el valor inicial que le hemos dado. /a varia!le con:ipo?on0ni aparece o!viamente en el inspector. /a varia!le a#la'os aparece en el inspector, pero sin iniciali'ar. 1n cam!io, si pulsamos play o!servaremos que automticamente le es asignado el valor 5E que le dimos en segunda declaraci"n. /a varia!le mi2ecreto no es accesi!le desde el inspector porque es privada. e hecho, esa varia!le no podr se accedida desde ning3n script distinto del que la contiene. /a varia!le arrastrame es recogida en el inspector, y al ser de un tipo propio de %nity, nos aparecer con una flechita diminuta en la derecha que nos indica que podemos importar del juego cualquier componente de ese tipo para asignar un valor a la misma, !ien usando el men3 que emerge al clic8ar dicha flecha, !ien va arrastrar el o!jeto o componente desde las carpetas de proyecto o jerarqua. #or 3ltimo, la varia!le en/aMunci"n no aparece en el inspector, ya que al ser declarada dentro de una funci"n no tiene carcter p3!lico.

Bueno, pues con esto ya de!era quedar un poco ms clara la manera en que las varia!les y los scripts son tratados en %nity. #ara la pr"(ima lecci"n empe'aremos a anali'ar clase por clase de la A#0.

3. CLASE OBJECT (I)


)a llegado el momento de empe'ar a pelearnos con las clases que componen la A#0 de %nity, y tal como os comenta!a considero lo ms conveniente empe'ar con la clase !ase.

1s sa!ido que en #@@ las clases !ase de las que heredan las dems suelen tener una funcionalidad !astante limitada, cuando no ine(istente, siendo su funci"n ms la de punto de partida de las que ha!rn de heredarla que la de instanciar o!jetos de dicha clase. /a clase @!ject, que es con la que vamos a empe'ar, no parece ser una e(cepci"n a esta regla.

/a clase @!ject consta de dos varia!les, dos funciones y nueve funciones de clase -M?.. ?omo sa!ris, las funciones de clase se diferencian de las funciones standard en que aqullas no precisan ser llamadas por una instancia u o!jeto de la clase, perteneciendo $como su nom!re indica$ a la clase y no a las instancias de dicha clase.

VARIABLES: name: var name : String Bueno, esta varia!le ya la conocamos. )ace referencia al nom!re del o!jeto, y comparten ese nom!re tanto el o!jeto en s como los componentes de dicho o!jeto. 1sta varia!le nos sirve tanto para cam!iar el nom!re a nuestro o!jeto... name D <?ualquier nom!re<C ...como para o!tener el nom!re de un o!jeto. #ro!emos esta segunda opci"n con un ejemplo muy sencillo. A!rimos %nity y nos vamos a la escena que creamos en la lecci"n anterior. 1n la vista del proyecto, hagamos do!le clic8 en el script que llamamos mi#rimer2cript. %na ve' se a!re el editor, !orramos todo el contenido y+ function %pdate-.O e!ug./og-name.C P ?omo vimos en la lecci"n anterior, e!ug./og nos permite imprimir en pantalla el valor de lo que se halle entre parntesis. 2alvamos el script -pero no cerramos el editor, meramente lo minimi'amos. )ay una cuesti"n que no quiero dejar pasar por alto. /o que hemos modificado y guardado es el script que se halla en la carpeta de proyecto. 9o o!stante, al hacer eso automticamente se modifican todas las copias de este script que tengamos por ah. 1n el caso que nos ocupa, recordaremos que a nuestro cu!o le ha!amos aadido una copia de este script, que a estas alturas por lo e(puesto ya ha!r sido modificado. #ro!moslo. 2i le damos al play, o!servaremos que !ajo la ventana game aparece el nom!re de nuestro cu!o. :odo !ien hasta aqu. no o!stante, en la definici"n del manual de referencia dice que todos los componentes del o!jeto comparten el mismo nom!re. 2i echamos un vista'o a nuestro cu!o en el inspector, o!servaremos que entre otros componentes tiene uno llamado transform, as que vamos a hacer la prue!a. 2ustituimos el <name< que ha!amos escrito en el editor de scripts entre parntesis por transform.name. @ sea+ e!ug./og-transform.name.C Fuardamos el script, le damos al play y....>oilQ, el componente transform comparte el nom!re <cu!o<.

hideFlags: var hideFlags : HideFlags 1sta varia!le no parece a priori tener una gran utilidad. 2e conseguira con su manipulaci"n hacer que un determinado o!jeto desapare'ca o !ien del inspector, o !ien de la jerarqua, o impedir que dicho o!jeto se pueda editar, o no permitir que un o!jeto sea salvado con la escena y en consecuencia destrudo con la nueva escena que se cargue. #ara tal fin esta varia!le manera las diferentes opciones de una de las muchas enumeraciones que hay en %nity. 1sta

enumeraci"n, de nom!re )ideMlags, tiene las siguientes opciones+ )ide0n)ierarchyNNNN1l o!jeto no aparecer en la jerarqua. )ide0n0nspectorNNNN1l o!jeto no aparecer en el inspector. ont2aveNNNNN1l o!jeto no ser salvado en la escena ni destruido en la nueva que se cargue. 9ot1dita!leNNNNNN1l o!jeto no ser edita!le en el inspector. )ideAnd ont2aveNNN?om!inaci"n de )ide0n)ierarchy y ont2ave.

As, si por ejemplo quisiramos -no se me ocurre muy !ien para qu. que el cu!o desapareciera del inspector mientras se desarrolla el juego, le vincularamos un script parecido a este+ var me1vaporo+ Fame@!jectCme1vaporo.hideMlags D )ideMlags.)ide0n0nspectorC 1ste script lo podramos arrastrar a la cmara principal, y con posterioridad arrastrar nuestro cu!o en la varia!le glo!al me1vaporo, que est esperando un game@!ject. @!servaremos que cuando le demos al play, el cu!o desaparece del inspector. R#or qu me1vaporo es de tipo Fame@!jectSR9o de!era tratarse de un @!ject, que es la clase que estamos tratandoS. #ues efectivamente, pero sucede que si sustituimos Fame@!ject por @!ject en nuestro script, compro!aremos que desaparece del inspector la varia!le me1vaporo, posi!lemente por lo que deca al principio de la lecci"n de que la clase @!ject est pensasa como clase !ase para dotar de funcionalidad a las que la heredan, que para ser instanciada ella misma. 1n cualquier caso, como digo, no parece que hideMlags sea una varia!le que vayamos a usar mucho.

4. CLASE OBJECT (II)

FUNCIONES: ToString: function ToString () : String evuelve un string con el nom!re del gameo!ject que hace la consulta. GetInstanceID: function GetInstanceID () : int %nity asigna a cada o!jeto un identificador 3nico. 1sta funci"n devuelve ese identificador. >amos a utili'ar estas dos funciones en un mismo ejemplo. 1n el captulo anterior tenamos vinculado nuestro script$ para$todo a la cmara principal. A!rimos el editor de scripts, !orramos todo y tecleamos lo siguiente+ var todo2o!re*i+ Fame@!jectC e!ug./og-<1l nom!re de este o!jeto es < B todo2o!re*i.:o2tring-. B < y su id unica es < B todo2o!re*i.Fet0nstance0 -..C 1l script no merece mucha e(plicaci"n. Asegurmonos de arrastrar el cu!o a la varia!le todo2o!re*i en el inspector. Al pulsar el play de!eria mostrarse el nom!re e id del cu!o, tal como se muestra en la imagen -o!viamente, la id no tiene por qu coincidir con la que os apare'ca a vosotros.

FUNCIONES DE CLASE

o!erator "ool# $$ % &$ 1stas tres funciones mramente ha!ilitan la posi!ilidad de esta!lecer comparaciones de igualdad;desigualdad entre dos o!jetos o componentes, o -en el caso del operador !ool.si e(iste dicho o!jeto componente y tiene un valor distinto de null. #or ejemplo+ if -rigid!ody. e!ug./og-<1ste gameo!ject tiene vinculado un &igid!ody<.C Gue sera lo mismo que ha!er escrito if -rigid!ody QD null. e!ug./og-<1ste gameo!ject tiene vinculado un &igid!ody<.C

Instantiate: static function Instantiate (original : Object !osition : "ector# rotation : $uaternion) : Object 1sta funci"n lo que hace es clonar el o!jeto que le pasamos como primer parmetro, y devolver ese clon del o!jeto original, u!icndolo en posici"n y rotaci"n determinadas. @!servamos que el parmetro <position< es de tipo >ector7, que es una clase que no tardaremos mucho en estudiar. e hecho, posi!lemente sea la pr"(ima que tratemos, ya que aunque no pertenece a la jerarqua de herencia que hemos tomado como referencia para el orden de estudio, s que va a aparecer el n3mero suficiente de veces durante el trnsito por dicha jerarqua como para no ocuparnos de ella de primeras. %n >ector7 es, en pocas pala!ras, un punto en el espacio tridimensional. icho punto viene dado por las coordenadas en el eje I -derecha$i'quierda. , -arri!a$a!ajo. y J -delante$detrs.. ?ada unidad se corresponde a una unidad en %nity -valga la redundancia., que a su ve' equivale a un metro. #or lo tanto para que un o!jeto se desplace un metro a la derecha, escri!iramos en nuestro >ector7 -5,E,E.. 9otemos que esto es ni ms ni menos que lo que hace de manera ms visual las tres varia!les position del transform que aparecen en el inspector. 1l otro parmetro de la funci"n, rotation, es de tipo Guaternion. Guien sepa lo que es, felicidades, yo estuve varios das pelendome con apuntes de matemticas por la red y a lo sumo me hice una idea a!stracta de que un cuaterni"n se compone de tres n3meros reales y uno imaginario, el clculo de los cuales esta!lece la rotaci"n de un o!jeto. 2i os sirve de consuelo, y eso lo indica el propio manual de referencia oficial de %nity, es muy raro que tra!ajemos directamente con cuaterniones, sino que lo haremos con funciones que nos simplifiquen el tra!ajo. ,o personalmente me quedo solamente con la idea de que un cuaterni"n lo componen cuatro elementos y mide las rotaciones. ?on eso es suficiente, creedme. Bueno, pues dicho esto a ver si somos capaces de instanciar;clonar un cu!o. 9os vamos a %nity, y le quitamos a la cmara principal el script que le ha!amos colocado anteriormente. #ara hacer eso, con la cmara seleccionada en el inspector colocamos el rat"n so!re el nom!re del script, !ot"n derechoDL&emove ?omponent. Ahora, para no andar vinculando scripts a gameo!jects que nada tienen que ver con l -como hicimos no hace mucho con la cmara., vamos a crear un gameo!ject vaco cuya 3nica utilidad sea contener nuestro script. #ara ello nos vamos al men3 superior, y le damos a Fame@!jectDL?reate empty. A la carpeta que nos aparecer en la jerarqua la renom!ramos -M6. como #orta2cripts.

>ale, ahora do!le clic so!re nuestro script en la vista de #royecto para a!rir el editor de scipts, y escri!imos+ var reproducete + Fame@!jectC 0nstantiate-reproducete, >ector7-6.E,E,E., Guaternion.identity.C Aqu lo que hemos hecho meramente es dejar una varia!le glo!al <e(puesta< -que pueda ser accesi!le desde el inspector. y llamar a la funci"n instantiate, de tal manera que clonar el Fameo!ject que le arrastremos y lo situar dos unidades;metros a la derecha del o!jeto original. Guaternion.identity meramente significa que el o!jeto clonado tendr rotaci"n cero, esto es, su transform rotation estar a E,E,E -salvo que el o!jeto clonado dependa a su ve' de otro o!jeto, en cuyo caso tendr la misma rotaci"n que el o!jeto padre, pero esto ya lo e(plicaremos cuando toque. 2alvamos el script y lo arrastramos hasta nuestro #orta2cripts en la jerarqua. >emos que en el inspector, con #orta2cripts seleccionado, aparece el script y la varia!le e(puesta que llamamos reproducete. Arrastramos el cu!o hasta ella y ya podemos darle al play. e!era aparecernos un segundo cu!o, tal que as+

#odemos o!servar alguna cosa ms. 1n la jerarqua aparece $mientras se est reproduciendo la escena$ un segundo cu!o, el cual %nity nos indica e(presamente que es un clon del original. 2i lo seleccionamos, podemos ver en su transform en el inspector que la varia!le ( -el eje derecha;i'quierda. no est en el cero, sino en el dos, tal como le ha!amos indicado. #ro!emos otra cosa. etenemos la reproducci"n de la escena. 2eleccionamos el cu!o original, y le damos a los ejes I e , de transform rotation los valores 6K y TK respectivamente.1l cu!o girar so!re dichos ejes. mosle al play. #odemos o!servar que el cu!o clonado se muestra alineado con la cuadrcula glo!al, y no con el cu!o original. 1sto es lo que conseguimos con Guaternion.identity. /a funci"n instantiate es muy usada para crear proyectiles, partculas en e(plosiones e incluso A0 -inteligencia artificial. para enemigos. ?a!e una segunda forma distinta para la funci"n 0nstantiate, que es esta+ static function Instantiate (original : Object) : Object ?omo podemos o!servar, aqu meramente estamos duplicando el o!jeto, se tal suerte que el clonado se u!icar en el mismo lugar y con la misma rotaci"n que el original. #odemos pro!arlo en nuestro script meramente eliminando el segundo y tercer parmetro. Al darle al play, sa!emos que ha aparecido un clon porque as lo indica la jerarqua, pero no podemos distinguirlo porque est justo en el mismo sitio que el original y se estn solapando.

Destro%: static function Destro% (obj : Object t : float & '('F) : void ?omo su nom!re indica, esta funci"n !orra del juego un gameo!ject, un componente o un asset. :iene dos parmetros, siendo el primero el elemento a !orrar y el segundo el tiempo en segundos que tardar en !orrarlo desde que se llame a la funci"n -si no se indica lo contrario, por defecto el parmetro indica cero segundos, esto es, la destrucci"n del o!jeto es automtica.. )ay una cuesti"n que igual ahora no se entiende muy !ien, pero la dejo apuntada para tratarla ms en profundidad en otro momento+ si en el parmetro o!t colocamos un ?omponente, la funci"n s"lo eliminar ese componente, hacindolo desaparecer del Fameo!ject al que pertene'ca. #ero si en cam!io lo que le pasamos a la funci"n es un gameo!ject, se destruir tanto el gameo!ject como todos los hijos de ese gameo!ject -esto es, todos los o!jetos y componentes e inclusive otros gameo!jects que dependan del eliminado en una relaci"n de parentesco.. #ara tener un acercamiento intuitivo a esta relaci"n de dependencia, pensemos en un gameo!ject coche que tiene, entre otros, cuatro componentes rueda y un gameo!ject conductor que hemos vinculado al gameo!ject coche para que all donde se desplace el coche vaya el conductor. 2i un misil destruye un componente rueda usando la funci"n destroy, s"lo se destruir la rueda. 2i en cam!io lo que destruye es el gameo!ject coche, se destruir tanto el vehculo como las ruedas como el conductor.

>amos a pro!ar la funci"n estroy. #ara empe'ar devolvamos a nuestro cu!o original a su rotaci"n original -E,E,E.. >amos a rehacer ahora nuestro sufrido script, que tenemos vinculado al cu!o. 1n el editor de scripts modificamos nuestro c"digo as+ var reproducete + Fame@!jectC var nasio#a*orir + Fame@!jectC nasio#a*orir D 0nstantiate-reproducete, >ector7-6.E,E,E., Guaternion.identity.C estroy -nasio#a*orir, 5E.E.C ?reo que es !astante fcil de entender. /o que hemos hecho es aadir una segunda varia!le de tipo Fame@!ject, que no vamos a iniciali'ar desde el inspector, porque lo que har ser almacenar el cu!o clonado que devuelve la funci"n 0nstantiate. 0nmediatamente es llamada la funci"n estroy, que !orrar el elemento clonado que hemos almacenado en nasio#a*orir pasados die' segundos. 2alvamos, le damos al play, contamos die', y adi"s clon.

Destro%Immediate: static function Destro%Immediate (obj : Object allo)Destro%ing*ssets : boolean & false) : void 1sta funci"n destruye inmediatamente un o!jeto, igual que la funci"n anterior. esde el manual de %nity se nos dice, no o!stante, que es preferi!le usar estroy en lugar de esta funci"n, ya que puede !orrar ms de lo que deseamos. #or lo tanto, olvidmonos de estroy0mmediate.

5. CLASE OBJECT ( III)

?ontinuamos con las funciones de clase de la clase @!ject. &ecordemos que las funciones de clase, como su nom!re indica, no van vinculadas a o!jetos o instancias de una clase, sino a la clase en s, esto es, no se utili'a el operador punto entre el nom!re del o!jeto;instancia y el de la funci"n, como sucedera en una funci"n normal -o mtodo. dentro de una clase.

FindO"'ectO(T%!e static function FindObjectOfT%!e (t%!e : T%!e) : Object

1sta funci"n devuelve el primer o!jeto activo que %nity encuentre que sea del tipo que le pasamos como parmetro. >emoslo en un ejemplo. &ecuperamos una ve' ms nuestro script, !orramos todo y tipeamos lo siguiente+ var dameAlgo + @!jectC dameAlgo D Mind@!ject@f:ype-?amera.C e!ug./og-< e!eria ha!er encontrado 5 < B dameAlgo.C 2alvamos, le damos al play y o!servamos que %nity ha encontrado nuestra cmara principal. 9os advierte el manual de referencia que esta funci"n puede ser un poco lenta y costosa en trminos de rendimiento, por lo que se recomienda no usarla a su ve' como parte de una funci"n que se actualice cada frame -como por ejemplo la funci"n %pdate, que estudiaremos a no mucho tardar.

FindO"'ectsO(T%!e static function FindObjectsOfT%!e (t%!e : T%!e) : Object+,

9o hace falta ser muy perspica' para darse cuenta de que esta funci"n es idntica a la anterior, con la diferencia de que aqu lo que se devuelve no es el primer o!jeto activo de tipo :ype, sino que se devuelven en un array todos los o!jetos activos cuyo tipo coincide con el que solicitamos. >eamos la diferencia rehaciendo nuestro script+ var dameAlgo + @!jectUVC var chivato + 2tringC dameAlgo D Mind@!jects@f:ype-Fame@!ject.C chivato D <)e encontrado < B dameAlgo./ength B < o!jetos+ <C for-var contador D EC contador W dameAlgo./engthC contadorBB. chivato BD dameAlgoUcontadorV.name B < <C e!ug./og-chivato.C /o que hemos hecho aqu es lo siguiente+ primero hemos reconvertido nuestra varia!le dameAlgo en un array de @!jects. eclaramos despus una varia!le de tipo string para que vaya recopilando toda la informaci"n que al final imprimiremos. 0niciali'amos luego nuestro array con todos los o!jetos de tipo Fame@!ject que %nity encuentre en nuestra escena. A partir de ah,montamos un !ucle for para ir aadiendo a nuestro string <chivato< el nom!re de todos los o!jetos encontrados. Minalmente, imprimimos. 2i todo ha salido !ien, el resultado tendra que ser este al darle al play+ DontDestro%OnLoad static function DontDestro%On-oad (target : Object) : void ?on esta funci"n conseguimos que el o!jeto que colocamos como parmetro no se destruya cuando se cargue una nueva escena. #or defecto, cuando el jugador cam!ia de escena o nivel, todos los o!jetos de la escena que a!andona se destruyen antes de crear los que corresponden al nuevo nivel. ?on esta funci"n, conseguimos que los o!jetos que queramos pervivan al cam!io de escena. ado que a3n no sa!emos cargar escenas nuevas, no vamos a reali'ar ning3n ejemplo. ,a lo haremos cuando e(pliquemos las oporunas funciones.

, con esto aca!amos el anlisis de nuestra primera clase. 1spero que os hayan quedado los conceptos ms o menos claros -al principio cuesta un poquillo, as que no desesperis.. , por supuesto, si hay alguna duda, queja -educada. o correcci"n que hacer, sentiros li!res de comentar.

!. ESTRUCTURA VECTOR3 (I)


/o primero que ca!ra decir de >ector7 es que, a diferencia de @!ject, por ejemplo, no es en s una clase, sino una estructura. 1n la corta historia de la programaci"n las estructuras surgieron antes de las clases, en los viejos tiempos de la programaci"n procedimental, y originalmente eran poco ms que una colecci"n de varia!les que guarda!an alg3n tipo de relaci"n entre s. )oy por hoy, no o!stante, no hay ninguna diferencia entre una estructura y una clase. Aunque >ector7 no est contenido dentro del esquema de herencia principal de %nity, es una clase imprescindi!le para la creaci"n de cualquier juego, ya que precisamente es la que permite que representemos puntos y vectores en el espacio 7 , y por ende la que nos permite tra!ajar con distancias y despla'amientos. 1l concepto de punto, siendo sencillo cuando se entiende, a veces provoca en los recin llegados no pocas confusiones. Gui's lo mejor para captar el concepto de punto en 7 previamente tengamos que aprehender el concepto de punto en 6 . >amos a intentar e(plicarlo de una manera llana, y ruego me disculpen los que ya tenan claro el concepto+ elante vuestro posi!lemente tengis la pantalla de vuestro ordenador o del dispositivo electr"nico desde el que estis

viendo estas lneas. 1n alg3n lugar de la pantalla estar seguramente el cursor del rat"n, apuntando a alg3n punto -valga la redundancia. determinado de sta. 2i quisiramos e(plicarle a alguien que no est viendo la pantalla en qu lugar est el cursor, o si meramente quisiramos dejar por escrito de una manera fia!le en qu punto e(acto est ahora nuestro cursor, una !uena manera de hacerlo sera decir+ el cursor est I centmetros -digamos por ejemplo 5T. a la derecha del !orde i'quierdo de la pantalla e , centmetros por de!ajo del !orde superior de la pantalla -pongamos 6E.. As, si por ejemplo convenimos que la esquina superior i'quierda de la pantalla es el punto E,E, nuestro cursor en el mundo 6 de la pantalla estar situado en el punto 5T,6E. #or lo tanto, o!servamos que para determinar la situaci"n e(acta de un punto necesitamos a su ve' otro punto que nos sirva de referencia -, es importante retener este concepto, so!re el que no tardaremos en volver.. As, para sa!er d"nde est el punto al que seala el rat"n necesitamos primero compararlo con el punto que tomamos como referencia, y la resta entre am!os puntos es la distancia que los separa, que es este caso ya no sera un punto sino un vector, aunque se represente igual. /o mismo es aplica!le a las tres dimensiones, aunque a nivel intuitivo nos cueste un poco ms de pillarlo. *eramente entendamos que si nuestra pantalla de ordenador no fuera plana, sino por ejemplo un holograma, para locali'ar el o!jetivo de nuestro rat"n tendramos que aadir un nuevo punto -o eje. J, para calcular la profundidad con relaci"n a un punto de origen -que podra ser la esquina superior i'quierda ms cercana a nosotros de la pantalla hologrfica en 7d. /a estructura >ector7, pues, nos permite averiguar en qu punto se halla cada gameo!ject, cam!iar su posici"n, calcular las distancias entre ellos, etc. 1s conveniente advertir que el tipo >ector7 no es la 3nica clase;estructura que maneja lo relativo a puntos y despla'amientos. ?umplen funcionalidades parecidas -que no iguales. la clase Guaternion y la *atri(XIX. 1(isten, antes de que nos alarmemos en e(ceso, funciones que permiten convertir, por ejemplo, un >ector7 en un Guaternion -y viceversa., as que de momento no nos o!sesionemos ms de la cuenta con conceptos que nos suenen e(traos. , tras esta e(tensa introducci"n, en el pr"(imo captulo empe'amos con la estructura en s.

". ESTRUCTURA VECTOR3 (II)


CONSTRUCTOR: .)static function "ector# (/ : float % : float 0 : float) : "ector#

?omo sa!emos de nuestros conocimientos de programaci"n orientada a o!jetos, el constructor es una funci"n especial cuyo cometido es crear de manera adecuada las instancias;o!jetos de una determinada clase o estructura. /a funci"n constructora se caracteri'a por tener el mismo nom!re que la clase. :al como vemos en el prototipo de nuestro constructor, le hemos de pasar al mismo los tres componentes de nuestro punto 7 , referidos al eje hori'ontal, vertical y de profundidad respectivamente, en formato de punto flotante. As+ var mi#unto D >ector7-6.E, K.E, X.Y.C

referenciamos un punto que con respecto al origen se despla'ar dos unidades a la derecha, cinco hacia arri!a y X,Y hacia el fondo. >ale, pero Rcul es el origenS, se preguntar alguien. #ues depende, tendremos que responder. 2i un o!jeto no depende de otro, entendemos por origen el punto E,E,E de las coordenadas glo!ales -que es donde de!eramos tener nuestro cu!o. y desde ese punto origen se calcula el despla'amiento, pero si un o!jeto depende de otro -recordemos el ejemplo de la rueda y el coche. ca!en para ese o!jeto dos orgenes o coordenadas diferentes+ las glo!ales -distancia de la rueda respecto del eje E,E,E del caso anterior. y las locales -referidas al o!jeto del que depende.

1)static function "ector# (/ : float % : float) : "ector#

?omo vemos, hay una segunda funci"n constructora que no toma en cuenta el eje J -la profundidad. asumiendo que sta es cero. #or tanto, si a la funci"n constructora >ector7 s"lo le pasamos dos parmetros, automticamente ser llamada esta segunda versi"n del constructor.

VARIABLES:

)# %# *:

1stas varia!les se refieren a los componentes I, , y J del vector, respectivamente.

this: var this+inde/ : int, : float

1sta es otra forma para acceder a los componentes I, , y J del vector, siendo los respectivos ndices de cada componente E, 5 y 6. As, estas dos declaraciones son equivalentes+ var mi>ector + >ector7C mi>ector.( D 7.EC mi>ectorUEV D 7.EC ;;1quivale a la anterior

magnit+de: var magnitude : float 1sta varia!le devuelve la longitud o tamao de un vector. )a!amos ha!lado previamente de que un vector7 contiene el n3mero de unidades que lo separan del origen dado en los ejes I, , y J. @!viamente, cuanta mayor es la distancia entre nuestro >ector7 y el punto de origen, mayor la longitud del vector. /a longitud del vector equivale a la rai' cuadrada de -(Z(ByZyB'Z'.. 2oy consciente de que a estas alturas la utilidad de funciones como estas es difcil de apreciar. ?on un poco de paciencia, y cuando las com!inemos con otras clases, veremos el partido que se le puede sacar a todo esto.

s,r-agnit+de: var s2r3agnitude : float

2i de lo que se trata es de comparar dos vectores, es preferi!le usar esta funci"n que la precedente, ya que aunque pare'ca antiintuitivo, %nity calcula con ms rapide' los cuadrados de las magnitudes que las magnitudes en s.

normali*ed: var normali0ed : "ector#

1sta varia!le devuelve un vector con la misma direcci"n que el original, pero con magnitud 5. 1s importante constatar

que el vector original permanece inalterado y lo que se devuelve es meramente una copia que conserva la direcci"n de dicho original, aunque con la longitud alterada. 2i en lugar de normali'ar una copia quisiramos hacer lo propio con el original, entonces tendramos que usar la funci"n 9ormali'e, que veremos en !reve. ecir tam!in que si el vector es demasiado pequeo para ser normali'ado, lo que se devuelve es un vector a cero.

VARIABLES DE CLASE:

*ero: static var 0ero : "ector#

1s meramente un atajo para poner un vector a cero. transform.position D >ector7.'eroC ;; 1s lo mismo que escri!ir transform.position D >ector7-E,E,E.C

one# (or.ard# +! % right:

2on respectivamente atajos para escri!ir >ector7-5,5,5., >ector7-E,E,5., >ector7-E,5,E. y >ector7-5,E,E..

>amos a ver algunos de los conceptos de esta lecci"n en un ejemplo. A!rimos nuestro script favorito y escri!imos+ var un@!jeto + Fame@!jectC var despla'amiento + >ector7C var magnitud + int D EC despla'amiento D >ector7.rightC for-var contador D EC contador W 7C contadorBB. O un@!jeto.transform.position BD despla'amientoC magnitud BD despla'amiento.magnitudeC e!ug./og-</ongitud del >ector del cu!o+ < B magnitud.C P

2alvamos, arrastramos nuestro cu!o para que se convierta en la varia!le un@!jeto y le damos al play. 9uestro cu!o se mueve tres unidades a la derecha y !ajo la ventana Fame aparece la magnitud de despla'amiento del vector. 1l script funciona de la siguiente forma+ Adems de la varia!le que sostendr a nuestro cu!o, creamos una varia!le de tipo >ecto7 para poder almacenar a modo de impulsos manio!ras de despla'amiento de una unidad a la derecha. 1se input a la derecha se lo daremos tres veces mediante un !ucle for, y cada magnitud individual -que o!viamente vale 5 cada ve'. se acumula en una varia!le de tipo int que hemos creado a tal efecto.

#. ESTRUCTURA VECTOR3(III)

Scale: function Scale (scale : "ector#) : void

*ultiplica el >ector7 que llama la funci"n por el >ector7 que le pasamos a dicha funci"n como parmetro. /o veremos mejor con un ejemplo. >amos a darle un meneo de nuevo a nuestro script. :ecleamos+ var un@!jeto + Fame@!jectC var mi>ector + >ector7C mi>ector D un@!jeto.transform.position D >ector7-6.E, 5.E, 7.E.C e!ug./og-<*agnitud inicial del cu!o < Bmi>ector.magnitude.C mi>ector.2cale->ector7-7.E, 5.K, 6.E..C un@!jeto.transform.position D mi>ectorC e!ug./og-<*agnitud final del cu!o < Bmi>ector.magnitude.C Antes que nada vamos a e(plicar lo que pretendemos hacer+ dejamos e(puesta la varia!le un@!jeto para arrastrar con posterioridad nuestro cu!o desde el inspector. Asimismo declaramos una varia!le para sostener el valor original y modificado para un vector7. Aunque a3n no lo hemos estudiado, a nadie sorprender que los diferentes gameo!jects que ocupan la escena han de ir ineludi!lemente vinculados a un o!jeto transform, el cual a su ve' es el que sirve para fijar en qu punto del espacio 7 se halla el gameo!ject. As, para o!tener o indicar la posici"n de un gameo!ject en el espacio usaramos la sinta(is gameo!ject.transform.position. 2e da la circunstancia que la varia!le position de la clase transform es de tipo >ector7, por lo que nos sirve para nuestro ejemplo. )acemos una iniciaci"n do!le, de tal manera que damos unos valores a nuestro >ector7 mi>ector, que a su ve' tendr el mismo valor que le damos a la posici"n actual del cu!o. @!tenemos la magnitud de dicho vector y la imprimimos. /uego usamos la funci"n 2cale, y la magnitud del vector modificado es impreso de nuevo, y a la par el cu!o se despla'a por segunda ve'. @!tendremos al darle al play un resultado como este

2i nos fijamos en la parte inferior de la ventana Fame, s"lo aparece impresa la magnitud final del vector de nuestro cu!o. #ara ver tam!in el valor inicial, hemos de hacer un clic8 so!re dicho te(to impreso, de tal suerte que nos aparecer una ventana emergente con am!os valores, tal como mostramos+

/a funci"n 2cale tiene un segundo prototipo, que es el que sigue static function Scale (a : "ector# b : "ector#) : "ector#

1l fin 3ltimo es, al igual que en la funci"n hom"nima, multiplicar dos vectores. /a diferencia es que aqu pasamos e(presamente los dos vectores que queremos multiplicar entre s. :am!in difieren am!as funciones en que la primera no devuelve ning3n valor -el cam!io resultante de la multiplicaci"n es directamente asignado al o!jeto que la llama. y esta en cam!io s devuelve un >ector7 con el resultado, que podemos por lo tanto asignar a una varia!le.

Normali*e: function 4ormali0e () : void

1sta funci"n hace que el >ector7 que la llama pase a tener una magnitude de 5, conservando, eso s, la misma direcci"n. ?omo decimos, esta funci"n cam!ia el vector que la llamaC si lo que pretendemos es conservar sin cam!ios el vector corriente y crear un nuevo vector normali'ado, hemos de usar $como ya aprendimos en el captulo anterior$ la varia!le normali'ed.

ToString: function ToString () : String

evuelve nuestro vector convertido en un string y formateado. #ara ver como funciona, aadamos al final del script que usamos en el ejemplo anterior la siguiente lnea+ e!ug./og-<*i vector como string formateado+ < B mi>ector.:o2tring-..C

>eremos que nos aparece el vector resultado de la multiplicaci"n del anterior ejemplo convertido en un string que podemos imprimir. ejamos para el pr"(imo captulo las dos funciones de clase que nos restan para aca!ar la e(plicaci"n de la estructura >ector7.

$. ESTRUCTURA VECTOR3 ( IV)

FUNCIONES DE CLASE:

Ler!: static function -er! (from : "ector# to : "ector# t : float) : "ector#

1sta funci"n interpola linealmente entre dos vectores, desde from hacia to en el valor t. >amos a intentar e(plicarlo de la manera ms clara posi!le, ya que se trata de una funci"n importante+ /erp reali'a una lnea imaginaria que va del punto que le pasamos como primer parmetro -from. al punto que le pasamos como segundo parmetro -to.. 1sa lnea imaginaria es entonces una recta con un origen y un final, y entre am!os e(tremos tiene muchos puntos intermedios. #ensemos por ejemplo en una regla, para tener ms o menos claro el concepto. #ongamos que al punto de origen -from. le asignamos el valor E, y al punto final -to. le damos el valor 5. 1n ese caso, el punto que est en la mitad de nuestra recta imaginaria es evidente que valdr E,K. ?on esto claro planteemos ahora el mismo asunto pero al revs. :enemos el punto origen y el punto final y queremos sa!er d"nde est la mitad e(acta entre esos dos puntos. /o que haramos es llamar a la funci"n /erp, asignar a los parmetros primero y segundo respectivamente las coordenadas de origen y final y darle al tercer parmetro -que en el prototipo reci!e el nom!re de <t<, y es de tipo float. el valor E.K. 1l valor retornado por la funci"n se corresponder con el punto situado en el centro de los dos e(tremos dados. 1l parmetro t puede reci!ir valores entre E.E -que coincide con el origen. hasta 5.E -que coincide con el final.. >amos a practicar.

1n %nity, le quitamos provisionalmente a nuestro gameo!ject #orta2cripts el script, para que no nos d errores en lo que a continuaci"n haremos. Acto seguido vamos al men3 gameo!jectDL creater other DL capsule. ?olocamos la cpsula a un valor $7 en el eje ( del transform en el inspector. &enom!ramos a esta cpsula y la llamamos @rigen. ?reamos luego otra cpsula, y en la coordenada ( de su transform la pondremos en 7. /a re!auti'amos como Min -Minal es una pala!ra reservada. 1s preferi!le que tengamos la escena enfocada desde la vista superior -lo que conseguimos haciendo clic8 en el eje , del gi'mo. Ahora hacemos do!le clic8 en el script -que aunque hemos !orrado del #ortascripts sigue estando en el #royecto., y tecleamos+ var principio + :ransformC var fin + :ransformC function %pdate -. O transform.position D >ector7./erp-principio.position, fin.position, E.7.C P

2alvamos el script y lo arrastramos a nuestro cu!o. Acto seguido seleccionamos el cu!o y en el inspector nos aparecern nuestras dos varia!les. Arrastramos origen a principio y destino a fin. 2i todo va !ien, nuestro cu!o de!iera situarse a tres dcimas partes de la lnea hipottica que separa las cpsulas, contando desde la que hemos dado en llamar origen. R/o pro!amosS

Bien. #arece que funciona, pero podemos ir un poco ms all. #ara ello vamos a recurrir a una clase que a3n no hemos estudiado, que es la clase :ime, y concretamente a la varia!le time de la clase :ime. :ime.time es una varia!le que representa los segundos transcurridos desde que el juego se inicia. #or lo tanto, la varia!le vale cero al iniciarse el juego, 5 un segundo despus, etc. ?on esto en mente, vamos a nuestro 3ltimo script y dentro de la funci"n /erp sustituimos el E.7 por :ime.time, salvamos y le damos al play. 1fectivamente, nuestro cu!o empie'a pegado al origen -el parmetro t, representado por :ime.time vale cero. y va despla'ndose hacia el fin hasta que t vale 5, o sea, hasta que transcurre un segundo. 2a!iendo esto, podemos hacer que el trayecto de nuestro cu!o dure por ejemplo die' segundos en lugar de uno. ?onseguimos esto meramente multiplicando :ime.time Z E.5. #odemos, dndole una vuelta ms de tuerca al asunto, crear una varia!le e(puesta -suscepti!le de ser accesada desde el inspector. de tipo float, que el usuario pueda modificar, y que al ser multiplicada por :ime.time haga que nuestro cu!o viaje ms rpido o ms lento.

Sler!: static function Sler! (from : "ector# to : "ector# t : float) : "ector#

1sta funci"n es similar a la anterior, con la particularidad de que en lugar de interpolar en lnea recta lo hace en forma esfrica. #ara pro!arla no tienes ms que sustituir el trmino </erp< del script anterior por <2lerp<, y poner el cu!o en "r!ita. 2i tienes tiempo y ganas, u!ica los gameo!jects @rigen y estino en otras posiciones a travs de sus respectivos transforms en el inspector -despl'alos tam!in en sus ejes , y J..

10. CLASE TRANS%ORM (I)

>amos a dedicar los pr"(imos captulos a estudiar una de las clases ms importantes de la A#0 de %nity. /a clase :ransform, como vemos en el grfico, hereda de ?omponent, que a su ve' deriva de @!ject, y por lo tanto esta clase tiene como propias las varia!les y funciones de las dos clases de las que hereda. /a pregunta parece o!ligada+ si :ransform hereda de ?omponent, Rpor qu no estudiamos la clase ?omponent primeroS 9o lo hacemos porque la clase ?omponent, en el fondo, es poco ms que una recopilaci"n del resto de clases. /o veremos mejor si recuperamos el grfico general de clases que vimos en su da+

2i nos fijamos con atenci"n, o!servaremos que la mayora de las varia!les de la ?lase component son a su ve' instancias -o!jetos. de un !uen n3mero de las otras clases, algunas de las cuales incluso $como la propia clase :ransform$ derivan de sta. 9os veramos pues, caso de estudiar primero la clase ?omponent, o!ligados a e(plicar lo que es un transform, un rigid!ody, una camera, etc, antes de e(plicar las clases que los desarrollan. #or lo tanto, para no liarnos en e(ceso, dejaremos la clase ?omponent para !astante ms adelante. Bien. RGu es un transformS. #osi!lemente muchos de los que ya hayan trasteado con la interface de %nity asimilarn esta pala!ra a la secci"n hom"nima del inspector. 1fectivamente, si seleccionamos cualquier gameo!ject de la escena, automticamente el inspector nos muestra en la secci"n transform los valores de posici"n, rotaci"n y escala de dicho gameo!ject. 9o puede e(istir un gameo!ject en la escena sin su propio transform. 2i nos fijamos, hasta nuestro #orta2cripts tiene vinculado un transform, pese a que como mero contenedor de scripts no es renderi'ado en la escena, y por lo tanto es invisi!le. 1n consecuencia, todo gameo!ject en nuestra escena est situado en un lugar determinado de sta -position., con una determinada inclinaci"n -rotation. y le es aplicada una determinada escala comparativa de tamao -scale.. ?on esto en mente, empecemos.

VARIABLES:

!osition: var !osition : "ector#

1sta varia!le nos indica en qu punto del espacio glo!al se u!ica nuestro transform -y por ende el gameo!ject al que el mismo va vinculado.. &ecordemos que el espacio glo!al es el que hace referencia a las coordenadas de la escena, y no a las de un determinado o!jeto. 2i quisiramos consultar;indicar el lugar del espacio local de un o!jeto, utili'aramos la varia!le local#osition. /a varia!le position es de tipo >ector7, y nos permite tanto o!tener los datos de posici"n del transform como modificarlos para darle una nueva u!icaci"n. #or ejemplo, si quisiramos u!icar un o!jeto en el centro del espacio glo!al, haramos+ el@!jetoGue2ea.transform.position D >ector7-E, E, E.C

#odemos asimismo acceder a uno s"lo de los ejes de la posici"n, tal como sigue+ e!ug./og-el@!jetoGue2ea.transform.position.(.C

/o cual nos permitira imprimir la posici"n que tiene nuestro transform referida al eje hori'ontal.

local/osition: var local5osition : "ector#

?omo adelant!amos hace un momento, local#osition indica la posici"n del transform al que dicha varia!le pertenece, calculada en trminos relativos al transform del que aqul depende. #arece ms difcil de lo que es en realidad, tal como vamos a demostrar con un ejemplo sencillo+ 9os vamos a %nity. 2i hemos guardado nuestra 3ltima sesi"n, de!emos tener en nuestra escena, aparte de nuestro viejo amigo el cu!o, dos cpsulas de nom!re origen y destino. 1liminamos estino. 2i por lo que sea no hu!iramos conservado las cpsulas, creamos un gameo!ject capsule nueva. 1sa cpsula -u @rigen, si guardamos la 3ltima escena.la u!icamos desde el inspector en la posici"n -7, X, 6. &esumiendo, tenemos en la escena-o de!iramos tener. el cu!o en las coordenadas de posici"n -E,E,E. y una cpsula en la posici"n -7,X,6.. 9inguno de estos gameo!jects es hijo a su ve' de otro, por lo que estn y se mueven en coordenadas glo!ales. A!rimos nuestro script y escri!imos+ transform.position D >ector7-$6,$5,$5.C

2alvamos y arrastramos el script a nuestro cu!o. Al darle al play, vemos que ste se despla'a respecto la posici"n que ocupa!a en las coordenadas glo!ales -el centro justo. dos unidades a la i'quierda, una hacia a!ajo y una hacia delante. Al darle al pause, nuestro cu!o vuelve a su lugar original, en E,E,E -es importante retener esto. >amos ahora a, en la =erarqua, arrastrar el gameo!ject cu!o y soltarlo dentro de gameo!ject cpsula -u @rigen.. >emos que el cu!o mantiene su posici"n en la vista de escena, pero si lo seleccionamos -est ahora contenido en la cpsula., sus coordenadas en el transform del inspector son ahora las inversas que las que le dimos al gameo!ject cpsula. 1sto es as porque ahora para el cu!o sus coordenadas de posici"n no dependen ya del espacio glo!al, sino del local de la cpsula de la cual depende. #ara el cu!o la coordenada E,E,E no es ya el centro de la escena, sino el centro del gameo!ject capsula, y dado que con respecto a la cpsula el cu!o est despla'ado tres unidades a la i'quierda, cuatro hacia a!ajo y dos hacia delante, son las que muestra. 1l hecho de que el cu!o dependa de la cpsula o dicho en terminologa %nity, el cu!o sea hijo de la cpsula, no implica que no pueda seguir siendo locali'ado;u!icado en coordenadas glo!ales. e hecho, si le damos al play de nuevo, ha!ida cuenta de que estamos utili'ando en nuestro script la varia!le position -glo!al., el cu!o se seguir despla'ando al mismo sitio al que lo haca cuando a3n no dependa de la cpsula. #ero, o!viamente, al tener ahora un padre, le podemos aplicar ahora al cu!o la varia!le local#osition, y as podemos modificar el script como sigue+ transform.local#osition D >ector7-$6,$5,$5.C

>emos ahora que el movimiento del cu!o lo es en relaci"n con la posici"n que ocupa pap capsula -o para ser ms precisos el transform de pap cpsula.. #ro!ad si no lo veis claro a pasarle un vector -E,E,E. a nuestro script en lugar del que hemos escrito antes. 2i le aplicramos esta varia!le local#osition a un transform sin padre, dicho transform se movera en el espacio glo!al, tal como si le hu!iramos aplicado position y no local#osition.

11. CLASE TRANS%ORM (II)

e+lerAngles: var euler*ngles : "ector#

1sta varia!le indica la rotaci"n del transform en grados. 2e corresponde plenamente con los valores que aparecen en el apartado rotation de cada transform en el inspector. /os valores de esta varia!le vienen dados, al igual que los de position, en formato >ector7. /o que sucede es que un valor de -[E,E,E. referido a la posici"n implica que nuestro transform se desplace [E unidades a la derecha, mientras que los mismos valores relativos a la rotaci"n implicaran que nuestro transform gire [E grados -el equivalente a un cuarto de vuelta. so!re el eje I. Al igual que con la varia!le position, eulerAngles nos permite consultar individualmente la rotaci"n de nuestro transform so!re un determinado eje. #ero si lo que queremos no es consultar sino cam!iar la rotaci"n, de!eremos indicar los tres valores va un >ector7, y %nity los convertir entonces en los valores que l usa internamente. #orque $esto no s si lo he dicho antes$ %nity tra!aja internamente con Guaterniones, por motivos de rendimiento y e(actitud, mientras que a los humanos nos resulta ms sencillo hacerlo con grados 1uler, as que en la prctica esisten unos <atri!utos de traducci"n< que nos permite pasar de quaterniones a grados y viceversa, a fin de que hom!res y mquina sigan tra!ajando con los elementos que mejor se adapten a sus capacidades. Al igual que con position, e(iste una varia!le eulerAngles para funcionar con valores glo!ales -la que estamos estudiando. y otra local1ulerAngles que tra!aja con valores locales -dependientes del padre del transform que rota. A esta varia!le s"lo podemos asignarle valores e(actos, no de incremento, ya que fallara pasados los 7TE\. #ara incrementar una rotaci"n de esta forma, tenemos que usar la funci"n :ransform.rotate. %semos un ejemplo muy simple. Antes arrastremos nuestro cu!o en la jerarqua fuera de la cpsula, para desemparentarlo. , rehacemos por ensima ve' nuestro script -que de!era continua vinculado al cu!o. transform.eulerAngles D >ector7-TE,E,E.C

#odis ver que nuestro cu!o ha girado un TE grados so!re el eje I, entendido ste como un alam!re invisi!le que cru'a de manera hori'ontal la escena -por decirlo de alguna manera. ?omo colof"n, aadir que %nity automticamente convierte los angulos 1uler que le pasamos al transform en los valores usados para la rotaci"n almacenada en :ransform.rotation.

localE+lerAngles: var local6uler*ngles : "ector#

Aqu no de!eramos necesitar grandes e(plicaciones+ local1ulerAngles se refiere a la rotaci"n en grados de un transform con relaci"n a la que tiene el transform del cual depende en una relaci"n hijo;padre. Al igual que con la varia!le anterior, %nity automticamente convierte los angulos 1uler en los valores usados para la rotaci"n almacenada en :ransform.local&otation.

rotation: var rotation : $uaternion

1s la varia!le que contiene la rotaci"n del transform en el mundo glo!al almacenada en quaterniones.

?omo ya hemos dicho, %nity almacena internamente todas las rotaciones en quaterniones, lo cual no quiere decir que nosotros tengamos que tra!ajar directamente con ellos. #or norma general, o !ien tra!ajaremos con grados 1uler que luego se convertirn implcita o e(plicitamente en quaterniones, o !ien a lo sumo usaremos alguna funci"n que nos permita encapsular las operaciones con quaterniones.

localRotation:

var local7otation : $uaternion

@!viamente, esta varia!le indica la rotaci"n en quaterniones de un transform relativa a la rotaci"n de su padre

right# +! % (or.ard: var right : "ector# var u! : "ector# var for)ard : "ector#

1stas varia!les hacen referencia respectivamente al eje I-derecha;i'quierda., , -arri!a;a!ajo. y J-delante;detrs. de las coordenadas glo!ales del transform. 9o las hemos de confundir con las varia!les del mismo nom!re de la estructura >ector7. As, >ector7.up es un atajo que equivale a >ector7-E,5,E., esto es, implica un movimiento de una unidad hacia arri!a. 1n cam!io, transform.up meramente hace referencia al eje arri!a;a!ajo, pero no implica movimiento. #ara mover un transform por esta va tendramos que hacer algo como esto+ 1n %nity eliminamos el script que tenemos vinculado a nuestro cu!o. 1n #royecto a!rimos nuestro script y tecleamos+ var un@!jeto + Fame@!jectC un@!jeto.transform.position D transform.rightZ5EC un@!jeto.transform.eulerAngles D transform.upZXKC

Arrastramos nuestro script tras salvarlo a #orta2cripts en la =erarqua y con #ortascripts seleccionado arrastramos el cu!o a la varia!le e(puesta. #lay. 1fectivamente, el cu!o se despla'a 5E unidades a la derecha y XK grados so!re el eje ,.

12. CLASE TRANS%ORM (III)

>amos a e(plicar las varia!les que nos quedan en esta lecci"n.

localScale: var localScale : "ector#

?omo su nom!re indica, es una varia!le de tipo >ector7 que permite consultar o esta!lecer la escala de un transform en relaci"n con la de su padre. @!viamente, un transform con esta varia!le en E,E,E tendr la misma escala que su padre.

!arent: var !arent : Transform

)ace referencia al padre del transform -que es o!viamente otro transform., y a travs de esta varia!le se puede consultar y;o cam!iar dicho padre. >eamos primero de qu forma podemos consultar valores relativos al padre de nuestro transform+ 9os vamos a %nity, arrastramos en la =erarqua el cu!o dentro de la cpsula, y a #orta2cripts le !orramos el script para que no nos d errores. 1n #royecto le damos do!le clic8 a mi#rimer2cript y escri!imos lo que sigue+ e!ug./og-transform.parent.game@!ject.name.C

Arrastramos tras salvar el script dentro del cu!o -que est dentro de la cpsula.. #lay. Aparece el nom!re de la cpsula,que es lo que pretendamos. Mijaros c"mo a travs del operador punto le decimos al %nity -leyendo de derecha a i'quierda. que !usque el nom!re del gameo!ject al que pertenece el transform que es el padre del transform del gameo!ject que hace la consulta -al que va vinculado el script. y lo imprima en pantalla.

>amos ahora a darle un padre nuevo a nuestro cu!o. A!rimos el script y, sin !orrarla, despla'amos la declaraci"n que ha!amos escrito un par de renglones hacia a!ajo, y encima escri!imos lo siguiente+ var nuevo#adre + :ransformC transform.parent D nuevo#adreC e!ug./og-transform.parent.game@!ject.name.C;;1sto ya lo tenamos escrito

2alvamos, y seleccionamos el cu!o para que en el inspector quede e(puesta la varia!le nuevo#adre. Arrastramos hasta ella la cmara principal desde la jerarqua y le damos al play. 9uestro cu!o ha cam!iado de padre. #ensemos, llegados a este punto, que nuestro transform hijo tiene una posici"n, rotaci"n y escala relativa con respecto a su padre. 2i cam!iamos su padre, stas o!viamente cam!iarn.

root: var root : Transform

1sta varia!le hace referencia al transform ms alto de la jerarqua, por lo que guarda muchas similitudes con parent, pero referida al ]parent de los parent^ del que depende nuestro transform. 2i ste tiene un padre sin padre, el resultado equivaldr a parent. 2i su padre tiene un padre que tiene un padre que tiene un padre, la varia!le ir escalando hasta llegar al 3ltimo padre y devolver su valor -o nos permitir modificar dicho valor.. #ara el caso de que el o!jeto que invoca esta varia!le no tenga padre, lo que se devuelve no es null, sino el propio transform que la invoca.

childCo+nt: var child8ount : int

1s meramente una varia!le de tipo int que indica el n3mero de hijos que tiene un transform.

loss%Scale: var loss%Scale : "ector#

1s esta una varia!le de tipo >ector7 que representa la escala glo!al del o!jeto. 1s una varia!le de s"lo lectura, por lo que o!viamente no podemos modificar la escala glo!al -la local ya vimos que s con local2cale. asignando valores a esta varia!le.

, con esto aca!amos las varia!les y nos lan'amos a por las funciones, que tam!in son unas cuantas.

13. CLASE TRANS%ORM (IV)


FUNCIONES:

Translate: (+nction Translate 0translation : Vector1# relati2eTo : S!ace $ S!ace3Sel(4 : 2oid

1sta funci"n nos permite mover el transform en la direcci"n y distancia indicados en el parmetro de tipo >ector7 traslation. 1l segundo parmetro nos permite decidir si el transform se mover seg3n sus propias coordenadas -locales. o lo har en !ase al espacio glo!al. #or defecto, si no indicamos el segundo parmetro, %nity entiende que el transform se mover seg3n sus propias coordenadas -2pace.2elf.. esarrollemos esto con un ejemplo+ #ara empe'ar, desemparentamos nuestro cu!o respecto de la cpsula, arrastrndolo a un espacio vaco de la jerarqua. Acto seguido, con el cu!o seleccionado, en el inspector le asignamos a la coordenada , de rotaci"n un valor de 7K. A!rimos el script que tenemos asignado al cu!o y tecleamos+ transform.:ranslate->ector7.for4ard Z K.C

2alvamos y presionamos play. 1l cu!o avan'a cinco unidades en su eje ,, y recalcamos lo de <su< eje, ya que al no aadirle un segundo parmetro que diga lo contrario, se mueve seg3n sus coordenadas locales. #ara ver la diferencia, aadamos como segundo parmetro a la funci"n la varia!le _orld de la enumeraci"n 2pace, para que sustituya al parmetro por defecto 2pace.2elf+ transform.:ranslate->ector7.for4ard Z K, 2pace._orld.C

function Translate (/ : float % : float 0 : float relativeTo : S!ace & S!ace(Self) : void 1(iste un segundo prototipo para la funci"n :ranslate. ?omo se puede compro!ar, se diferencia del primero en que en lugar de pasar como parmetro para esta!lecer la direcci"n y longitud del movimiento un >ector7, se pasa cada eje como un float independiente.

function Translate (translation : "ector# relativeTo : Transform) : void function Translate (/ : float % : float 0 : float relativeTo : Transform) : void 1stos dos prototipos varan de los anteriores en el segundo parmetro, que ya no versa so!re si el movimiento se har tomando en cuenta las coordenadas locales del o!jeto que se mueve o las glo!ales de la escena. 1n cam!io, aqu el movimiento de nuestro transform vendr fijado por otro transform. e esta manera, nos moveremos de acuerdo con las coordenadas locales de ese segundo o!jeto al que hacemos referencia. 2i por ejemplo el parmetro relative:o es una cmara, la derecha del traslation no es la derecha local de nuestro transform, o la derecha glo!al, sino la derecha de la cmara. #or ejemplo+

:ecleamos lo siguiente en nuestro script transform.:ranslate->ector7.right Z K.C

1sto har que nuestro cu!o se mueva cinco unidades a s+ derecha. , ahora modificamos el script para que quede as+ var mi?amara + :ransformC transform.:ranslate->ector7.right Z K, mi?amara.C

Arrastramos la cmara principal hasta la varia!le mi?amara. e nuevo al play. Ahora el cu!o se mueve cinco unidades a la derecha de la cmara. ?omo 3ltimo apundo hemos de aadir que si relative:o es nulo, las coordenadas del movimiento pasarn a ser las glo!ales.

Rotate: function 7otate (euler*ngles : "ector# relativeTo : S!ace & S!ace(Self) : void

1sta funci"n permite rotar un transform. Acepta como parmetro un >ector7 con los grados de rotaci"n en ngulos 1uler. #or defecto, al igual que sucediera con la funci"n translate, el transform rota so!re sus coordenadas locales, pudiendo hacerlo seg3n las coordenadas glo!ales si se lo indicamos con 2pace._orld como segundo parmetro. >eamos un ejemplo. &ehagamos nuestro script con el siguiente contenido+ function %pdate-. O transform.&otate->ector7.right Z 6K Z :ime.delta:ime.C transform.&otate->ector7.up Z 6E Z :ime.delta:ime, 2pace._orld.C P

Al darle al play, o!servaremos que nuestro cu!o rota so!re su eje I a ra'"n de 6K grados por segundo mientras a la ve' gira so!re el eje , glo!al a ra'"n de 6E grados por minuto. 1s de sealar que am!as instrucciones se encuentran contenidas dentro de la funci"n %pdate. 1sta funci"n, que en su momento estudiaremos con la de!ida profundidad, es llamada cada frame por nuestro ordenador -el framerate de cada ordenador vara., de tal manera que el movimiento es contnuo, pues los valores de rotaci"n de nuestro cu!o son actuali'ados constantemente. #recisamente porque el framerate de cada ordenador es distinto, y para evitar que en funci"n de cada #? los o!jetos se movieran ms o menos deprisa -lo que tendra indesea!les consecuencias, so!re todo en juegos en lnea multijugador., se suele utili'ar la varia!le de la clase :ime :ime.delta:ime. :ime.delta:ime lo que consigue es transformar la unidad de frecuencia de cualquier tipo de movimiento de frames a segundos. 2i por ejemplo en el 3ltimo script no hu!iramos usado estas varia!les de tiempo, el cu!o girara 6K y 6E grados cada frame, quedando al al!ur de cada ordenador la frecuencia real que eso supondra. Al multiplicarlo por :ime.delta:ime las rotaciones dependern del tiempo y en consecuencia se producirn con la misma cadencia en cualquier ordenador.

function 7otate (/*ngle : float %*ngle : float 0*ngle : float relativeTo : S!ace & S!ace(Self) : void 1n esta versi"n de la funci"n, la 3nica diferencia es que se sustituye el >ector7 por tres floats, en los cuales se consignarn igualmente los grados de rotaci"n.

function 7otate (a/is : "ector# angle : float relativeTo : S!ace & S!ace(Self) : void

/a variante que nos ofrece este tercer prototipo es que por un lado se indica en el primer parmetro so!re qu eje queremos que rote el transform, y en un segundo parmetro de tipo float le hemos de indicar el n3mero de grados ha de rotar.

14. CLASE TRANS%ORM (V)

RotateAro+nd: function 7otate*round (!oint : "ector# a/is : "ector# angle : float) : void

1sta funci"n nos permite que nuestro transform rote alrededor de un punto -u o!jeto situado en ese punto., como si or!itara. 1l parmetro point sera el punto, descrito por un >ector7, alrededor del cual queremos hacer girar nuestro transform. A(is nos servir para indicar so!re qu eje queremos girar, y angle el n3mero de grados por frame -si est dentro de la funci"n update. o por segundo -si implicamos la varia!le de clase :ime.delta:ime. que queremos que gire. @!viamente, aqu estamos variando tanto la rotaci"n como la posici"n de nuestro transform. si por ejemplo quiriramos que nuestro cu!o girara so!re su eje , alrededor del centro e(acto del espacio glo!al, a ra'"n de 6E grados por segundo, escri!iramos este script+ function %pdate-. O transform.&otateAround ->ector7.'ero, >ector7.up, 6E Z :ime.delta:ime.C P

ado que el cu!o se halla!a ya en las coordenadas glo!ales E,E,E el script anterior lo 3nico que consigue es que el cu!o pare'ca girar so!re s mismo. >amos a hace lo siguiente+ colocamos en el inspector a nuestro cu!o en position.( D $5, y volvemos a darle al play. , vemos ya ms claramente c"mo or!ita alrededor del punto dado, cam!iando simultneamente de posici"n y de rotaci"n. #odemos hacer tam!in con esta funci"n que un o!jeto or!ite alrededor de otro. 1scri!imos+ var centro eFravedad+ :ransformC function %pdate-. O transform.&otateAround -centro eFravedad.position, >ector7.up, 6E Z :ime.delta:ime.C P

Acto seguido, arrastramos el o!jeto so!re el que queremos que or!ite nuestro cu!o, en este caso la cpsula. /e damos al play y compro!amos. @!servemos que aunque arrastramos un gameo!ject, lo que est esperando nuestro scrips es un transform. /o que sucede es que $tal como vimos en las primeras lecciones$ todos los componentes de nuestro gameo!ject comparten

nom!re, de tal manera que cuando en casos como este %nity detecta que uno de los componentes del gameo!ject que le estamos arrastrando tiene el nom!re y el tipo del que est esperando para cumplimentar una varia!le, automticamente selecciona $en este caso$ el transform hom"nimo y no el gameo!ject. 1se transform, no o!stante, no es del tipo >ector7 que espera nuestra funci"n. 2 que lo es la varia!le position del mismo, que adems contiene las coordenadas glo!ales del transform so!re el que queremos or!itar. #odis pro!ar a sustituir en el segundo parmetro >ector7.up por >ector7.right -o >ector7.for4ard., y compro!ar qu es lo que sucede.

Loo5At: function -oo9*t (target : Transform )orld:! : "ector# & "ector#(u!) : void

1l nom!re de esta funci"n se podra traducir al castellano como <mira a<, y es e(actamente eso lo que hace+ &otar nuestro transform hacia un o!jetivo $parmetro target$ que es asimismo de tipo transform -y no >ector7, como en el caso de la funci"n anterior.. 1sa rotaci"n se efect3a so!re un eje glo!al, y por defecto ste ser el eje ,. 1llo implicar que nuestro transform, si no le indicamos lo contrario, girar hacia la derecha y la i'quierda <mirando< al transform que hayamos designado como o!jetivo. )uelga decir que esta funci"n se usa mucho para cmaras, cuando pretendemos que stas sigan en todo momento a un determinado personaje. 1s importante avisar de que para que el transform gire so!re el eje que le indiquemos, ha de estar totalmente perpendicular a dicho eje glo!al. >amos a la prctica. 1n el #royecto, colocamos el rat"n so!re la carpeta *is 2cripts y le damos al !ot"n derechoDLcreateDLjavascript. Al nuevo script lo renom!ramos como *i2egundo2cript y le damos do!le clic8 para se se nos a!ra el editor. espla'amos un poco hacia a!ajo la funci"n %pdate, y la dejamos como sigue+ var sigueme + :ransformC function %pdate -. O transform./oo8At-sigueme.C P

2alvamos, y la arrastramos hasta nuestra cmara en la jerarqua. 2eleccionamos entonces la cmara y arrastramos ahora hasta la varia!le sigueme nuestro cu!o. #reviamente a darle al play nos aseguramos de que el otro script -*i#rimer2cript. que tenemos vinculado al cu!o, contenga lo siguiente+ var centro eFravedad+ :ransformC function %pdate-. O transform.&otateAround -centro eFravedad.position, >ector7.up, 6E Z :ime.delta:ime.C P

, ahora s, ya podemos darle al play y perseguir a nuestro cu!o. function -oo9*t ()orld5osition : "ector# )orld:! : "ector# & "ector#(u!) : void 1ste segundo prototipo se diferencia del primero en que el o!jetivo que ha de seguir nuestro transform no es otro transform, sino un >ector7. 1sto tiene sentido, siguiendo con el ejemplo de la cmara, si quisiramos que sta enfocara un punto concreto de la escena -en coordenadas glo!ales. #or ejemplo, si queremos que una cmara enfoque al centro de la escena, le vinculamos este script+ transform./oo8At->ector7.'ero.C

@tra posi!ilidad que nos permite esta funci"n es que sea nuestro jugador, desde su teclado, quien se encargue de decidir d"nde ha de enfocar la cmara. #ara ello tendremos que recurrir a una clase que a3n no hemos visto, la clase input. A!rimos el script *i2egundo2cript, y tecleamos lo que sigue+ function %pdate -. O transform./oo8At->ector7-0nput.FetA(is-<)ori'ontal<. Z 5E.E,E,E..C P

/e damos al play y movemos la cmara con las flechas de despla'amiento hori'ontal. Gui's notemos que el resultado es un poco !asto, pero meramente quera que tuvirais una idea de las utilidades de esta funci"n. :am!in podramos controlar la cmara desde el rat"n y no desde el teclado. >eremos todo esto en profundidad cuando estudiemos la clase input. 9os vemos en el siguiente captulo. 5K. ?/A21 :&A92M@&* ->0. Trans(ormDirection: function TransformDirection (direction : "ector#) : "ector#

1sta funci"n toma como 3nico parmetro la direcci"n local de un transform almacenada en un >ector7 y la convierte en direcci"n glo!al, devolvindola en otro >ector7. /a utilidad de esta funci"n puede resultar un poco confusa al principio. #ensemos, para intentar apro(imarnos al concepto, que quisiramos hacer nuestra propia versi"n del M0MA 6E55. *odelamos un campo de fut!ol y, para darle ms realismo y emoci"n al juego, colocamos varias cmaras en los laterales del campo, cmaras que mediante /oo8At iran siguiendo los lances del juego. 1l pro!lema que nos encontraramos es que cuando *essi -por poner un caso. est avan'ando hacia delante -en las coordenadas glo!ales., en cam!io en nuestra cmara lateral pareciera que lo est haciento $por ejemplo$ hacia la i'quierda. , en consecuencia, cuando intentamos que nuestro defensa lo ataje movindolo hacia atrs -seg3n la perspectiva que nos da la cmara lateral. veremos consternados que el defensa en lugar de retroceder se despla'a hacia la derecha. 1sto no nos pasara si, gracias a esta funci"n, convertimos la coordenada <hacia detrs< de nuestra cmara en su equivalente en coordenadas glo!ales. 2i esa funci"n se la aplicamos a todas las cmaras, no tendremos que estar pensando <@jo, que esta cmara est en el gol norte, por lo que si me !aso en ella cuando haga un movimiento, he de recordar que arri!a es a!ajo y viceversa y la derecha es la i'quierda y !la, !la, !la<. >emoslo en un ejemplo. 1n %nity !orramos el script *i2egundo2cript de la cmara. ?olocamos en el inspector a nuestro cu!o en las coordenadas E.E.E. con una rotaci"n igualmente de E,E,E. Asimismo, la cmara de!era estar en las coordenadas de posici"n E,5,$K con los tres ejes de rotaci"n a E. A!rimos *i#rimer2cript. :ecleamos esto+ var mi?amara + :ransformC var esta1s*i erecha + >ector7C esta1s*i erecha D mi?amara.:ransform irection->ector7.right.C transform.:ranslate-esta1s*i erecha Z 7.C Arrastramos la cmara a mi?amara. /e damos al play. 1l cu!o se mover 5E unidades a la derecha. #ero, Ra la derecha de quinS. 2i o!servamos, la derecha del cu!o es tam!in la derecha de la cmara. #ara averiguarlo, vamos a recolocar la cmara en estas coordenadas+ #osition+ $5E, 5, $E.K

&otation+ E, [E, E , de nuevo le damos al play. @!viamente, el cu!o se mueve a la derecha de la cmara. >isto desde la ventana game, coincidir ahora <nuestra< derecha -entendiendo como tal la que nos muestra la pantalla. con el sentido el movimiento.

1l script no necesita mucha e(plicaci"n. 0niciali'amos una varia!le con el transform de la cmara que hemos arrastrado. /a derecha de esa cmara la almacenamos en una varia!le de tipo >ector7, la cual luego pasamos como parmetro a nuestra funci"n :ransform irection para que nos convierta la derecha de nuestra cmara en la derecha de las coordenadas glo!ales. A partir de ah, todo lo que le suceda a la derecha de nuestra cmara -por as decirlo. le estar pasando a la derecha del mundo. function TransformDirection (/ : float % : float 0 : float) : "ector# 1s la misma funci"n, pero aplicando como parmetros 7 floats para cada eje en lugar de un >ector7.

In2erseTrans(ormDirection: function InverseTransformDirection (direction : "ector#) : "ector# o !ien function InverseTransformDirection (/ : float % : float 0 : float) : "ector#

2e trata o!viamente de la funci"n inversa a la anterior, y por consiguiente transforma una direcci"n glo!al en direcci"n local. >eamos un ejemplo+ evolvemos antes que nada a nuestra cmara a su lugar y rotaci"n originales+ #osition+ E,5,$K &otation+ E,E,E /a posici"n y rotaci"n de nuestro cu!o, por su parte, est totalmente a E. A!rimos *i#rimer2cipt, y tecleamos+ var esta1s/a erecha el*undo + >ector7C esta1s/a erecha el*undo D transform.0nverse:ransform irection->ector7.right.C transform.:ranslate-esta1s/a erecha el*undo Z 6.C

?omo vemos, declaramos una varia!le de tipo >ector7 que luego iniciali'amos de la siguiente forma+ le pasamos a la funci"n 0nverse:ransform irection el parmetro >ector7.right, que en esta funci"n representa la derecha en coordenadas glo!ales -no la derecha de ning3n transform.. 1sa derecha del mundo, glo!al, es <traducida< por la funci"n en una coordenada local suscepti!le de usar por cualquier transform y es asignada,como decamos, a nuestra varia!le esta1s/a erecha el*undo. icha varia!le, por 3ltimo, es pasada como parmetro de movimiento al transform del gameo!ject que tiene vinculado el script -en este caso el cu!o.. R/a pro!amosS 1l cu!o se despla'a a la derecha. #ero, para sa!er si la derecha es la derecha del cu!o o la derecha glo!al, podemos en el inspector darle un valor al rotation., del cu!o de XK grados, por ejemplo. , pro!amos de nuevo.

efinitivamente, el cu!o se mueve ahora siguiendo el eje I glo!al, y no el suyo local.

1!. CLASE TRANS%ORM ( VII)


Trans(orm/oint: function Transform5oint (!osition : "ector#) : "ector# function Transform5oint (/ : float % : float 0 : float) : "ector#

A diferencia de :ransform irection, lo que esta funci"n transforma de local en glo!al es la posici"n y no la direcci"n. 1sto es, esta funci"n no versa so!re si un transform se despla'a a su derecha o a la derecha de las coordenadas glo!ales, sino de si las coordenadas en que se encuentra el transform son glo!ales -respecto al mundo. o locales -respecto al padre de dicho transform.. ?on esto entendido, como decimos, esta funci"n acepta como parmetro las coordenadas locales de un transform -su u!icaci"n respecto de la de su padre. y devuelve dichas coordenadas traducidas a coordenadas glo!ales.

/o veremos ms claron con un ejemplo. ?on el cu!o en position E,E,E y rotation en E,E,E -si no,no funcionar. arrastramos el cu!o dentro de la cpsula en la =erarqua, para convertir a cu!o en hijo de la cpsula. 2i seleccionamos el cu!o, vemos en el inspector que sus coordenadas de posici"n han pasado a ser locales respecto de su padre. A!rimos *i#rimer2cript -que de!era seguir siendo parte del cu!o. y escri!imos el siguiente script+ var coordenadas/ocales + >ector7C var coordenadasFlo!ales+ >ector7C var coordenadas:ransformadas+ >ector7C coordenadas/ocales D transform.local#ositionC coordenadasFlo!ales D transform.positionC coordenadas:ransformadas D transform.position D transform.:ransform#oint-transform.local#osition.C e!ug./og-<1l cu!o tiene las coordenadas locales < B coordenadas/ocales.:o2tring-. B < las glo!ales < B coordenadasFlo!ales.:o2tring-. B < y las transformadas < B coordenadas:ransformadas.:o2tring-..C

1l ejemplo parece ms complicado de lo que es. eclaramos tres varia!les de tipo >ector7 para que contengan las tres coordenadas que imprimiremos para nuestro cu!o -los nom!res de las varia!les son lo suficientemente e(plicativos.. Acto seguido iniciali'amos las dos primeras varia!les con la posici"n glo!al y local del transform, y la tercera con las coordenadas que tendr el transform cuando convirtamos sus coordinadas locales -respecto de la cpsula. en glo!ales. 2alvamos y le damos al play. @!servamos que por un lado el cu!o se despla'a en direcci"n y distancia opuesta al cilindro, ya que el $7,$X,$6 que constituan sus coordenadas locales ahora ha pasado a ser su posici"n en coordenadas glo!ales.

In2erseTrans(orm/oint: function InverseTransform5oint (!osition : "ector#) : "ector# function InverseTransform5oint (/ : float % : float 0 : float) : "ector#

Munci"n inversa a la precedente, que por tanto transforma la posici"n de un transform dado del espacio glo!al al espacio local.

DetachChildren: function Detach8hildren () : void

1s una funci"n muy sencilla que sirve para desparentar los hijos. #ara pro!arla de!emos eliminar el script vinculado al cu!o, y posteriormente hacer do!le clic8 en *i#rimer2cript en el #royecto para teclear lo siguiente+ transform. etach?hildren-.C

2alvamos y lo arrastramos a la cpsula, que es el transform que tiene hijos. /e damos al play y o!servaremos c"mo en la =erarqua el cu!o deja de aparecer como hijo de la cpsula. 1sta funci"n es 3til, entre otras cosas, cuando por alguna ra'"n queramos destruir al o!jeto padre sin destruir a sus hijos+ transform. etach?hildren-.C estroy-game@!ject.C

Find: function Find (name : String) : Transform

?on esta funci"n podemos !uscar por su nom!re $y en su caso acceder$ a un transform hijo de nuestro transform. /a funci"n devuelve dicho transform hijo, si lo encuentra. 2i no lo encuentra, retorna null. 2i tenemos que !uscar a varios niveles, esto es, hijos de los hijos de nuestros hijos, podemos utili'ar un slash o !arra inclinada -];^. para recrear la jerarqua donde queremos !uscar -p ej. <?uerpo;Bra'o;*ano;0ndice<. ado que de!eramos tener el cu!o a3n dentro de la cpsula, y *i#rimer2cript vinculado a sta, lo aprovecharemos para reali'ar un ejemplo+ var aqui*i)ijo + :ransformC function %pdate-. O aqui*i)ijo D transform.Mind-<?u!o<.C aqui*i)ijo.&otate-:ime.delta:imeZTE, E, E.C P

?omo podemos compro!ar al darle al play, la funci"n Mind encuentra un transform hijo llamado <?u!o< -recordemos que, por un lado hemos de suministrarle un string, esto es, no nos de!emos olvidar de las comillas, y por otro lado que todos los componentes de un gameo!ject comparten por defecto el mismo nom!re que ste, as que el transform del ?u!o se llama ?u!o., y almacena ese transform que encuentra dentro de la varia!le aqui*i)ijo. A partir de ah, podemos utili'ar esa varia!le como si fuera un alias del propio transform.

IsChildO(: function Is8hildOf (!arent : Transform) : boolean

1sta funci"n casi no requiere e(plicaci"n. evuelve true si el transform que hace la pregunta es hijo, <nieto< o incluso idntico al transform parent que pasamos como parmetro. 1n otro caso, devuelve false.

, con esto aca!amos la clase transform, que como deca al inicio es una de las die' clases ms importantes de la A#0 de %nity.

1". CLASE RIGIDBODY (I)

9os disponemos a estudiar otra de las clases vitales para entender el funcionamiento de %nity. 1s raro en juego en el que no interviene de alguna manera la fsica -un enemigo se cae, un personaje salta, y coche choca contra un muro.... /a clase &igid!ody controla la posici"n de un o!jeto a travs de simulaci"n de fsica. 1l componente &igid!ody, al ser aadido a un gameo!ject, toma el control so!re la posici"n de un o!jeto, haciendo que caiga !ajo la influencia de la gravedad, y puede calcular c"mo los o!jetos respondern a las colisiones. >amos a inspeccionar unas cosas en %nity+ antes que nada, si estis siguiendo por orden estas lecciones tendris -como yo. emparentado el cu!o dentro de la cpsula, as que lo arrastramos fuera para desemparentarlo. /uego, con el cu!o seleccionado, echamos un vista'o al inspector. >emos en l diferentes apartados -su transform, su malla, un collider y elementos de renderi'ado. pero no un rigid!ody. /o mismo nos pasara si e(aminamos la cpsula. Am!os o!jetos, por lo tanto, no estn sometidos a leyes fsicas, y en consecuencia es como si carecieran de masa y por ende fueran ajenos a la gravedad. >amos a regalarles un rigid!ody a nuestros o!jetos. #ara hacer eso nos vamos $con uno de los o!tetos seleccionado$ al men3 superior, y le damos a ?omponentDL#hysicsDL&igid!ody. 1l gameo!ject que tenamos selecionado tiene ahora un componente nuevo+

)acemos lo mismo con el otro gameo!ject. Acto seguido, en la ventana 1scena pulsamos la I de nuestro gi'mo,para tener una visi"n de los o!jetos desde el eje hori'ontal, y compro!ar mejor lo que pasar ahora. /e damos al play... y los o!jetos caen, porque ya no son inmunes a la gravedad. /o que procede ahora, para evitar que nuestros o!jetos a!andonen la escena a la primera de cam!io, es colocar un suelo. >amos a ello. Antes que nada, vamos a eliminar a nuestra vieja amiga la cpsula -conocida por los ms veteranos por @rigen.. /a ra'"n es que por su forma especfica no es demasiado esta!le para nuestros ejemplos una ve' se ve afectada por la gravedad. As que adi"s, cpsula. , como a rey muerto, rey puesto, nos vamos al men3 y le damos a Fame@!jectDL?reate otherDL2phere. /a renom!ramos como <1sfera<. A continuaci"n vamos a colocar a nuestros dos o!jetos a ras de suelo -antes no importa!a que estuvieran flotando por ah, pero ahora no querremos empe'ar el juego con un o!jeto pegndose un torta'o contra el suelo.. ?olocamos, como decimos, nuestros o!jetos en las siguientes coordenadas de posici"n -las rotaciones de!en estar a E.+ ?u!o+ E,E,E. 1sfera+ 6,E,6. 9os vamos ahora al men3DLFameo!jectDL?reate @therDL#lane. /o renom!ramos antes que nada como <2uelo<. /uego colocamos nuestra ventana de escena en vista superior -clic8 en eje , del gi'mo., y para aca!ar, en la coordenada , de su transform.position escri!imos $E.K. 1sto 3ltimo supongo que merece una e(plicaci"n. >eamos, tanto el cu!o como la esfera tienen una altura de una unidad y su origen -el E,E,E. de dichos o!jetos se halla en su centro geomtrico. 1sto quiere decir que cuando un cu!o est en el valor E de su eje ,, la mitad del cu!o -E,K. se halla por de!ajo del nivel E -que es donde hemos colocado el suelo.. 1n definitiva, si tanto el cu!o como la esfera y el suelo los dejramos con sus respectivos ejes , a cero, los dos primeros apareceran semienterrados en el tercero. #ara evitarlo, o !ien levantamos todos los o!jetos o !ien !ajamos el suelo, que es lo que hemos hecho. mosle al play. @!servamos que los o!jetos ya no se caen, aunque a decir verdad y siendo todos los elementos de

nuestra escena del mismo color, qui's nos interesara ponerle a nuestro suelo un color que los hiciera resaltar. ?on el mouse situado so!re la carpeta *is 2cripts, pulsamos el !ot"n derecho y creamos otro script -javascript, recordemos.. /o llamaremos ?olor2uelo, y dice as+ function 2tart-. O renderer.material.colorD?olor.redC P

/a funci"n 2tart es llamada por %nity, como su nom!re indica, cuando se inicia el juego. 2"lo es llamada una ve', a diferencia de %pdate, y en este caso nos interesa que sea as ya que vamos a dejar el color de nuestro suelo fijo durante todo el juego. 2alvamos y arrastramos el script a 2uelo. /e damos al play.

, voil, el suelo se nos vuelve de color rojo y los o!jetos contrastan algo ms. A3n y todo, la escena contin3a un poco oscura, as que mejor iluminarla un poco, RnoS 0ntroducimos en la escena desde el men3 gameo!ject una lu' direccional, que renom!raremos como </u'< y u!icaremos;rotaremos en las siguientes coordenadas+ #osici"n+ $K,5K,$5E &otaci"n+ 6E,E,E 2i le damos al play, de!eramos ver algo parecido a esto+

, ms o menos con esto tendramos ya la escena <preparada< para empe'ar a tra!ajar con la clase &igid!ody.

1#. CLASE RIGIDBODY (II)

e un mero vista'o a este grfico podris sin duda deducir dos cosas+ 5.$ /a clase &igid!ody es <hermana< de la clase :ransform. 1stn al mismo nivel y heredan de las mismas clases. 6.$ 9os va a ocupar un !uen n3mero de lecciones estudiarla. #ero el esfuer'o veris que merece la pena, ya que dominando las clases :ransform, &igid!ody -y ?ollider con sus dos clases hijas, que estudiaremos tras &igid!ody. tendremos controlado en gran parte el tema del movimiento y reacci"n ante el movimiento ajeno de nuestros gameo!jects. , sin ms dilaci"n, vamos all. VARIABLES: 2elocit%: "ar velocit% : "ector#

&epresenta a travs de un vector la velocidad del rigid!ody. 9o es aconseja!le en la mayora de casos modificar esta varia!le directamente, ya que derivara en un comportamiento poco realista -no ha!ra una transici"n entre la velocidad -o incluso inactividad. anterior y la nueva velocidad. 2 est

justificado en cam!io su uso para aquellos cam!ios de velocidad que provienen de un impulso, como por ejemplo un salto. function Mi(ed%pdate -. O if -0nput.FetButton o4n -<=ump<.. O rigid!ody.velocity D >ector7-E,T,E.C P P

:ecleamos este script en *i#rimer2cript, lo salvamos y lo arrastramos al cu!o. )ay varias cosas del mismo que necesitarn una e(plicaci"n. #ara empe'ar, vemos que se est usando una funci"n llamada Mi(ed%pdate. 1sta funci"n es parecida a la funci"n %pdate, de la que ya ha!amos ha!lado, pero a diferencia de sta, Mi(ed%pdate es llamada -actuali'ada. a intervalos regulares -fijos.. #or lo tanto, as como en la funci"n %pdate la actuali'aci"n depende del framerate de cada ordenador, en la funci"n Mi(ed%pdate la actuali'aci"n se produce en intervalos fijos, iguales para todos los ordenadores. #or esa ra'"n, cuando tratamos con cuestiones relacionadas con la fsica -y toda la clase &igid!ody est relacionada con la fsica. ha!remos de usar la funci"n Mi(ed%pdate y no la funci"n %pdate -salvo que queramos que las cadas, colisiones y velocidad de los o!jetos de nuestro juego sean diferentes en funci"n del ordenador con el que juguemos o que, yendo a3n ms all, en un juego online multijugador el personaje de cada user vaya a una velocidad distinta, por ejemplo.. /o segundo nuevo del script es una referencia a la clase input. /a clase input -otra de las clases que ocupan el top ten de importancia en %nity. es la que controla los eventos, esto es, qu tiene que hacer el usuario para disparar, qu tecla hace qu cosa, qu tipo de colisiones provocan que pase otra cosa distinta, etc. 1n este caso, 0nput.FetButtom o4n-string. dispara un evento cuando el usuario pulsa la tecla que le pasamos a la funci"n como un string. 1n nuestro 2cript le pasamos el string <=ump<, que por defecto se corresponde a la !arra espaciadora. R, qu sucede cuando le damos a la !arra espaciadoraS. #ues que al rigid!ody que en el captulo anterior le aadimos a nuestro cu!o le ser aumentada de golpe la velocidad en el vector , -arri!a;a!ajo.. #ara compro!arlo, dale al play y cuando el juego est corriendo presiona la !arra espaciadora.

ang+larVelocit%: "ar angular"elocit% : "ector#

>ector que representa la velocidad angular del rigid!ody. #or velocidad angular nos referimos a la velocidad de rotaci"n. Al igual que con velocity, en la mayora de casos no cam!iaremos la velocidad directamente, pues salvo casos en que precisamos un impulso s3!ito de la velocidad, no queda realista. #ara entender !ien la diferencia entre velocidad y velocidad angular, vamos a completar el script anterior, permitindonos aplicar una u otra velocidad, o incluso am!as a la par. *i#rimer2cript quedar as+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<=ump<.. O rigid!ody.velocity D >ector7-E,T,E.C P if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.angular>elocity D >ector7-`,E,E.C P P

?omo podemos o!servar, hemos aadido un segundo if de tal manera de que si el jugador en lugar de presionar la !arra espaciadora -jump. presiona cualquiera de las dos flechas hori'ontales de direcci"n del teclado, la velocidad que se aplique al cu!o ser velocidad angular. 2alvamos, le damos al play y pulsamos cualquiera de las flechas hori'ontales. #ro!a!lemente o!servaremos que el cu!o hace intenci"n de girarse, pero no tiene la fuer'a suficiente para hacerlo. 2i, en cam!io, pulsamos la !arra espaciadora y mientras el cu!o est en el aire presionamos la flecha hori'ontal, asistiremos seguramente a una !onita

pirueta de nuestro cu!o.

1$. CLASE RIGIDBODY (III)

drag: "ar drag : float

0ndica la resistencia al movimiento de un o!jeto y por lo tanto se usa para enlentecer dicho o!jeto. ?uando ms algo el valor, mayor resistencia. >emoslo aadiendo un tercer if a nuestro script, de tal forma que quede as+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<=ump<.. O rigid!ody.velocity D >ector7-E,T,E.C P if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.angular>elocity D >ector7-`,E,E.C P if -0nput.Fetaey o4n -<'<.. O rigid!ody.drag D 5EC P P

2alvamos. /a funci"n Fetaey o4n de la clase input dispara un evento cuando el user presiona una determinada tecla, en nuestro ejemplo la 'eta. /e damos al play y lan'amos al aire nuestro cu!o presionando la !arra espaciadora, y cuando est en el aire presionamos la '. @!servaremos c"mo los movimientos del cu!o se enlentecen. 2i a continuaci"n volvemos a presionar la !arra espaciadora o la flecha hori'ontal, compro!aremos que la resistencia al movimiento de nuestro cu!o es mucho mayor.

ang+larDrag: rigidbod%(angularDrag & .';

0ndica la resistencia angular del o!jeto. #uede ser usado para enlentecer la rotaci"n de un o!jeto.

mass: "ar mass : float

>aria!le que representa la masa del rigid!ody, su peso. &ecomienda el manual de referencia que el valor de la masa de!era estar entre E.5 y 5E. *asas grandes $seg3n el manual$ hacen las simulaciones fsicas inesta!les. @!viamente, los o!jetos con mayor masa proyectan a los que tienen menos masa cuando chocan. #ensemos en un

cami"n grande golpeando un coche pequeo. >amos a verlo con un ejemplo sencillo. #ara llevarlo a ca!o eliminamos el script que tiene vinculado nuestro cu!o. /uego seleccionamos la esfera, y la u!icamos en las coordenadas $7,E,E. Acto seguido hacemos do!le clic8 en *i#rimer2cript para a!rir el editor y tecleamos lo que sigue+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.velocity D >ector7-[,E,E.C P P

2alvamos y arrastramos el script a la esfera. 1ste no tiene mucho misterio+ al presionar la flecha hori'ontal del teclado, nuestra esfera de!era tomar una velocidad de aceleraci"n hacia su derecha, por lo que en principio de!era impactar con el cu!o. #ro!moslo. #lay. @!servamos que efectivamente al pulsar la flecha de despla'amiento hori'ontal, la esfera golpea contra el cu!o con la suficiente fuer'a como para incluso volcarlo. 2i nos fijamos, en los respectivos rigid!odies del cu!o y la esfera que aparecen en el inspector, am!os tienen una mass de 5. e!ido a ello, a rai' del impacto no hay un o!jeto que pare'ca <salir victorioso< de este -el cu!o gira una cara y la esfera retrocede lentamente tras el impacto.. RGue pasara, no o!stante, si uno de los dos rigid!odies tuviera una masa sensi!lemente distinta del otroS #ro!moslo aadiendo una e(presi"n ms a nuestro script+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.velocity D >ector7-[,E,E.C rigid!ody.mass D E.5C P P

Ahora nuestra esfera tendr una masa de E.5, esto es, una dcima parte de la masa del cu!o. 2alvamos, play, flecha lateral... ?asi ni mueve el cu!o. #odis pro!ar a la inversa, si queris, darle ms masa a la esfera -sin pasar de 5E, recordad.. ?ompro!ad que una ve' pulsais la flecha de despla'amiento hori'ontal, la masa de la esfera -si es que la tenis seleccionada. cam!ia en el inspector y se convierte en la que ha!is asignado en el script. #ara aca!ar, advertiros de que un error com3n es asumir que o!jetos pesados caen ms rpido que los ligeros. 1sto no es verdad, ya que la velocidad depende de la gravedad y la resistencia -drag., y no de la masa.

+seGra2it%: "ar useGravit% : boolean

Booleano que controla si la gravedad afecta a este rigid!ody. 2i est en false el rigid!ody se comportar como si estuviera en el espacio. #ro!amos. &ehacemos *i#rimer2cript+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<=ump<.. O rigid!ody.velocity D >ector7-E,`,E.C P

if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.useFravity D falseC P if -0nput.FetButton o4n -<>ertical<.. O rigid!ody.useFravity D trueC P P

2alvamos, y le damos impulso hacia arri!a a nuestra esfera. Alternad las flechas de despla'amiento hori'ontal y vertical para compro!ar la diferencia de movimientos sin y con gravedad.

20. CLASE RIGIDBODY (IV)

is6inematic: "ar is<inematic : boolean

1s un !ooleano que controla si las fsicas afectan al rigid!ody. 2i isainematic est ha!ilitado -es true., a nuestro rigid!ody no le afectarn ni fuer'as, ni colisiones ni junturas -joints.. 1llo quiere decir que no podemos esperar que frente $por ejemplo$ a una colisi"n ese rigid!ody 8inemtico se comporte de la manera l"gica que por su masa, resistencia y gravedad de!iera comportarse. 2us movimientos, reacciones y respuestas, por tanto, de!eremos marcrselos especficamente mediante scripts o animaciones. /os cuerpos 8inemticos, por el contrario y a su ve', s afectan el movimiento de otros rigid!odies no 8inemticos a travs de colisiones o joints. Guisiera aprovechar para recordar que las varia!les <e(puestas< de tipo !ooleano son mostradas por el inspector como un chec8!o(, donde el cuadro marcado se corresponde a true y el desmarcado al false.

(ree*eRotation: "ar free0e7otation : =oolean

1sta varia!le vendra a ser una especiali'aci"n de la anterior. free'e&otation controla si las fsicas cam!iarn la rotaci"n del o!jeto. 2i esta varia!le est ha!ilitada -true., la rotaci"n no ser mofificada por la simulaci"n de fsicas, y en todo caso tendremos que esta!lecerla nosotros manualmente mediante scripts o animaciones.

constraints: "ar constraints : 7igidbod%8onstraints

?ontrola qu grados de li!ertad estn permitidos para la simulaci"n de nuestro rigid!ody. #or defecto esta varia!le tiene el valor &igid!ody?onstraints.Mree'e9one, permitiendo rotaci"n y movimiento en todos los ejes.

1n algunos casos, puedes querer constreir un rigid!ody para que s"lo se mueva o rote so!re algunos ejes, como por ejemplo cuando desarrolles juegos en 6 . #uedes usar el operador de !its @& -bccb. para com!inar m3ltiples constraints. >amos a pro!ar con un sencillo ejemplo la utilidad de esta varia!le. 1n %nity alejamos un poco la cmara para que se vea tanto la esfera como el lateral i'quierdo -seg3n se mira. del plano. A!rimos nuestro script ha!itual+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.velocity D >ector7-$T,E,E.C P P

2alvamos, play, flecha despla'amiento lateral. /a esfera so!repasa la superficie del plano y arrastrada por la gravedad cae. #odramos solucionar esta eventualidad quitndole la gravedad a la esfera, pero tenemos una soluci"n ms elegante+ no permitir que nuestra esfera se mueva en el eje , -arri!a;a!ajo.. As que modificamos nuestro script+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.velocity D >ector7-$T,E,E.C rigid!ody.constraints D &igid!ody?onstraints.Mree'e#osition,C P P

, volvemos a pro!ar. ado que le hemos congelado -<free'e<. a nuestra esfera la posi!ilidad de alterar el valor de su eje de posici"n ,, la esfera no puede ni ascender ni caer, ra'"n por la cual contin3a rodando allende el plano. @!servamos que esta varia!le es de tipo &igid!ody?onstraints, lo cual en el fondo es una enumeraci"n que nos permite elegir entre una serie de valores, a sa!er+ 9one 2in limitaciones de posici"n ni de rotaci"n Mree'e#ositionI ?ongela la posici"n en el eje I. Mree'e#osition, ?ongela la posici"n en el eje ,. Mree'e#ositionJ ?ongela la posici"n en el eje J. Mree'e&otationI ?ongela la rotaci"n so!re el eje I. Mree'e&otation, ?ongela la rotaci"n so!re el eje ,. Mree'e&otationJ ?ongela la rotaci"n so!re el eje J. Mree'e#osition ?ongela la posici"n so!re todos los ejes. Mree'e&otation ?ongela la rotaci"n so!re todos los ejes Mree'eAll ?ongela rotaci"n y posici"n de todos los ejes

collisionDetection-ode: var collisionDetection3ode : 8ollisionDetection3ode

1sta varia!le nos permite esta!lecer el modo de detecci"n de colisiones del rigid!ody. ?omo podemos o!servar, es de tipo ?ollision etection*ode, tratndose sta al igual que en el caso anterior de una enumeraci"n que admite tres tipos de valores, que pasamos a desarrollar+

Distrete: 1ste es el modo de detecci"n de colisiones por defecto. 1s el que menos recursos consume, pero no garanti'a que nuestro rigid!ody detecte un conjunto de colisiones, so!re todo si estas acontencen a gran velocidad. 1n modo discrete %nity comprue!a si el rigid!ody ha sido colisionado cada ve' que se llama a la funci"n fi(ed%pdate, que como ya e(plicamos es llamada un n3mero fijo de veces por segundo. 2i la colisi"n se produce en el impass entre una

llamada a fi(edupdate y la siguiente, nuestro rigid!ody no la captar. 8ontinuous: ?on este modo on, nuestro rigid!ody detectar las colisiones con cualquier malla geomtrica esttica que se tropiece en su camino, incluso si la colisi"n ocurre entre dos llamadas a Mi(ed%pdate. #or malla geomtrica esttica %nity entiende cualquier *esh?ollider -no tardaremos en estudiarlo. que no tenga un rigid!ody vinculado. 8ontinuousDinamic: 2i esta!lecemos este sistema de detecci"n de colisiones para nuestro rigig!ody, ste detectar colisiones tanto con mallas geomtricas estticas como con otros rigid!odies que tengan a su ve' activado el modo continous collision detection. 1ste sistema consume !astantes recursos y de!e ser s"lo usado para prevenir movimientos muy rpidos de o!jetos. 2"lo es soportado, adems, por rigid!odies con sphere o !o( collider.

A efectos de sinta(is, para colocar el sistema de detecci"n de un rigid!ody en modo ?ontinuous inamic, por ejemplo, lo escri!iramos as+ rigid!ody.collision etection*ode D ?ollision etection*ode.?ontinuous ynamicC

21. CLASE RIGIDBODY (V)

centerO(-ass: 8enterOf3ass : "ector#

&epresenta el centro de masa relativo al origen del transform. 1l centro del transform se corresponde a las coordenadas locales E,E,E, y si no reu!icamos va un script el centro de masa, %nity lo calcula automticamente -suele coincidir con el centro del transform. 2i !ien no es una varia!le con demasiada utilidad, s que a veces puede servirnos para, por ejemplo, hacer ms esta!le y menos propenso a los vuelcos a un coche. %n coche con un centro de masa;gravedad !ajo es menos propenso a volcar. rigid!ody.center@f*ass D >ector7 -E, $6, E.C

.orldCenterO(-ass: var )orld8enterOf3ass : "ector#

1sta varia!le nos indica el centro de masa;gravedad de un rigid!ody en el espacio glo!al. :engamos presente que a diferencia de la anterior esta varia!le es de solo lectura.

detectCollisions: "ar detect8ollisions : =oolean

0ndica si la detecci"n de colisiones est ha!ilitada -por defecto, s.. esha!ilitar esta varia!le es util si tenemos un o!jeto que es 8inemtico y queremos evitar que el sistema realice clculos in3tiles de detecci"n de colisiones para l.

inter!olation: "ar inter!olation : 7igidbod%Inter!olation

/a interpolaci"n nos permite suavi'ar el efecto de correr fsicas en un framerate fijo. #or defecto la interpolaci"n est off. ?omunmente se usa la interpolaci"n de rigid!odies en los personajes de los jugadores. /as fsicas suelen transcurrir en pasos fijos -Mi(ed%pdate., mientras los grficos son renderi'ados en framerates varia!les. 1sto puede llevar a que los o!jetos pare'can tem!lorosos, porque fsicas y grficos no estn completamente sincroni'ados. 1l efecto es sutil pero percepti!le, y so!re todo afecta a los personajes principales que son seguidos por alguna cmara. 1s recomenta!le poner en on la interpolaci"n para el personaje principal pero desha!ilitarla para los dems. /a enumeraci"n &igid!ody0nterpolation tiene los siguientes valores+ 9one 2ignifica que no hay interpolaci"n. 1s la opci"n por defecto. 0nterpolate /a interpolaci"n ir con un poco de retraso, pero puede ser un poco ms suave que la e(trapolaci"n. 1(trapolate /a e(trapolaci"n predecir la posici"n del rigid!ody en !ase a la velocidad actual.

slee!Velocit%: var slee!"elocit% : float

/a velocidad lineal, por de!ajo de la cual los o!jetos empie'an a dormir -por defecto E.5X. en un rango que va de E a infinity. /a hecho de que los o!jetos duerman es una optimi'aci"n que permite que el engine de fsicas deje de procesar para estor rigid!odies. As, cuando el o!jeto se duerme deja de detectar colisiones o reali'ar simulaciones, por ejemplo.

slee!Ang+larVelocit%: var slee!*ngular"elocit% : float

/a velocidad angular, por de!ajo de los cuales los o!jetos empie'an a dormirse -por defecto E.5X.

ma)Ang+larVelocit%: "ar ma/*ngular"elocit% : float

&epresenta la ma(ima velocidad angular del rigid!ody -por defecto `. en un rango que va de E a infinity. 2e tiene que fijar una velocidad angular m(ima para evitar inesta!ilidades numricas con o!jetos rotando demasiado rpido.

Bueno, y hasta aqu las varia!les de la clase &igid!ody. )e omitido la e(plicaci"n de unas cuantas que me han parecido poco importantes, de poco uso.

22. CLASE RIGIDBODY (VI)

FUNCIONES: SetDensit%: Function SetDensit% (densit% : float) : void

9os permite asignar una masa en !ase al collider vinculado, lo cual es 3til para asignar una masa en unos valores acordes al tamao de los colliders. #odemos aplicar un ejemplo similar al que reali'amos con la varia!le mass. A!rimos nuestro script ha!itual y tecleamos+ function Mi(ed%pdate -. O if -0nput.FetButton o4n -<)ori'ontal<.. O rigid!ody.velocity D >ector7-T,E,E.C rigid!ody.2et ensity-T.E.C P P

2alvamos. #lay. #resionamos la flecha de despla'amiento hori'ontal y compro!amos que la masa de la esfera le permite literalmente arrastrar al cu!o.

AddForce: function *ddForce (force : "ector# mode : Force3ode & Force3ode(Force) : void

1sta funci"n -una de las ms importantes de la A#0 de %nity. aade una fuer'a al rigid!ody. ?omo resultado de esto el rigid!ody comen'ar a moverse. 1l primer parmetro es un >ector7, que nos servir para indicar la potencia y direcci"n de la fuer'a que aplicamos. #or ejemplo, podemos teclear en nuestro script de ca!ecera+ function Mi(ed%pdate -. O rigid!ody.AddMorce ->ector7.up Z 5E.C P

, al darle al play nuestra esfera ascender, fruto de una fuer'a constante -aplicada en cada actuali'aci"n de la funci"n Mi(ed%pdate.. @!viamente, la velocidad de movimiento depender $adems de la fuer'a aplicada $ de la masa del rigid!ody y de la resistencia, esto es, varios rigid!odies diferentes tendrn reaccione diferentes cuando les es aplicada la misma fuer'a. function *ddForce (/ : float % : float 0 : float mode : Force3ode & Force3ode(Force) : void

1ste segundo prototipo de la funci"n, como ya viene siendo ha!itual, meramente sustituye el parmetro de tipo >ector7 por 7 de tipo float. ;;1quivale al script anterior function Mi(ed%pdate -. O rigid!ody.AddMorce -E, 5E, E.C P

1l segundo parmetro o!servamos que es de tipo Morce*ode, que como posi!lemente sospechis es una nueva enumeraci"n made in %nity, que tiene los siguientes valores+ Morce Aade una fuer'a contnua al rigid!ody, dependiendo de su masa. 1s el valor por defecto y que o!tiene resultados ms realistas, ya que como decamos costar ms esfuer'o mover o!jetos ms pesados que ms livianos. Acceleration Aade una aceleraci"n contnua al rigid!ody, ignorando su masa. A diferencia de Morce*ode.Morce, Acceleration mover cualquier rigid!ody de la misma forma sin tener en cuenta su masa, lo que es 3til si s"lo queremos controlar la aceleraci"n de un o!jeto sin preocuparnos de la fuer'a que de!eramos aplicarle para o!tenerla teniendo en cuenta su masa y resistencia. 0mpulse Aade un impulso puntual de fuer'a al rigid!ody, teniendo en cuenta su masa. )ay que tener la precauci"n de no incluir este modo dentro de una funci"n que se actualice a menudo -como Mi(ed%pdate.. 1ste modo es 3til para aplicar fuer'as que acontecen de repente, como e(plosiones o colisiones. >elocity?hange Aade un cam!io de velocidad instantneo al rigid!ody, ignorando su masa. ?on esa salvedad -una misma fuer'a tendr los mismos resultados con rigid!odies de diferente masa., le es aplica!le lo mismo que al modo precedente.

#odemos ver la diferencia entre fuer'as aplicadas en el mismo script de arri!a. /o modificamos para que quede as+ function Mi(ed%pdate -. O rigid!ody.AddMorce ->ector7.up Z 5E, Morce*ode.0mpulse.C P

#odis ver que la esfera sale disparada. 9o retorna porque como la tenemos dentro de la funci"n Mi(ed%pdate est reci!iendo un impulso peri"dico. >amos a li!erarla+ rigid!ody.AddMorce ->ector7.up Z 5E, Morce*ode.0mpulse.C

2upongo que queda demostrada la diferencia entre fuer'a constante e impulso.

AddRelati2eForce function *dd7elativeForce (force : "ector# mode : Force3ode & Force3ode(Force) : void

Aade una fuer'a al rigid!ody relativa al sistema local de coordenadas de dicho rigid!ody. #ara e(plicar qu quiere decir esto, vamos a preparar un ejemplo que requerir varias fases+ #ara empe'ar, eliminamos el script que tenemos vinculado a la esfera. 9os colocamos en la vista vertical en la ventana 2cene, haciendo clic8 en la , del gi'mo. 1n #royecto hacemos do!le clic8 en *i#rimer 2cript para a!rir el editor, y tecleamos+ function Mi(ed%pdate-.O rigid!ody.AddMorce ->ector7.right Z 5K.C P

2alvamos, arrastramos el script al cu!o y le damos al play. :al como era de esperar, se aplica una fuer'a lateral al cu!o, pero ste da demasiadas vueltas so!re s como para hacer una demostraci"n respecto a las coordenadas de despla'amiento, as que vamos a completar el script con una de esas varia!les que cuando uno las estudia cree que no las usar nunca. rigid!ody.center@f*ass D >ector7-E,$E.7,E.C function Mi(ed%pdate-.O rigid!ody.AddMorce ->ector7.right Z 5K.C P

1(acto. /e !ajamos el centro de gravedad al cu!o y en principio de!eramos ahora poderlo arrastrar como un mue!le. #ro!emos si esto funciona en la prctica. /o suficiente para poder reali'ar la e(plicaci"n. Ahora giremos en el inspector el cu!o 7K grados so!re el eje ,. >olvamos a darle al play. >emos que la fuer'a que aplica la funci"n AddMorce lo es en relaci"n a las coordenadas glo!ales, y no a las del o!jeto. 2ustituimos en el script AddMorce por Add&elativeMorce y pro!emos de nuevo. Ahora la fuer'a no es aplicada a la derecha del mundo, sino a la derecha relativa del cu!o.

23. CLASE RIGIDBODY (VII)

AddTor,+e: function *ddTor2ue (tor2ue : "ector# mode : Force3ode & Force3ode(Force) : void function *ddTor2ue (/ : float % : float 0 : float mode : Force3ode & Force3ode(Force) : void

1sta funci"n aade una torsi"n -no he podido encontrar una traducci"n mejor para torque. al rigid!ody. ?omo resultado el rigid!ody empe'ar a girar alrededor del eje de torsi"n. As, si al eje , de rotaci"n de nuestro cu!o le reintegramos su valor de E y luego modificamos de la siguiente manera nuestro script del 3ltimo ejemplo... rigid!ody.center@f*ass D >ector7-E,$E.7,E.C function Mi(ed%pdate-.O rigid!ody.Add:orque ->ector7.right Z 5K.C P

...vemos que efectivamente se le ha aadido a nuestro cu!o una fuer'a de torsi"n;rotaci"n so!re el eje I. &ecordemos que cuando ha!lamos de rotaci"n, hemos de considerar a cada eje como si se tratara de una lnea rgida alrededor de la cual nuestro o!jeto gira. 1sto es, si quisiramos que el cu!o se moviera como una peon'a, tendriamos que hacerlo rotar so!re su eje ,. #ro!ad a cam!iar <>ector.right Z 5K< por <>ector.up Z 6K<. -, si queremos que rote en direcci"n opuesta, le anteponemos un signo $ al >ector..

AddRelati2eTor,+e: function *dd7elativeTor2ue (tor2ue : "ector# mode : Force3ode & Force3ode(Force) : void function *dd7elativeTor2ue (/ : float % : float 0 : float mode : Force3ode & Force3ode(Force) : void

?omo podris suponer, esta funci"n aade una fuer'a de torsi"n relativa a las coordenadas locales;propias del rigid!ody. 1s a Add:orque lo mismo que Add&elativeMorce a AddMorce.

AddForceAt/osition: Function *ddForce*t5osition (force : "ector# !osition : "ector# mode : Force3ode & Force3ode(Force) : void

Aplica fuer'a a un rigid!ody en una posici"n determinada.

AddE)!losionForce: Function *dd6/!losionForce (e/!losionForce : float e/!losion5osition : "ector# e/!losion7adius : float u!)ards3odifier : float & '('F mode : Force3ode & Force3ode(Force) : void

Aplica una fuer'a al rigid!ody que simula el efecto de una e(plosi"n. /a fuer'a de la e(plosi"n decaer de manera lineal con la distancia del rigid!ody. 1sta funci"n tam!in funciona !ien con o!jetos inertes. 2i el radio es E, la fuer'a plena ser aplicada sin importar cuan lejos se produ'da la e(plosi"n del rigid!ody. %p4ards*odifier aplica la fuer'a como si fuera aplicada desde de!ajo del o!jeto.

-o2e/osition: F+nction -o2e/osition 0!osition : Vector14 : 2oid

*ueve el rigid!ody de posici"n. #or ejemplo+ private var velocidad + >ector7 D >ector7 -7, E, E.C function Mi(ed%pdate -. O rigid!ody.*ove#osition-rigid!ody.position B velocidad Z :ime.delta:ime.C P

1n este script declaramos primero una varia!le de tipo >ector7. /e anteponemos la pala!ra clave <private<, que implica que dicha varia!le no ser accesi!le desde el inspector -no quedar e(puesta.. 2e declara como privada una varia!le que no queremos que se modifique desde la interface. 1l resto del script no merece mucha e(plicaci"n. 2e suma el >ector7 con la velociadd a la posici"n del rigid!ody, y para que el despla'amiento se produ'ca en segundos y no en porciones de frames, lo multiplicamos por :ime.delta:ime.

-o2eRotation: function 3ove7otation (rot : $uaternion) : void &ota el ridid!ody. 2i o!servamos el prototipo de la funci"n, vemos que hemos de pasarle a la misma un parmetro de tipo Guaternion. ,a hemos dicho en otras ocasiones que resulta !astante complejo para los humanos tra!ajar con cuaterniones, ra'"n por la cual por norma general tra!ajaremos en grados 1uler se los pasaremos a la funci"n convenientemente traducidos. %n ejemplo+ private var velocidad1nAngulos + >ector7 D >ector7 -E, 5EE, E.C function Mi(ed%pdate -. O var velocidad1n?uaterniones#or:iempo + Guaternion D Guaternion.1uler-velocidad1nAngulos Z :ime.delta:ime.C rigid!ody.*ove&otation-rigid!ody.rotation Z velocidad1n?uaterniones#or:iempo.C P

?omo podemos compro!ar, meramente tenemos que usar la funci"n Guaternion.1uler, que reci!e grados euler como parmetro y devuelve cuaterniones. 1l resto es sencillo.

25. CLASE COLLIDER (I)

1sta es la clase !ase para todos los tipos de colliders -que en castellano traduciramos por <colisionadores<.. /as clases Bo(?ollider, 2phere?ollider, ?apsule?ollider y *esh?ollider derivan de ella. %n collider vendra a ser la estructura que hace s"lidos a los o!jetos. 2eleccionemos en %nity la esfera. 1n el inspector o!servamos que tiene un 2phere ?ollider, que no es ms que un collider con forma de esfera. 2i desmarcamos el chec8!o( de dicho collider y le damos al play, automticamente la esfera deja de ser s"lida y, por efecto de la gravedad

que le da el rigid!ody, atraviesa el suelo y cae. #odemos seleccionar el cu!o. @!viamente, el cu!o no tiene una sphere collider, sino una !o( collider. , si importramos un gameo!ject capsule, tendra un capsule ?ollider. 1l pro!lema viene cuando importamos un game o!ject que no tiene una de estas formas primitivas. A veces se puede <encajar< una capsule collider en un r!ol, o una !o( collider en un coche. A veces no necesitamos que el colisionador de un o!jeto coincida al 5EEd con dicho o!jeto y uno de estos colliders !sicos nos pueden hacer el apao. #ero hay veces en que, !ien por la importancia del game o!ject en el juego, !ien por la forma compleja que tiene dicho game o!ject, !ien en la mayora de casos por am!as cosas -pensemos en el ninja protagonista de nuestro juego, por ejemplo. necesitamos un collider que sea completamente fiel a la forma del gameo!ject. #ara ello tenemos el mesh collider -que estudiaremos en !reve., que es meramente la malla del o!jeto convertida en la estructura s"lida del mismo que interact3a con el resto del mundo. 1(iste !astante confusi"n entre los nuevos en %nity respecto la diferencia entre un collider y un rigid!ody. %n collider, como decimos, es meramente la superficie de nuestro o!jeto. %n rigid!ody en cam!io implica la aplicaci"n de las leyes fsicas a dicho o!jeto. %n o!jeto puede tener un collider y no un rigid!ody -chocar con otros o!jetos, aunque no podremos controlar sus reacciones a las colisiones y ser %nity quien se encargue de ellas automticamente., y puede tener un rigid!ody y no un collider -aunque entre otras cosas tendremos que desactivarle la gravedad, para que no atraviese los suelos.. @!viamente, un o!jeto puede tener un rigid!ody y un collider, y de hecho %nity recomienda que si tu o!jeto es previsi!le que vaya a intervenir en muchas colisiones, adems de un collider es recomenda!le aadirle un rigid!ody 8inemtico. >amos a ello+ VARIABLES: ena"led: var enabled : boolean

2i el collider est ha!ilitado -true., colisionar con otros colliders. 2e corresponde al chec8!o( que est en el inspector en el apartado del collider.

attachedRidid"od%: var attached7igidbod% : 7igidbod%

1sta varia!le hace referencia al rigid!ody vinculado a este collider, y permite acceder a l. tiene rigid!ody.

evuelve nulo si el collider no

/os colliders son automticamente conectado al rigid!ody relacionado con el mismo game o!ject o con alg3n game o!ject padre. 1sto es, por ejemplo el rigid!ody que le aadimos en su momento al cu!o automticamente qued" vinculado al !o( collider de ste. #ro!moslo rehaciendo *i#rimer2ript+ function Mi(ed%pdate-. O collider.attached&igid!ody.AddMorce-E,5K,E.C P

2alvamos, nos aseguramos de que el script siga vinculado al cu!o, y le damos al play.

isTrigger: var isTrigger : boolean

2i esta varia!le est ha!ilitada -true. el collider se convierte en un trigger -lo podramos traducir por <desencadenante< o <disparador<.. %n trigger no colisiona con rigid!odies, y en su lugar enva los mensajes @n:rigger1nter, @n:rigger1(it y @n:rigger2tay -que estudiaremos al final de la clase. cuando un rigid!ody entra o sale de l. e esta manera nos permite a nosotros disear de manera especfica su comportamiento o las consecuencias de entrar en contacto con un trigger -pensemos en una puerta que nos lleva a otra dimensi"n, que se puede atravesar pero dispara un evento que nos teletransporta, por ejemplo.

material: var material : 5h%sic3aterial

1l material usado por el collider. 2i el material es compartido por varios colliders, al ser asignado a esta varia!le se har una copia de dicho material que le ser asignada al collider. /a varia!le es del tipo #hysic*aterial, que como en su momento estudiaremos es una clase que nos permite manejar aspectos de los materiales como la fricci"n o la capacidad de re!ote y el grado de la misma.

shared-aterial: var shared3aterial : 5h%sic3aterial

1l material compartido de este collider. *odificando este material cam!iaremos las propiedades de la superficie de todos los colliders que estn usando el mismo material. 1n muchos casos es preferi!le modificar en su lugar el ?ollider.material.

"o+nds: var bounds : =ounds

/os lmites;!ordes del collider en coordenadas glo!ales.

2". CLASE MES&COLLIDER

/a clase *esh?ollider, como vemos, hereda de la recin estudiada ?ollider, ra'"n por la que hereda todas sus varia!les, funciones y mensajes que enva, amn de hacer lo propio con las clases ?omponent y @!ject. %na *esh?ollider -o colisionador de malla., tal como dijimos no hace mucho, es meramente la malla de un gameo!ject que convertimos en collider, por norma general porque nuestro gameo!ject tiene una forma en la que difcilmente se puede encajar una malla primitiva. ?omo ventajas de usar esta opci"n, o!viamente que ha!r una mayor coherencia entre la apariencia del gameo!ject y su superficie de colisi"n. ?omo mayor desventaja, el aumento de consumo para que nuestro ordenador haga los pertinentes clculos para cada plano de nuestra malla.

VARIABLES: shared-esh: var shared3esh : 3esh

)ace referencia al o!jeto malla que nuestro gameo!ject est usando como detector de colisiones, si lo hay. 9os permite consultar sus caractersticas y;o asignar uno. /a varia!le es de tipo mesh -malla. y la estudiaremos ms adelante.

con2e): var conve/ : boolean

%sa un collider conve(o para la malla, esto es, con esta varia!le esta!lecida en true nuestro collider de malla automticamente pasa a ser conve(o y todas las entradas y agujeros que pudiera tener nuestra malla desaparecen, permitiendo una detecci"n de colisiones mucho ms completa. /as mallas conve(as pueden colisionar con otros colliders conve(os y no conve(os. #or lo tanto los colliders de malla conve(os son apropiados para rigid!odies en el caso de que necesitramos colliders con formas ms detalladas que los colliders primitivos. transform.collider.conve( D trueC

smoothS!hereCollisions:

var smoothS!here8ollisions : boolean

%sa normales interpolados para colisiones de esferas en lugar de normales planos poligonales. 1sto suavi'a los !aches para rodamientos de esferas so!re superficies suaves.

2#. CLASE C&ARACTERCONTROLLER (I)

%n character ?ontroller nos permite hacer fcilmente movimientos limitados por colisiones sin tener que lidiar con un rigid!ody. ?ompro!moslo empricamente, siguiendo estos pasos+ 5.$ /e !orramos a la esfera el script que tiene vinculado. 6.$ /e eliminamos a la esfera su componente rigid!ody -!ot"n derecho del rat"n situado so!re el nom!re de dicho componenteDL remove component. 7.$ ?on la esfera seleccionada, vamos al men3 ?omponentDL#hysicsDL?haracter ?ontroller. 9os saldr un aviso preguntndonos si realmente queremos sustituir el collider primitivo que por defecto trae la esfera por un ?haracter collider. #resionamos &eplace. X.$ 1n =erarqua seleccionamos suelo, y en el inspector desmarcamos el chec8!o( situado junto a *esh ?ollider. K.$ #lay. 1l cu!o, afectado por las leyes fsicas, atraviesa el suelo al que le hemos desha!illitado la malla. 2in em!argo el cu!o, que ahora est controlado por el character controller, no se ve afectado por las leyes fsicas. Antes de seguir, volvamos a ha!ilitar la malla del suelo en su correspondiente chec8!o(. %n character ?ontroller no se ve afectado tampoco por fuer'as y se mover s"lo cuando llamemos a la funci"n *ove, especfica de esta clase.

VARIABLES: isGro+nded: var isGrounded : boolean

Booleano que devuelve true si nuestro character controller -controlador de personaje, podramos traducirlo. esta!a tocando el suelo durante el 3ltimo movimiento.

2elocit%: var velocit% : "ector#

/a velocidad relativa actual del character. /a velocidad as retornada es la diferencia durante la 3ltima actuali'aci"n entre la distancia antes y despus de llamar a la funci"n *ove o 2imple*ove, esto es, d"nde esta!a el 3ltimo frame, o la 3ltima porci"n de frame o el 3ltimo segundo el character antes de llamar a una de esas funciones y d"nde est!a despues, para que distancia partida por -tiempo, frame o fracci"n dada. sea igual a la velocidad por tiempo, frame o fracci"n dada. ecimos que la velocidad es relativa porque no puede seguir movimientos del transform que suceden fuera del character controller -por ej un character emparentado !ajo otro transform en movimiento, como por ejemplo un vehculo movindose.

collisionFlags: var collisionFlags : 8ollisionFlags

1sta varia!le nos indic qu parte de la cpsula -que es la forma que tiene un character controller. colision" con el entorno durante la 3ltima llamada a ?haracter?ontroller.*ove. ?ompro!amos que la varia!le es de tipo ?ollisionMlags, que tal como podemos sospechar es de tipo enumeraci"n, permitindonos usar los siguientes valores+

9one+ 9o hay colisi"n. 2ides+ ?olisi"n en los lados. A!ove+ ?olisi"n en la parte superior. Bello4+ ?olisi"n en la parte inferior. As, un sistema para determinar si nuestro character controller ha topado con algo, y en qu parte de la cpsula, sera como sigue -no hace falta que tecleis esto, es s"lo a modo indicativo.+ function %pdate -. O var controller + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C controller.*ove->ector7-5,E,E..C if -controller.collisionMlags DD ?ollisionMlags.9one. print-<9o hay colisiones<.C if -controller.collisionMlags e ?ollisionMlags.2ides. print-<?olisi"n lateral, al menos<.C if -controller.collisionMlags DD ?ollisionMlags.2ides. print-<2"lo colisi"n lateral, ninguna de otro tipo<.C

if -controller.collisionMlags e ?ollisionMlags.A!ove. print-<?olisi"n superior, al menos<.C if -controller.collisionMlags DD ?ollisionMlags.A!ove. print-<2"lo colisi"n superior, ninguna de otro tipo<.C if -controller.collisionMlags e ?ollisionMlags.Belo4. print-<:ocando tierra<.C if -controller.collisionMlags DD ?ollisionMlags.Belo4. print-<2"lo tocando tierra, nada ms<.C P

/e aadimos el script a la esfera -si no lo tena ya vinculado. y le damos al play. /a esfera se mueve hacia la derecha, hasta que impacta con el cu!o -dmonos cuenta que la esfera ya no tiene un ridig!ody, pero gracias al character controller sigue colisionando con otros colliders. e!ajo de la ventana game aparece impresa la 3ltima colisi"n, pero no es la 3nica. 2i le hacemos clic8 al mensaje impreso nos saldr una lista de todas las colisiones que ha sufrido nuestra esfera hasta topar con el cu!o. /a funci"n Fet?omponent que hemos tecleado al inicio del script a3n no la hemos estudiado, pero su cometido es !astante o!vio+ !uscar el componente del gameo!ject que hace la llamada y que sea del tipo que le pasamos como parmetro, retornndolo. 1n este caso, nos sirve para iniciali'ar la varia!le controller, con la que tra!ajaremos para montar un primitivo sistema de identificaci"n de colisiones. la funci"n #rint es similar a e!ug./og, y la funci"n *ove la estudiaremos durante el pr"(imo captulo.

2$. CLASE C&ARACTERCONTROLLER (II)

radi+s: var radius : float

1l radio de la cpsula del character controller.

height: var height : float

/a altura de la cpsula del character controller.

center: var center : "ector#

1l centro de la cpsula del character relativo a la posici"n del transform.

slo!eLimit: var slo!e-imit : float

1l lmite de pendiente en grados por el que puede ascender nuestro character controller. >amos a pro!ar esta varia!le. 2igue estos pasos+ 5.$ 2eleccionamos el cu!o y lo despla'amos a la derecha -transform.( D 7, por ejemplo. 6.$ >amos al men3DLFame@!jectDLcreate otherDL?u!e. 7.$ 1n el apartado transform, le damos al nuevo cu!e estos valores+ position D E,6,E rotation D E,E,75K scale D E.6,`,5 9os de!era ha!er quedado algo as+

>ale, ahora tenemos una pasarela con una inclinaci"n de XK grados -7TE$75K., por lo tanto, que nuestra esfera la pueda su!ir o no depende del valor que le demos a slope/imit. As, si tecleamos+ function %pdate -. O var controller + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C controller.slope/imit D XT.EC controller.*ove->ector7-5,E,E..C P

9uestra esfera s ascender por la rampa, ya que el grado de inclinaci"n de esta es inferior al que puede asumir nuestro character controller. #ero le asignamos a slope/imit el valor XK.E. o!servaremos que ya la esfera se niega a su!ir.

ste!O((set: var ste!Offset : float

/os lmites de altura que el character controller podr superar, fijados en metros.-no podr por ejemplo su!ir una escalera si cada escal"n mide ms de ese lmite. #ara tra!ajar con un ejemplo, vamos a seleccionar el gameo!ject que nos sirvi" como rampa en el ejemplo anterior. /e esta!lecemos estos valores+ position+ E,E,E

rotation+ E,E,[E scale+ E.T,7,5 #or otro lado, a nuestro cu!o le vamos a aumentar momentneamente la altura -scale.y D X.. , tecleamos el siguiente c"digo para nuestra esfera+ function %pdate -. O var controller + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C controller.step@ffset D E.7C controller.*ove->ector7-5,E,E..C P

:omemos nota de que la antigua rampa tiene una altura de E.T. 1n cam!io, a nuestro character controller le hemos limitado la capacidad de superar alturas mayores de E.7, por lo que cuando le demos al play...la esfera topar con la rampa. 1n cam!io, si variamos el valor de step@ffset y lo colocamos, por ejemplo, a E.[, la esfera no tendr pro!lemas en superar la rampa, aunque tras hacerlo topar con el cu!o. #or e(periencia personal, las mediciones de esta varia!le no siempre resulta e(actas, ya que no todos los gameo!jects se asientan completamente y de manera e(acta so!re el suelo, o ste presenta desniveles. #ara evitar este tipo de ine(actitudes es necesario pro!ar el comportamiento de los o!jetos y modificar step@ffsset en consecuencia, hasta dar con el comportamiento adecuado. Borramos la rampa y devolvemos al cu!o a sus dimensiones ha!ituales y a su posici"n E,E,E.

detectCollisions: var detect8ollisions : boolean

etermina si otros rigid!odies o character controllers colisionan con nuestro character ?ontroller -por defecto esto est siempre ha!ilitado.. 1sta varia!le no afecta a las colisiones que nuestro character controller sufre cuando se mueve, sino las que sufre a ra' del movimiento de otros character controllers o colliders, y en concreto a si esos colliders o character controllers entrantes de!en ser !loqueados por nuestro controller. #ara este ejemplo tenemos que escri!ir dos scripts. A!rimos *i#rimer2cript, que de!eramos tener vinculado a nuestra esfera, y tecleamos+ function %pdate -. O var controller + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C controller.detect?ollisions D falseC P

Aqu meramente le decimos a nuestro character controller que no queremos que !loquee los colliders entrantes. , ahora a!rimos *i2egundo2cript y escri!imos+ function Mi(ed%pdate-. O rigid!ody.AddMorce-$5E,E,E.C P

/e asignamos este segundo script al cu!o, de tal forma que se despla'ar hacia la i'quierda, hasta colisionar con la esfera. 1s preferi!le colocar la escena en vista superior -eje , del gi'mo.. /e damos al play. , tal como era de esperar, nuestra esfera no !loquea al cu!o. 1so s, si lo hu!iramos hecho al revs -mover la esfera hacia el cu!o. aunque la varia!le detect?ollisions estuviera en false, se producira la colisi"n y el consiguiente !loqueo.

, en la pr"(ima lecci"n vamos a por las funciones de esta clase.

30. CLASE C&ARACTERCONTROLLER ( III)

FUNCIONES: -o2e:

function 3ove (motion : "ector#) : 8ollisionFlags

1sta funci"n mueve un character controller en la direcci"n y velocidad esta!lecida por el parmetro de tipo vector tres. icho movimiento s"lo ser restringido por las colisiones que sufra el character. 1mpecemos por un ejemplo !sico. 1liminamos el script vinculado al cu!o, y acto seguido modificamos el script vinculado a la esfera, para que quede as+ private var mi?har?ol + ?haracter?ontrollerC mi?har?ol D Fet?omponent-?haracter?ontroller.C function %pdate-. O mi?har?ol.*ove->ector7-5 Z :ime.delta:ime ,E,E..C P

9o tiene mucho misterio. Almacenamos el componente character controller de nuestro gameo!ject en una varia!le -que declaramos como privada para que no sea accesi!le desde el inspector., y acto seguido le damos un movimiento de una unidad por segundo a la derecha. #ulsando el play efectivamente la esfera se despla'a hasta que topa con el cu!o. 1l collider del cu!o en este caso detiene el avance de la esfera, porque lo intercepta de pleno. #ero si al cu!o lo u!icamos en position.JD E.Y y volvemos a darle al play, o!servamos que la esfera no detiene su avance. ?hoca y se despla'a de manera acorde a la colisi"n, pero acto seguido contin3a avan'ando hacia la derecha. /a funci"n devuelve una varia!le de tipo collisionMlags, que estudiamos hace un par de captulos, y que aporta informaci"n so!re la u!icaci"n de las colisiones que ha sufrido el character controller. ?on esa informaci"n, podemos alterar el comportamiento de nuestro character controller cuando sufra una colisi"n en una 'ona determinada de su cpsula. Ampliamos el script anterior, para que quede as+ private var mi?har?ol + ?haracter?ontrollerC mi?har?ol D Fet?omponent-?haracter?ontroller.C private var direccion + >ector7 D >ector7.rightC function %pdate-. O var misFolpes + ?ollisionMlags D mi?har?ol.*ove-direccion Z :ime.delta:ime.C if-misFolpes DD ?ollisionMlags.2ides. O

direccion D >ector7-E,E,$5.C P P

/a esfera empie'a su despla'amiento hacia la derecha -que es la direcci"n inicial que se le asigna a la funci"n *ove., hasta que colisiona con el cu!o. Al hacerlo, nuestro condicional <if< detecta si la colisi"n se ha producido en uno de los laterales de la cpsula de nuestro character controller -?ollisionMlags.2ides. y, para ese caso, se le pasa un nuevo vector7 a la direcci"n de la esfera.

Sim!le-o2e: function Sim!le3ove (s!eed : "ector#) : boolean

#odramos deducir que esta funci"n es similar a la anterior, y as es, pero con algunas peculiaridades. #or ejemplo, si a nuestra esfera le asignamos el siguiente script... function %pdate-. O var mi?har?ol + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C mi?har?ol.2imple*ove->ector7-5 Z :ime.delta:ime, E,E..C P

...podramos esperar que la esfera se moviera hacia la derecha, pero se da el caso de que a la que presionamos play la esfera atraviesa el suelo y cae. 1sto es porque esta funci"n automticamente le asigna gravedad al character controller que la llama. #or otro lado, esta funci"n no devuelve informaci"n so!re el lugar de contacto en que se ha producido las colisiones.

31. CLASE RENDERER (I)

%n render vendra a ser el proceso por el que un ordenador muestra una imagen. e ah que sea incuestiona!le la importancia de esta clase dentro de %nity. :anto los gameo!jects como algunos componentes tiene una propiedad renderer a la que podemos acceder;modificar, o que incluso se puede desha!ilitar para hacer dicho gameo!ject o componente invisi!le.

VARIABLES: ena"led: var enabled : boolean

)ace el o!jeto visi!le -true. o invisi!le -false..

castShado.s: var castShado)s : boolean

R#royecta som!ras este o!jetoS

recei2eShado.s: var receiveShado)s : boolean

R&eci!e som!ras este o!jetoS

material: var material : 3aterial

1l material de nuestro o!jeto. *odificar esta varia!le s"lo cam!iar el material para este o!jeto. 2i el material que asignamos a nuestro o!jeto est siendo usado para otros renders, se clonar el material compartido y se asignar una copia de dicho material para nuestro o!jeto. /a varia!le es de tipo *aterial,que estudiaremos en su momento, y que nos permite cam!iar el color del o!jeto, su te(tura y la manera en que reacciona a la lu', entre otras propiedades. >eamos un ejemplo sencillo. /e asignamos este script a la esfera+ renderer.material.color D ?olor.greenC renderer.material.shader D 2hader.Mind- <:ransparent; iffuse< .C renderer.receive2hado4s D falseC

Al darle al play, podemos o!servar el cam!io de apariencia. shared-aterial: var shared3aterial : 3aterial

)ace referencia al material que nuestro o!jeto comparte con otros. *odificar esta varia!la cam!iar la apariencia de todos los o!jetos que usen este material y las propiedades del mismo que estn almacenadas en el proyecto tam!in, ra'"n por la que no es recomenda!le modificar materiales retornados por shared*aterial. 2i quieres modificar el material de un renderer usa la varia!le ]material^ en su lugar.

shared-aterials: var shared3aterials : 3aterial+,

evuelve un array con todos los materials compartidos de este o!jeto, a diferencia de shared*aterial y material, que s"lo devuelven el primer material usado si el o!jeto tiene ms de uno. %nity soporta que un o!jeto use m3ltiples materiales. Al igual que la varia!le anterior y por la misma ra'"n, no es aconseja!le modificar materiales devueltos por esta varia!le

materials: var materials : 3aterial+,

evuelve un array con todos los materiales usados por el renderer.

"o+nds: var bounds : =ounds

1s una varia!le de s"lo lectura que indica los lmites del volumen del renderer. A cada renderer %nity le asigna una caja invisi!le que contiene -que envuelve. al o!jeto y cuyos !ordes estn alineados con los ejes glo!ales. e esta manera a %nity le resulta ms sencillo hacer clculos de despla'amiento y situaci"n. #or ejemplo, renderer.!ounds.center normalmente es ms preciso para indicar el centro de un o!jeto que transform.position, especialmente si el o!jeto no es simtrico. #ensemos, para apro(imarnos intuitivamente al concepto, en esas rosas que vienen dentro de cajas transparentes de plstico. 1n cualquier caso, la estructura Bounds la estudiaremos ms adelante.

lightma!Inde): var lightma!Inde/ : int

1l ndice del lightmap aplicado a este renderer. 1l ndice se refiere al array de lightmaps que est en la clase /ightmap2ettings. %n valor de 6KK significa que no se ha asignado ning3n lightmap, por lo que se usa el que est por defecto. %na escena puede tener varias lightmaps almacenados en ella, y el renderer puede usar uno o varios. 1sto hace

posi!le tener el mismo material en varios o!jetos, mientras cada o!jeto puede referirse a un ligthmap diferente o diferente porci"n de un lightmap.

isVisi"le: ar is"isible : boolean

>aria!le de s"lo lectura que indica si el renderer es visi!le en alguna cmara. )ay que tener presente que un o!jeto es considerado visi!le para %nity cuando necesita ser renderi'ado en la escena. #odra por lo tanto no ser visi!le por ninguna cmara, pero todava necesitar ser renderi'ado -para proyectar som!ras, por ejemplo..

32. CLASE RENDERER ( II)

FUNCIONES: OnBecameVisi"le: function On=ecame"isible () : void

1sta funci"n -del tipo mensaje enviado. es llamada cuando el o!jeto se vuelve visi!le para alguna cmara. 1ste mensaje es enviado a todos los scripts vinculados al renderer. 1s 3til para evitar clculos que son s"lo necesarios cuando el o!jeto es visi!le. &ecordemos que la sinta(is de este tipo de funciones es distinta, as que si quisiramos por ejemplo que un gameo!ject fuera visi!le cuando fuera a salir en una cmara, escri!iramos esto+ function @nBecame>isi!le-. O ena!led D trueC P

OnBecameIn2isi"le: function On=ecameInvisible () : void

1s llamada cuando el o!jeto ya no es visi!le por ninguna cmara.

33. CLASE MES&%ILTER

%n mesh filter -o filtro de malla. toma una malla de la carpeta de assets y se la pasa a mesh renderer para renderi'arla en la pantalla. 1s, para entendernos, la estructura de alam!re de la malla. VARIABLES: mesh: var mesh : 3esh evuelve la instancia de malla asignada al mesh filter. 2i no se ha asignado ninguna malla al mesh filter se crear y asignar una nueva. 2i la malla asignada al mesh filter es compartida por otros o!jetos, automticamente se duplicar y la malla instanciada ser retornada. %sando las propiedades de malla puedes modificar la malla para un solo o!jeto solamente. /os otros o!jetos que usan la misma malla no sern modificados. ?uando estudiemos la clase *esh aprenderemos las diferentes posi!ilidades de alteraci"n y deformaci"n de mallas que esto nos permite. shared-esh: var shared3esh : 3esh evuelve la malla compartida del mesh filter. 1s recomenda!le usar esta funci"n s"lo para leer datos de malla y no para escri!irlos, dado que podras modificar los assets importados y todos los o!jetos que usan esta malla podran ser afectados. :engamos en cuenta tam!in que no ser posi!le deshacer los cam!ios hechos a esta malla.

34. CLASE JOINT (I)

1s la clase !ase para todos los tipos de joints. #or clase !ase queremos decir que no podemos instanciarla como tal, sino que sirve para ser heredada por diferentes tipos de joint -hingejoint, springjoint, characterjoint. que estudiaremos a continuaci"n. #odramos traducir joint por juntura o articulaci"n, pero en principio usaremos la pala!ra en ingls. 9o o!stante, tal como denota el significado en castellano de joint, podemos deducir que esta clase sirve para unir varios o!jetos de una manera u otra -pensemos en una puerta unida por una !isagra, en las articulaciones que mantienen unidos los huesos, o meramente en una pared de o!jetos$ladrillo..

VARIABLES: connectedBod%: var connected=od% : 7igidbod%

1sta varia!le referencia a otro rigid!ody con el que este nuestra variante de joint conecta. 2i la varia!le es null, el joint conecta el o!jeto con el mundo, esto es, en lugar de estar vinculado a otro rigid!ody, nuestro o!jeto quedar <clavado< en su lugar en la escena. a)is: var a/is : "ector#

1l eje altededor del cual el movimiento del rigid!ody estar restringido, indicado en coordenadas locales.

anchor: var anchor : "ector#

/a posici"n del ancla alrededor de la cual el movimiento de los joints est restringido. /a posici"n es definida en espacio local. 1n la pr"(ima lecci"n reali'aremos una serie de ejemplos que nos permitir comprender con mayor claridad la funcionalidad de estas varia!les.

35. CLASE JOINT ( II)

"rea5Force: var brea9Force : float

/a fuer'a que es necesario aplicarle a este joint para romperlo. /a fuer'a podra venir por colisiones con otros o!jetos, fuer'as aplicadas con rigid!ody.AddMorce o por otros joints. >amos a reali'ar una serie de ejemplos que incluirn tanto las varia!les vistas en la lecci"n anterior como en sta. #ara ello vamos a seguir los siguientes pasos+ 5.$ 1liminamos en el inspector el hingejoint de la esfera, y a sta le aadimos un sphere collider. /a u!icamos en la posici"n -$5,E,$K.. /e eliminamos el script que tena vinculado. 6.$>amos al men3 gameo!jectDL?reate otherDL?u!e. %!icamos este cu!e en -$5,E,E. y le aadimos un hingejoint. 7.$1ditamos el script *i#rimer2cript como sigue+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.!rea8Morce D 6EC

X.$Asignamos *i#rimer2cript al recin creado gameo!ject ?u!e, y luego arrastramos nuestro cu!o a la varia!le pegadoA:i. K.$1ditamos ahora *i2egundo script, tecleando+ function Mi(ed%pdate-. O rigid!ody.AddMorce-E,E,[.C P

T.$1ste script se lo asignamos a la esfera. Bueno, pues vamos ahora a jugar a los !olos ms rupestres de la historia. :enemos por un lado dos cu!os unidos por un joint -el cu!o que tiene el hinge joint y el cu!o unido a ste primero a travs de la varia!le connectedBody., con una fuer'a de ruptura de 6E, y una esfera dispuesta a chocar contra el cu!o situado a nuestra i'quierda con una fuer'a de [.

mosle al play y pro!emos qu sucede. 1st claro que es mayor la resistencia del cu!o que la fuer'a de la esfera. >eamos si la varia!le !rea8Morce ha tenido algo que ver en dicha resistencia cam!iando su valor de 6E a X. #lay. @!servamos que $aunque con algo de esfuer'o$ ahora s la esfera rompe el joint y consigue arrastrar el cu!o de la i'quierda -el portador del hingejoint.. )agamos ahora unas pequeas modificaciones+ %!icamos la esfera en -E,E,$K. para que nos vaya a impactar al cu!o que no tiene asignado el hingejoint. #ara hacer un acercamiento intuitivo al ejercicio, podemos pensar que el cu!o situado a nuestra i'quierda -cu!e. sera el marco y el de nuestra derecha -nuestro cu!o. la puerta. >isto as, ahora vamos a intentar impactar nuestra esfera con la puerta. &esta!lecemos la varia!le !rea8Morce a 6E. /e damos al play. >eremos que la esfera arrastra al cu!o -a!re la puerta., pero no rompe su uni"n con el otro cu!o. ?am!iemos de nuevo la varia!le !rea8Morce de valor, pongmmosle un 5. e nuevo play. @!servad c"mo la esfera no tiene pro!lemas en romper la juntura. #ero vamos a seguir jugando con las varia!les que hemos ido viendo en estos dos captulos. Antes que nada despla'aremos un poco nuestra esfera para que s"lo golpee en el cu!o que no tiene el hinge joint, as que u!icamos la esfera en -E.K,E,$K. >amos a aadir luego la varia!le a(is a *i#rimer2cript, de la siguiente manera+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.a(is D >ector7.upC hinge=oint.!rea8Morce D 6EC

&ecordemos que a(is indica el eje alrededor del cual el movimiento de nuestro rigid!ody portador del hingejoint permanecer !loqueado. #or lo tanto, si !loqueamos el eje up;do4n a travs de la varia!le a(is, te"ricamente el cu!o de nuestra i'quierda no de!era girar so!re dicho eje. ?omo truco os recomendara que antes de darle al play seleccionrais en el inspector el ?u!e, para que veis la flecha naranja saliendo del gameo!ject. Al darle al play, la flecha sealar en la direcci"n del eje indicado por la varia!le a(is. #ulsamos el play, decimos, y tal como esper!amos, la esfera pasa a travs del cu!o de nuestra derecha, pero el que tiene el hinge joint no gira so!re su eje vertical. /a diferencia resulta muy clara si cam!iamos en lugar de >ector7.up colocamos >ector7.for4ard como valor de a(is. pro!adlo sin miedo. #ro!emos ahora la varia!le anchor, que tal como indic!amos indica la posici"n del ancla alrededor de la cual se restringe el movimiento de los joints. #ro!emos a dejar *i#rimer2cript as+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.a(is D >ector7.rightC hinge=oint.anchor D >ector7-E,E,E.C hinge=oint.!rea8Morce D 6EC

)emos cam!iado, como vemos, el eje que restringir la varia!le a(is, pasando del eje arri!a;a!ajo al derecha;i'quierda. %!icamos la varia!le anchor en las coordenadas locales de nuestro hingejoint -E,E,E.. mosle al play y o!servemos por un lado la u!icaci"n de la flecha naranja -recordemos previo pulsar play dejar seleccionado ?u!e. y por otro el comportamiento de am!os cu!os al ser impactados por la esfera. >ale. Ahora vamos a modificar la u!icaci"n del ancla. ejmosla as+ hinge=oint.anchor D >ector7-E,$E.K,E.K.C

1so significa -recordemos que estamos en coordenadas locales del cu!e. que el ancla estar situada en el centro del cu!e respecto del eje I -E., en la parte inferior del cu!e respecto del eje , -$E.K. y en la parte trasera del cu!e respecto

al eje J -E.K.. mosle al play y o!servemos la situaci"n del ancla y la diferencia de comportamiento.

"rea5Tor,+e: var brea9Tor2ue : float

/a torsi"n que es necesario aplicar a este joint para romperlo.

FUNCIONES: On7ointBrea5: function On>oint=rea9 (brea9Force : float) : void

Munci"n de tipo <mensaje enviado< que es llamada cuando un joint vinculado al mismo game o!ject se rompe. ?uando una fuer'a que es mayor que el !rea8Morce del joint es aplicada, el joint se romper. 1n ese momento, esta funci"n ser llamada y el la fuer'a de ruptura aplicada al joint le ser pasada a la misma. espus de @n=ointBrea8 el joint automticamente ser !orrado del game o!ject. Adaptemos *i#rimer2cript para e(plicar esta funci"n+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.!rea8Morce D 5.EC function @n=ointBrea8-resistencia + float. O e!ug./og-<2e nos rompi" el joint con resistencia < B resistencia.C P

1l script es !astante sencillo. /e aplicamos a nuestro hingejoint una fuer'a de ruptura !aja, para asegurarnos de que el impacto de la esfera lo romper. ?uando esto suceda ser llamada la funci"n @n=ointBrea8, que en este caso imprimir un mensaje en el que, adems de un te(to, mostrar el valor que tendr tras la ruptura la varia!le que le pasamos como parmetro, y que coincidir con la fuer'a de ruptura previamente asignada. Bueno, pues e(plicada la clase !ase, iremos a por las diferentes clases que heredan de joint.

3!. CLASE &INGEJOINT (I)

1sta clase agrupa juntos 6 rigid!odies, constreindolos a moverse como si estuvieran conectados por una !isagra. 1ste tipo de joints es perfecto para puertas, pero tam!in puede usarse para modelar cadenas, por ejemplo.

VARIABLES: motor: var motor : >oint3otor

/a varia!le motor aplicar una fuer'a en aumento hasta conseguir la velocidad deseada en grados por segundo. 1sta varia!le es de tipo =oint*otor, que es una estructura que a su ve' tiene las siguientes varia!les+ target>elocity+ 1s la velocidad de despla'amiento o rotaci"n que se pretende conseguir. force+ 1s la fuer'a que aplicar el motor para conseguir la velocidad fijada en target>elocity. free2pin+ 1s un !ooleano. 2i est ha!ilitado, el motor s"lo acelerar y nunca reducir. 2i unimos intuitivamente los conceptos junturas y motor, posi!lemente se nos vengan a la ca!e'a engranajes, vehculos o maquinarias. 1sa intuici"n no va muy desencaminada. )agamos las siguientes modificaciones para prepararnos el terreno. 1liminamos el script vinculado a la esfera. /uego vamos a colocar a nuestros cu!os siameses -cu!o y cu!e. dos unidades so!re tierra, lo que o!viamente conseguiremos colocando su posici"n -la de los dos. en el eje I en 6. 1n am!os casos, adems y para evitar que se nos caigan al suelo por la gravedad, en sus respectivos constrainst marcaremos Mree'e #osition ,. Ahora editamos el script *i#rimer2cript -que si hemos seguido las lecciones al pie de la letra de!emos tener vinculado a ?u!e., para que lu'ca as+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.anchor D >ector7-E,E,E.C hinge=oint.motor.force D5EEC hinge=oint.motor.target>elocity D [EC hinge=oint.motor.free2pin D trueC

&esumamos lo que hemos hecho+ 1l rigid!ody del segundo cu!o -el que no tiene asignado un hinge=oint. es asignado a la varia!le pegadoA:i, que posteriormente es conectada al hinge=oint. 1l ancla entre am!os cu!os -que por defecto se u!ica en el eje I. la colocamos en el centro geomtrico del cu!o, para que el giro que pretendemos sea ms natural. /uego aplicamos un motor al hingejoint con una fuer'a de 5EE hasta conseguir alcan'ar una velocidad de [E grados por segundo, y sin que el motor pueda reducir. mosle al play para compro!ar que funciona. 1l motor trata de alcan'ar la velocidad angular de motor.target>elocity en grados por segundo. 1l motor s"lo ser capa' de alcan'ar motor.target>elocity si motor.force es suficientemente grande. 2i el joint est girando ms rpido que el motor.target>elocity el motor se romper. %n velor negativo para motor.target>elocity har que el motor gire en direcci"n contraria. 1l motor.force es la torsi"n m(ima que el motor puede ejercer. 2i es cero el motor se desha!ilita. 1l motor frenar cuando gire ms rpido que motor.target>elocity s"lo si motor.free2pin es false. 2i motor.free2pin es true el motor no frenar.

3". CLASE &INGEJOINT ( II)

limits: var limits : >oint-imits

>aria!le que esta!lece;indica los lmites de nuestro hingejoint -recordemos, para que tengamos ms o menos claro a qu nos referimos con lo de lmites, que hinge lo podemos traducir por <!isagra<.. /a varia!le es del tipo =oint/imits, que es una estructura que a su ve' tiene las siguientes cuatro varia!les+ min+ 1s el lmite inferior del joint. ?uando el ngulo o posici"n del joint se halla por de!ajo de este valor, el joint reci!e la fuer'a necesaria para resta!lecerlo a ese mnimo. ma(+ 1l lmite superior del joint. 2i el ngulo o posici"n de ste est por encima de este valor, el joint reci!e fuer'as pra resta!lecerlo a dicho m(imo. minBounce+/a capacidad de retorno del joint a su lmite inferior cuando es golpeado por de!ajo de ste -pensemos en las puertas del 2aloon. ma(Bounce+/o mismo que la anterior aplicado al lmite superior.

1l joint ser limitado para que el angulo est siempre entre limits.min y limits.ma(. icho ngulo se calcula en trminos relativos al ngulo e(istente al principio de la simulaci"n, esto es, si entre dos rigid!odys hay ya al inicio un ngulo de 6E\, si su varia!le limits.min la fijamos en 5E, el ngulo real ser de 7E\ >amos a trastear un rato, que es la mejor manera de quedarse con los conceptos. e entrada, vamos a devolver al suelo a nuestros cu!os, as que devolvemos sus transform.position.y respectivas a cero, y no nos olvidemos de desmarcar la casilla de sus constraints que marcamos en el ejemplo anterior.

#or otro lado, el script *i2egundo2cript, que en el anterior captulo le ha!amos sustraido a la esfera, se lo volvemos a asignar, para que de nuevo impacte contra nuestros cu!os. /e daremos algo ms de fuer'a -AddMorce-E,E,6E... %!icaremos a la esfera en la posici"n E.7,E,$K. Ahora vamos a intentar convertir los cu!os en lo ms parecido a una puerta, y le vamos a dar unos ngulos m(imo y mnimo de apertura. #ara evitar que el cu!o que tiene asignado el hinge joint -cu!e. se nos mueva demasiado le asignaremos un valor a su varia!le mass en el rigid!ody -en el inspector . de T. , tecleamos en *i#rimer2cript+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.a(is D >ector7.upC hinge=oint.anchor D >ector7-E.K,$E.K,E.K.C hinge=oint.limits.min D EC hinge=oint.limits.ma( D `EC hinge=oint.limits.minBounce D EC hinge=oint.limits.ma(Bounce D EC

2i lo pro!amos, veremos que al impacto de la esfera nuestro joint alcan'a un grado m(imo de `E grados, sin re!ote. 2i quisiramos o!tener un re!ote de nuestra puerta precaria, podramos asignarle a ma(Bounce un valor de X, por ejemplo.

s!ring: var s!ring : >ointS!ring

1sta varia!le intenta alcan'ar un ngulo que es su o!jetivo a !ase de aadir fuer'as de resorte y amortiguaci"n. #odemos traducir en este conte(to spring como muelle, lo que nos da una idea del tipo de impulso del que estamos ha!lando. 1l tipo de esta varia!le es =oint2pring, que tal como podemos suponer es de nuevo una estructura, que en este caso consta de tres varia!les+ spring+ /a fuer'a tipo resorte para alcan'ar la target#osition, el ngulo deseado. %n valor ms grande hace que alcancemos la posici"n ms rpido. damper+ /a fuer'a del amortiguador usada para amortiguar la velocidad angular. %n valor ms grande hace que alcance el o!jetivo ms lento. target#osition+ /a posici"n que el joint intenta alcan'ar. 1l spring alcan'a la target#osition en ngulos relativos al ngulo inicial.

#ongmoslo con un ejemplo. #ara ello previamente eliminamos el script vinculado a la esfera. , luego, *i#rimer2cript de!era quedar como sigue+ var pegadoA:i + &igid!odyC hinge=oint.connectedBody D pegadoA:iC hinge=oint.a(is D >ector7.upC hinge=oint.anchor D >ector7-E.K,$E.K,E.K.C hinge=oint.spring.spring D 6EC hinge=oint.spring.damper D TC hinge=oint.spring.target#osition D [EC

Aqu a!riremos nuestra puerta precaria con un impulso inicial de 6E y una amortiguaci"n de T, tendiendo a alcan'ar los [E grados. 2i le damos al play notaremos el evidente efecto catapulta.

+se-otor: var use3otor : boolean

)a!ilita;desha!ilita el motor del joint.

+seLimits: var use-imits : boolean

)a!ilita;desha!ilita los lmites del joint.

+seS!ring: var useS!ring : boolean

)a!ilita;desha!ilita el resorte del joint.

2elocit%: var velocit% : float

evuelve la velocidad actual del joint en grados por segundo.

angle: var angle : float

evuelve el ngulo actual en grados del joint con respecto a la posici"n inicial. 1s una varia!le de solo lectura.

3#. CLASE SPRINGJOINT

1l spring joint ata juntos dos rigid !odies que se encuentran a una cierta distancia. /as fuer'as spring -resorte. se aplicarn automticamente para mantener el o!jeto a la distancia dada, intentando mantener la distancia que ha!a cuando empe'". /as propiedades min istante y ma( istance aaden unos lmites de implcita distancia.

VARIABLES: s!ring: var s!ring : float

/a fuer'a del spring usada para mantener los dos o!jetos juntos.

dam!er: var dam!er : float

/a fuer'a de amortiguaci"n usada para amortiguar la fuer'a del spring.

minDistance: var minDistance : float

/a distancia mnima entre los rigid!odies relativa a su distancia inicial. /a distancia que ha!r de mantenerse se conservar entre min istance y ma( istance. Am!os valores son relativos a la distancia entre los respectivos centros de masa cuando la escena fue cargada al principio.

ma)Distance: var ma/Distance : float

/a distancia m(ima entre los rigid!odies relativa a su distancia inicial.

>eamos todo esto con un ejemplo rpido, para lo cual previamente haremos las pertinentes modificaciones en la interfa' de %nity. Asignamos -una ve' ms. el script *i2egundo2cript a la esfera. 2eleccionamos <?u!e< en la jerarqua, y lo u!icamos en position.( D $7. Asimismo le eliminamos el componente hingejoint y en componentsDL#hysicsDLspring joints le aadimos un spring. @!servaremos que ahora el cu!e en lugar de una flecha tiene un minicu!o. , $ahora s$ remo'amos *i#rimer2cript+ var pegadoA:i + &igid!odyC var spring=oint + 2pring=ointC spring=oint D Fet?omponent-2pring=oint.C spring=oint.connectedBody D pegadoA:iC spring=oint.spring D 6KC spring=oint.damper D XC spring=oint.min istance D EC spring=oint.ma( istance D EC

>eamos lo que hemos querido hacer. 1n primer lugar declaramos una varia!le -que la llamamos spring=oint por claridad didctica, pero que hu!iramos podido darle otro nom!re legal. de tipo 2pring=oint y le asignamos el componente 2pring=oint de nuestro cu!e. /uego vinculamos el cu!o a nuestro joint. , a partir de ah le damos al sprint;resorte una fuer'a de recuperaci"n de 6K, una de amortiguaci"n de X, y esta!lecemos la distancia mnima y m(ima la que ya am!os cu!os tenan al darle al play, esto es, 7 metros. 2i quisiramos que los cu!os tras el impacto de la esfera quedaran a ms o menos distancia de la inicial retocaramos respectivamente min istance o ma( istance. adle al play. 9uestro muelle retiene al cu!o a la distancia estipulada del portador del spring joint. #odis jugar con spring y damper para que esa fuer'a de tipo resorte sea ms o menos acusada.

3$. CLASE C&ARACTERJOINT

1sta clase, como su nom!re indica, es principalmente usada con personajes. 1n concreto, la utilidad !sica de la misma consiste en simular lo que se vienen llamando efectos &agdoll -proceso de animaci"n para simular muertes, valga la aparente paradoja.. &agdoll podra traducirse como <mueca de trapo<, para que nos hagamos una idea del efecto que se pretende conseguir.1sta especialidad de joint nos permite limitar el joint de cada eje.

VARIABLES: s.ingA)is: var s)ing*/is : "ector#

1l eje secundario alrededor del cual el joint puede rotar. /os lmites de rotaci"n permitida alrededor de este eje vendrn esta!lecidos por ?haracter=oint.s4ing5/imit.

lo.T.istLimit: var lo)T)ist-imit : Soft>oint-imit

1l lmite menor del ngulo permitido alrededor del eje primario del characterjoint. 1l lmite es relativo al ngulo de los dos rigid!ody con el que comen'" la simulaci"n. /a varia!le es de tipo 2oft=oint/imit, que es una estructura con estos valores+

limit+ 1l lmite de posici"n u ngulo del joint. spring+ 2i es mayor que cero, el lmite es soft. 1l spring retornar el joint a su posici"n inicial. damper+ 2i spring es mayor que cero, el lmite es soft. !ounciness+ ?uando el joint golpea el lmite, esta varia!le puede esta!lecerse para impedir un re!ote.

highT.istLimit:

var highT)ist-imit : Soft>oint-imit

1l lmite superior altededor del eje primario del characterjoint. 1l lmite es relativo al ngulo de los dos rigid!ody con el que comen'" la simulaci"n.

s.ing8Limit: var s)ing.-imit : Soft>oint-imit

1l lmite alrededor del eje primario del characterjoint. 1l lmite es simtrico, as que un valor de 7E limitara la rotaci"n entre $7E y 7E. 1l lmite es relativo al ngulo de los dos rigid!odys con que empe'" la simulaci"n.

s.ing9Limit: var s)ing1-imit : Soft>oint-imit

1l lmite alrededor el eje primario del joint del character.

/amenta!lemente, por la especificidad de esta clase en estos momentos no podemos utili'ar ejemplos, pero cuando estemos a un nivel ms avan'ado me comprometo volver a esta clase para verla con ms profundidad y claridad -y si yo me olvido, que alguien me lo recuerde, please.

40. CLASE BE&AVIOUR

#ara comprender el sentido de la clase Behaviour he considerado que lo mejor era traer a la vista de nuevo el organigrama general que estuvimos comentando en las primeras lecciones. 2i os fijis ya hemos estudiado todas las clases que deriva!an de ?omponent, a e(cepci"n de sta, de la que a su ve' deriva otra serie de clases -que son las

que estudiaremos a continuaci"n.. 1(plico todo esto porque la clase Behaviour, como tal, s"lo cuenta con una varia!le -con independencia, o!viamente, de las que hereda de @!ject y ?omponent.. icha varia!le es ena"led: var enabled : boolean

?omo podemos imaginar, esta varia!le solamente ha!ilita o desha!ilita el o!jeto Behaviour -y;o los o!jetos derivados de esta clase. de un gameo!ject. icho de otra forma, tenemos por un lado las clases que derivan directamente de ?omponent -las que ya hemos estudiado. y por otro las que derivan de Behaviour, que heredan lo mismo que las anteriores, ms una varia!le que les permite desha!ilitarse. 1sto es, la diferencia entre, por ejemplo, transform y camera es que la segunda se puede desactivar. 1sto lo podemos compro!ar en el inspector, con la main camera seleccionada+ veremos que ?amera cuenta con un chec8!o( -el equivalente a la varia!le ena!led. y :ransform no. @s suelto este rollo para que entendis que las clases que e(plicaremos a continuaci"n son en esencia de ra' idntica a las 3ltimas que hemos estudiado, con la peculiaridad indicada.

41. CLASE MONOBE&AVIOUR (I)

?omo podris deducir de un mero vista'o a las funciones contenidas en esta clase, estudiarla nos va a llevar un !uen rato. /a clase *ono!ehaviour es uno de los miem!ros destacados del top ten de la A#0 de %nity, as que es vital dominarla con una cierta solvencia. *onoBehaviour es la clase !ase de la que derivan todos los scripts. 9i ms ni menos. Al ser clase !ase, salvo en ?A no hace falta escri!irla e(presamente cuando llamemos a alguna de sus funciones, pues %nity la da por so!reentendida. icho de otra manera, para %nity es lo mismo esto *onoBehaviour.0nvo8e-.

que esto 0nvo8e-.

>amos ya a empe'ar con las funciones de *onoBehaviour+

FUNCIONES:

In2o5e: function Invo9e (method4ame : String time : float) : void

/lama a la funci"n que le pasemos como primer parmetro en el tiempo contado en segundos que le indiquemos como segundo parmetro. Aunque creo que el funcionamiento de esta funci"n es !astante evidente, nada mejor que verlo con un ejemplo. , previamente a empe'ar a disear el mismo, vamos a reorgani'ar nuestra escena en la interfa' de %nity siguiendo estos pasos+ 5.$ 1liminamos el Fameo!ject ?u!e. 6.$ %!icamos el Fameo!ject ?u!o en $6,E,E. 7.$ 1liminamos el script vinculado a la esfera. X.$ ?olocamos la esfera en 6,E,E. K.$ Asignamos por la va de arrastre *i#rimer2cript en #roject al Fame@!ject #orta2cripts. 2i por lo que sea no has seguido todas las lecciones y en la jerarqua no tienes un gameo!ject con ese nom!re, crea un Fameo!ject vaco y lo !auti'as como #orta2cripts. T.$ o!le clic8 en *i#rimer2cript para a!rir el editor y poder tra!ajar en l. :ecleamos esto+ var original + Fame@!jectC function @tro e/o*ismo-. O 0nstantiate-original, original.transform.position B >ector7.right, original.transform.rotation.C P 0nvo8e-<@tro e/o*ismo<, K.C

2eleccionamos #orta2cripts y en el inspector arrastramos el cu!o hasta el valor de la varia!le @riginal. #ulsamos el play. :ranscurridos cinco segundos, o!servaremos que la funci"n 0nvo8e llama a la funci"n @tro e/o*ismo, que a su ve' crea una instancia clonada de nuestro cu!o una unidad a la derecha. 2i queremos, podemos arrastrar la esfera a la varia!le @riginal, para que sea ella la clonada. %n pro!lema que me he encontrado a la hora de hacer este ejemplo, es que no s si 0nvo8e funciona para llamar a una funci"n que tenga uno o ms parmetros, y en caso afirmativo c"mo se ha de aadir dicho parmetro al string. 2i alguien conoce la respuesta a esto agradecera lo reportara.

42. CLASE MONOBE&AVIOUR (II)

In2o5eRe!eating: function Invo9e7e!eating (method4ame : String time : float re!eat7ate : float) : void

0nvoca la funci"n que le pasamos como string para dentro del n3mero de segundos que le pasamos como segundo parmetro, y una ve' se ejecuta, lo vuelve a hacer cada repeat&ate segundos -el tercer parmetro. >eremos claramente su funcionamiento rehaciendo ligeramente el ejemplo anterior -previamente es mejor que coloquemos la esfera en position.J D 7.+ var original + Fame@!jectC function @tro e/o*ismo-. O var copia + Fame@!ject D 0nstantiate-original, original.transform.position B >ector7.right, original.transform.rotation.C copia.transform.position BD >ector7-:ime.time $ K, E,E.C P 0nvo8e&epeating-<@tro e/o*ismo<, K,5.C

Arrastramos nuestro cu!o para iniciali'ar la varia!le <original< en el inspector, y le damos al play. 9uestro cu!o, pasados los K primeros segundos, empe'ar a clonarse cada segundo. >amos por partes+ /o que hemos hecho es primero declarar una funci"n que $al igual que en el ejemplo anterior$ clona el o!jeto que le hayamos arrastrado a <original< y lo coloca una unidad a la derecha del o!jeto clonado. Asimismo, para que no se nos amontonen los cu!os en el mismo punto, aprovechamos que la funci"n 0nstantiate devuelve el o!jeto clonado, para almacenarlo en una varia!le $que llamamos copia$ y lo que hacemos es que cada nuevo o!jeto instanciado se mueva una unidad ms a la derecha que el anterior, cosa que o!tenemos aprovechando que :ime.time hace precisamente eso, avan'ar una unidad cada segundo. Al resultado le restamos K, que es el n3mero de segundos que transcurren hasta que empie'an a clonarse los cu!os, por o!ra y gracia del segundo parmetro de 0nvo8e&epeating. 2i no le restramos ese K, el primer muro se clonara K unidades a la derecha del cu!o clonado. @!servamos que, centrndonos en la funci"n estudiada, que 0nvo8e&epeating llama a la funci"n transcurridos K segundos $en este caso$ y pasados los mismos, se repite de forma infinita cada segundo -7er parmetro..

CancelIn2o5e: function 8ancelInvo9e () : void function 8ancelInvo9e (method4ame : String) : void

:al como seguro que estaris suponiendo, ?ancel0nvo8e cancela las funciones que hayan sido invocadas por las dos funciones anteriores para un determinado script. /a primera variaci"n de esta funci"n no tiene parmetros, y al llamarse cancela todas las funciones 0nvo8e e 0nvo8e&epeating del script. /a segunda variaci"n de la funci"n s"lo cancelar la funci"n de dicho tipo que coincida con el nom!re que se le pasa como parmetro. Arreglemos un poco ms nuestro script dndole al usuario la posi!ilidad de cancelar la clonaci"n de cu!os. var original + Fame@!jectC function @tro e/o*ismo-. O var copia + Fame@!ject D 0nstantiate-original, original.transform.position B >ector7.right, original.transform.rotation.C

copia.transform.position BD >ector7-:ime.time $ K, E,E.C P 0nvo8e&epeating-<@tro e/o*ismo<, K,5.C function %pdate-. O if -0nput.FetButton -<Mire5<.. ?ancel0nvo8e-.C P

1s la misma funci"n anterior, s"lo que con el aadido que le hemos puesto, la funci"n update compro!ar cada frame si el usuario ha pulsado la tecla definida en input como Mire5. 2i tenemos la configuraci"n por defecto, de!era ser el ctrl i'quierdo o el !ot"n i'quierdo del rat"n.

IsIn2o5ing: function IsInvo9ing (method4ame : String) : boolean

1ste primer prototipo de la funci"n devuelve true si hay alg3n invo8e pendiente de la funci"n que se introduce como parmetro.

function IsInvo9ing () : boolean

1n esta segunda modalidad devuelve true si alg3n invo8e pendiente en este script.

43. CLASE MONOBE&AVIOUR (III)

StartCoro+tine: function Start8oroutine (routine : I6numerator) : 8oroutine

Antes de entrar a anali'ar esta funci"n quisiera e(plicar aunque fuera de forma superficial lo que es una corutina y c"mo son tratadas por %nity. %na corutina es una funci"n $que individuali'amos con la pala!ra clave yield$ que puede suspender su ejecuci"n hasta que una instruction dada $que tam!in contendr la pala!ra clave yield$ termine. >emoslo con un ejemplo sacado del manual de referencia de %nity+ ;;0mprime 2tarting E.E print -<2tarting < B :ime.time.C ;Z 2e llama a continuaci"n a la funci"n _aitAnd#rint como coroutine, cosa que se consigue anteponiendo la pala!ra clave yield. Al hacer esto permitimos que la funci"n se pueda suspender por una instrucci"n yield. #or lo tanto, el flujo del script se va a la funci"n 4aitandprint, donde se encuentra con una instrucci"n yield que le dice que espere cinco segundos, luego imprimir ]_aitand#rint K.E -que ser el tiempo transcurrido desde el inicio del c"mputo. y volver arri!a para imprimir done K.E^ -o un n3mero cercano..Z;

yield _aitAnd#rint-.C print -< one < B :ime.time.C function _aitAnd#rint -. O ;; suspende la ejecuci"n por K segundos yield _aitMor2econds -K.C print -<_aitAnd#rint <B :ime.time.C P

2i no veis clara la diferencia con el proceso secuencial ha!itual, no tenis ms que !orrar la pala!ra yield que est antes de la llamada a la funci"n. 2i hacis eso, el programa empe'ar escri!iendo <starting E<, !ajar a la siguiente instrucci"n, donde se encuentra con la funci"n _aitAnd#rint, que le indica que no va a hacer nada durante cinco segundos, as que pasar inmediatamente a la siguiente declaraci"n e imprimir < one E<, para luego, cinco segundos despus, imprimir por fin <_aitandprint K<.

Bien. ?on estas nociones vamos ya a la funci"n que nos ocupa, 2tart?oroutine. ?omo su nom!re indica, inicia una corrutina cuya ejecuci"n puede ser pausada en cualquier momento usando una instrucci"n yield. #rogramando en javascript, no es necesario escri!ir 2tart?oroutine, ya que el compilador la dar por supuesta. >eamos un segundo ejemplo sacado igualmente del manual de referencia de %nity. 1n este ejemplo, a diferencia del anterior, vamos a invocar una corrutina que no suspender la ejecuci"n de la funci"n que se desarrolla en paralelo+ function 2tart-. O ;; $ espus de E segundos imprimir <2tarting E.E< ;; $ espus de E segundos, imprimir <Before _aitAnd#rint Minishes E.E< ;; $ espus de 6 segundos imprimir <_aitAnd#rint 6.E< ;;1mpe'amos -funci"n 2tart. imprimiendo ]2tarting E.E^ print -<2tarting < B :ime.time.C ;Z Ahora vamos a iniciar la funci"n _aitAnd#rint como coroutine -en paralelo., pero sin suspender el flujo de llamadas a funciones que se puedan seguir dando en el hilo principal. 2i hu!iramos querido suspenderlo, hu!iramos utili'ado la f"rmula del ejemplo anterior, y hu!iramos antepuesto la pala!ra clave yield a la llamada a la funci"n. /o que sigue podra tam!in ha!erse escrito -en javascript. as+ _aitAnd#rint-6.E. y el compilador aadira el 2tart?oroutine por ti automticamente.Z; 2tart?oroutine-_aitAnd#rint-6.E..C ;Z?omo no hemos interrumpido el flujo principal con yield, la declaraci"n que viene ahora se ejecutar antes que la la funci"n anterior, puesto que la anterior ha de esperar dos segundos y el print que viene ahora no.Z; print -<Before _aitAnd#rint Minishes < B :ime.time.C P function _aitAnd#rint -4ait:ime + float. O ;; suspende la ejecuci"n por los segundos que le fijemos en 4ait:ime yield _aitMor2econds -4ait:ime.C print -<_aitAnd#rint <B :ime.time.C P

/a funci"n 2tart?oroutine tiene una segunda modalidad+ function Start8oroutine (method4ame : String value : object & null) : 8oroutine

1s como la funci"n anterior, pero usando un string. 1sta variante tiene una mayor so!recarga de procesamiento, pero es la 3nica que se puede detener con 2top?oroutine.

>amos a reali'ar otro ejemplo en el que , aparte de usar la variante con string de la funci"n, aprovecharemos para ilustrar de nuevo otra posi!ilidad que nos dan este tipo de instrucciones ,ield. 1l script ejecuta la funci"n o2omething, que dispara un !ucle. Al siguiente frame el script se detendr un segundo al toparse con la instrucci"n yield, pasar al yielf 4aitforseconds, esperar un segundo y luego se detendr. function 2tart -. O 2tart?oroutine-< o2omething<, 6.E.C yield _aitMor2econds-5.C 2top?oroutine-< o2omething<.C P function o2omething -some#arameter + float. O 4hile -true. O print-< o2omething /oop<.C ;; etiene la ejecuci"n de esta corutina y vuelve al loop principal hasta el ;;siguiente frame. yieldC P P

Sto!Coro+tine: function Sto!8oroutine (method4ame : String) : void

?omo hemos visto en el ejemplo anterior, detiene las corrutinas con el nom!re que le suministramos como parmetro iniciadas en este script. icho nom!re de funci"n lo hemos de pasar como un string, y no hemos de olvidar que s"lo las corrutinas con el nom!re indicado que se hayan iniciado mediante la variante string de 2tart?oroutine -la segunda modalidad de las anteriormente vistas. podrn ser detenidas con 2top?oroutine.

Sto!AllCoro+tines: function Sto!*ll8oroutines () : void

etiene todas las corrutinas que estn corriendo en ese script.

44. CLASE MONOBE&AVIOUR (IV)

1l resto de funciones que nos quedan por estudiar de la clase *onoBehaviour -que son unas cuantas. son com3nmente conocidas como <funciones so!reescri!i!les<. 1l nom!re les viene dado porque estas funciones tienen, con respecto a las <standard<, la peculiaridad de que nos permiten disear nosotros su contenido. #or e(plicarlo de alguna manera, la firma de estas funciones, que es lo que nos !rinda %nity, supondran el cundo y lo que nosotros escri!iremos ser el qu y el c"mo. 0ncidentalmente, y para entender un poco mas la plyade de funciones que vienen a continuaci"n, vamos a e(plicar el orden en que %nity iniciali'a los distintos elementos que lo componen cada ve' que se carga una escena en el juego+ $#rimero se cargan los o!jects -game o!jects y components.. $Acto seguido se cargan los scripts que van vinculados a estos o!jects, y una serie de funciones -las que veremos a continuaci"n. son llamadas en un orden especfico+ 5.$ A4a8e. 6.$ 2tart. 7.$%pdate;Mi(ed%pdate. X.$/ate%pdate.

U!date: function :!date () : void

1sta funci"n, con la que ya hemos lidiado en alguna ocasi"n, es llamada cada frame, si el *ono!ehaviour -script que la invoca. est activo. 1s la funci"n ms usada en los scripts, si !ien arrastra el inconveniente de que cada ordenador puede tener un framerate distinto, por lo que la misma instrucci"n de movimiento, por ejemplo, dara pie a diferentes velocidades dependiendo del framerate de cada uno -con resultados catastr"ficos, sin ir ms lejos, en juegos online para varios jugadores.. #ara transformar las unidades de actuali'aci"n de la funci"n de frames a segundos se utili'a :ime.delta:ime.

LateU!date: function -ate:!date () : void

/ate%pdate es llamado una ve' todas las funciones %pdate han sido llamadas. 1sto nos permite ordenar la ejecuci"n de scripts. #or ejemplo, una cmara que sigue a un o!jeto de!era implementarse en un late%pdate, pues ca!e que el o!jeto al que sigue se inicialice con un determinado movimiento en update, movimiento que de!era tener en cuenta la cmara.

Fi)edU!date: function Fi/ed:!date () : void

1sta funci"n se ejecuta cada cierto n3mero preesta!lecido y fijo de frames, lo que hace que no presente los pro!lemas de update. 2e de!e utili'ar en aquellos scripts que impliquen un componente de fsicas, y so!re todo, siempre se ha de utili'ar cuando haya que aadir una fuer'a a un &igid!ody.

A.a5e: function *)a9e () : void

A4a8e es llamada cuando se inicia el script, osea, cuando se carga la escena, y justo despus de que se carguen los o!jects -gameo!jects y components. a que el script hace referencia. e tal manera, es 3til para iniciali'ar varia!les o estados del juego antes de que el juego empiece, referenciando si es preciso a los o!jects a que hacen menci"n -y que ya ha!rn sido como decimos iniciali'ados previamente.. #or ejemplo, dentro de un a4a8e puedes tranquilamente usar Fameo!ject.Mind_ith:ag. ?ada funci"n a4a8e para gameo!jects es llamada de forma aleatoria, ra'"n por la cual se utili'a A4a8e para colocar referencias entre scripts -pej, el script I llamar al script ,. pero se ha de utili'a 2tart para pasar informaci"n de un lado a otro -pej+ 1l script ( le pasa el valor K al script ,., ya que A4a8e es llamada siempre antes que 2tart y as al mandar valores va 2tart nos aseguramos de que las relaciones entre scripts estn ya esta!lecidas va A4a8e. #or 3ltimo, indicar que A4a8e no puede formar parte de una corrutina, y que ser llamada aunque en el inspector la instancia del script est desha!ilitada;desmarcada.

Start: function Start () : void

1s llamada despus de A4a8e y antes de %pdate. Al igual que a4a8e, s"lo es llamada una ve' a lo largo de toda la vida del script. Aparte del momento en que son llamadas, 2tart se diferencia de A4a8e en que 2tart s"lo es llamada si la instancia del script est ha!ilitada, esto es, tiene su chec8!o( marcado en el inspector. As, cuando un gameo!ject es inicialmente usado en una escena esta funci"n es llamada automticamente.

Reset: function 7eset () : void

&esetea a los valores por defecto, restaurando los valores originales. 1sta funci"n es llamada cuando se pulsa reset en el inspector o cuando se aade un componente por primera ve'.

45. CLASE MONOBE&AVIOUR (V)

On-o+seEnter: function On3ouse6nter () : void

1sta funci"n es llamada cuando el cursor entra en un collider o un F%01lement. >emoslo con un ejemplo muy sencillo. :ecleamos+ function @n*ouse@ver-.O e!ug./og-<1l mouse est so!re el o!jeto < B game@!ject.name.C

Arrastramos el script al cu!o. #ulsamos play y o!servaremos que cuando el cursor est so!re el cu!o, se imprime la frase de!ajo de la ventana game.

1sta funci"n no ser llamada en o!jetos que pertene'can a 0gnore &aycast layer. @n*ouse1nter puede ser una corrutina, siempre que utilicemos una instrucci"n ,ield en la funci"n, y el evento ser enviado a todos los scripts vinculados con el collider o F%01lement

On-o+seO2er: function On3ouseOver () : void

1sta funci"n es llamada cada frame en la que el mouse permane'ca so!re el ?ollider o F%01lement, a diferencia de on*ouse1nter, que s"lo se dispara cuando entra el mouse. ?omo esta funci"n se actuali'a cada frame, podemos hacer cosas como la del ejemplo+ function @n*ouse@ver -. O renderer.material.color BD ?olor-E.5, E, E. Z :ime.delta:imeC P

2i pulsamos play y mantenemos el cursor so!re el cu!o, lentamente ste se ir tornando de color roji'o, de!ido al paulatino aumento del componente & -red. de su &FB. @n*ouse@ver puede ser, como @n*ouse1nter, una corrutina, simplemente utili'ando la declaraci"n yield en la funci"n

On-o+seE)it: function On3ouse6/it () : void

1sta funci"n es llamada cuando el rat"n ya no esta so!re un F%01lement o un ?ollider. #odemos completar con ella el script anterior+ function @n*ouse@ver -. O renderer.material.color BD ?olor-E.5, E, E. Z :ime.delta:imeC P function @n*ouse1(it -. O renderer.material.color D ?olor.4hiteC P

?uando se retira el mouse del cu!o, ste retorna a su color !lanco inicial. ?omo las precedentes, la funci"n no es llamada en o!jetos que tienen el 0gnore &aycast /ayer y puede formar parte de una coroutine.

On-o+seDo.n: function On3ouseDo)n () : void

1s llamada cuando el usuario pulsa el !ot"n del mouse so!re un F%01lement o ?ollider. #or seguir con el ejemplo anterior, podramos aadir al script+ function @n*ouse@ver -. O renderer.material.color BD ?olor-E.5, E, E. Z :ime.delta:imeC P function @n*ouse1(it -. O renderer.material.color D ?olor.4hiteC P function @n*ouse o4n -. O renderer.material.color D ?olor.!lueC P

Al presionar el !ot"n del rat"n, el cu!o se torna de color a'ul. A esta funci"n le es de aplicaci"n lo indicado para las precedentes en relaci"n con 0gnore &aycast y la posi!ilidad de ser una corrutina.

4!. CLASE MONOBE&AVIOUR (VI)

2eguimos con las funciones so!reescri!i!les. On-o+seU!: function On3ouse:! () : void

1sta funci"n es llamada cuando el usuario li!era;suelta el !ot"n del rat"n. 1s llamada incluso si el mouse no est al soltar el !ot"n so!re el mismo F%01lement o ?ollider en que esta!a cuando el !ot"n fue presionado. -#ara que tuviera ese comportamiento ha!ra que usar @n*ouse%pAsButton, que vamos a e(aminar a continuaci"n.

On-o+seU!AsB+tton: function On3ouse:!*s=utton () : void

?omo anticip!amos en la funci"n anterior, sta es llamada s"lo cuando el mouse es li!erado estando so!re el mismo F%01lement o ?ollider en el que fue presionado.

On-o+seDrag: function On3ouseDrag () : void

1s llamada esta funci"n cuando el usuario presiona el !ot"n del mouse so!re un F%01lement o un ?ollider y todava lo mantiene presionado. 1s llamada cada frame mientras el !ot"n siga presionado.

OnTriggerEnter# OnTriggerE)it# OnTriggerSta%# OnCollisionEnter# On CollisionE)it# OnCollisionSta%:

:odas estas funciones ya fueron e(plicadas en la clase ?ollider, as que a la misma me remito.

OnControllerCollider:it: function On8ontroller8olliderHit (hit : 8ontroller8olliderHit) : void

1s llamada cuando nuestro character controller golpea un collider mientras reali'a un movimiento, de tal manera que muchas veces esta funci"n sirve para empujar o!jetos cuando colisionan con el personaje. )agamos unas modificaciones previas al pertinente ejemplo en la interfa' de %nity. 5.$ 1liminamos el script vinculado a #orta2cripts, para que no nos lance errores. 6.$ Aadimos un ?haracter?ontroller al cu!o, reempla'ando cuando nos lo pida %nity el antiguo !o(?ollider. 7.$ esconectamos provisionalmente el !o(?ollider del gameo!ject 2uelo, dado que en caso contrario ser el suelo el primer collider con el que se tope nuestra funci"n. X.$ 1scri!imos este script, que le vincularemos al cu!o+ var mi?har?on + ?haracter?ontrollerC mi?har?on D Fet?omponent-?haracter?ontroller.C function %pdate-. O mi?har?on.*ove->ector7-5 Z :ime.delta:ime ,E,E..C P function @n?ontroller?ollider)it-te:oco. O te:oco.rigid!ody.AddMorce->ector7-E,E,KE..C P

#lay. 9uestro character controller -tam!in conocido como cu!o. avan'a hacia la i'quierda a ra'"n de un metro por segundo, y cuando se topa con un controller -la esfera., algunos datos de la colisi"n y sus intervinientes son pasador al 3nico parmetro de la funci"n, que es de la clase ?ontroller?ollider)it. /a clase ?ontroller?ollider)it, aunque la veremos ms en profundidad en otra lecci"n, cuenta con una serie de varia!les, entre las que destacan+ controller+ 1l character controller que golpea el collider -nuestro cu!o en el ejemplo. collider+ 1l collider que es golpeado por el character controller -la esfera, aqu. rigid!ody+ 1l rigid!ody que ha sido golpeado por el character controller, si es que el collider que golpeamos tiene rigid!ody -en el ejemplo lo usamos porque la esfera tiene rigid!ody.. game@!ject+ 1l game o!ject que ha sido golpeado por el character controller. transform+ 1l transform que ha sido golpeado por el controller. point+ 1l punto de impacto en coordenadas glo!ales. normal+ 1l normal de la superficie que ha sido colisionado en coordenadas glo!ales. move irection+ Apro(imadamente la direcci"n desde el centro de la cpsula del character controller al punto que tocamos. move/ength+ /a distancia que el character controller ha recorrido hasta golpear con el collider.

1ntonces, volviendo al ejemplo, a travs del parmetro de tipo ?ontroller?ollider)it que hemos dado en llamar te:oco, accedemos a la varia!le rigid!ody, que o!viamente se corresponde con el rigid!ody de la esfera, y a partir de ah le asignamos un comportamiento, que en este caso es meramente despla'arse en el eje J.

On7ointBrea5: function On>oint=rea9 (brea9Force : float) : void 1sta funci"n ya la e(plicamos en la lecci"n correspondiente a la clase =oint.

On/articleCollision: function On5article8ollision (other : GameObject) : void

1sta funci"n es llamada cuando una partcula choca con un collider. #uede por tanto usarse para computar el dao reci!ido por un gameo!ject cuando choca con partculas. 1ste mensaje es enviado a todos los scripts vinculados con el _orld#article?ollider y al collider que fue colisionado. 1l mensaje es s"lo enviado si ha!ilitamos 2end?ollision*essage en el inspector del _rold#article?ollider. Guedmonos de momento con esta sucinta informaci"n, que ya tra!ajaremos cuando nos toque lidiar con la clase #article1mitter.

4". CLASE MONOBE&AVIOUR (VII)

OnBecameVisi"le: function On=ecame"isible () : void

2e llama a esta funci"n cuando el renderer se convierte en visi!le por alguna cmara. 1ste mensaje se enva a todos los scripts relacionados con el renderer. 1sta funci"n y su opuesta f@nBecame0nvisi!le$ son 3tiles para evitar c"mputos que son s"lo necesarios cuando el o!jeto es visi!le.

OnBecameIn2isi"le: function On=ecameInvisible () : void

1s llamada cuando el renderer ya no es visi!le por ninguna cmara.

OnLe2el;asLoaded: function On-evel?as-oaded (level : int) : void

1sta funci"n es llamada despus de que un nuevo level ha sido cargado. 1l parmetro level de la funci"n es el level que ha sido cargado. 2i quiere ver el ndice de levels de su juego, use el men3 MileDLBuild settings.

OnEna"le: function On6nable () : void

1s llamada cuando el o!jeto pasa a estar ha!ilitado y activo.

OnDisa"le: function OnDisable () : void

1s llamada cuando el o!jeto se convierte en desha!ilitado o inactivo. :am!in cuando el o!jeto es destruido y puede ser usada la funci"n para procesos de limpie'a. ?uando los scripts son recargados despus de que la compilaci"n haya aca!ado, @n isa!le se llamar seguida por @n1na!le despus de que el script haya sido cargado.

OnDestro%: function OnDestro% () : void

1s llamada cuando el *onoBehaviour -script. es destruido. 2"lo puede ser llamada para gameo!jects que previamente hayan estado activos.

On/reC+ll: function On5re8ull () : void

1s llamada antes de que la cmara deseche la escena. ?ulling es un proceso que determina qu o!jetos son visi!les en la cmara, y @n#re?ull es llamada justo antes de dicho proceso. 1sta function es llamada s"lo si el script est vinculado con la cmara y est activado. 2i queremos cam!iar los parmetros de visi"n de la cmara -tal como field@f>ie4. lo tendremos que hacer aqu. /a visi!ilidad de los o!jetos de la escena se determinar en !ase a los parmetros de la cmara despus de la funci"n @n#re?ull.

On/reRender: function On5re7ender () : void

1s llamada antes de que la cmara empiece a renderi'ar la escena. 2"lo se llama si el script est vinculado a la cmara y activo. 1s importante comprender que si cam!iamos con esta funci"n los parmetros de visi"n de la cmara, como por ejemplo field@f>ie4, s"lo tendrn efecto el siguiente frame, por lo que hay que hacerlo mejor en la funci"n @n#re?ull, como hemos dicho antes.

On/ostRender: function On5ost7ender () : void

1s llamada despus de que la cmara aca!a de renderi'ar la escena, siempre que el script est vinculado con la cmara y activo.

OnRenderO"'ect: function On7enderObject () : void

1s llamada despus de que la cmara renderi'a la escena. 2e diferencia de @n#ost&ender en que @n&ender@!ject es llamada para cada o!jeto que tenga un script con la funci"n, sin importar si est vinculado a una cmara o no.

On;illRenderO"'ect: function On?ill7enderObject () : void

1sta funci"n es llamada una ve' por cada cmara si el o!jeto es visi!le. 1s llamada durante el proceso de culling -que podramos traducir por elecci"n o desechamiento., justo antes de renderi'ar todos los o!jetos seleccionados. #odra usarse por tanto esta funci"n para crear te(turas que pudieran actuali'arse s"lo si el o!jeto a renderi'ar es en realidad visi!le.

4#. CLASE MONOBE&AVIOUR (VIII)

OnGUI: function OnG:I () : void

1s llamada para renderi'ar y manejar eventos F%0. 1sto significa que nuestra implementaci"n de @nF%0 podra ser llamada varias veces por frame, a ra'"n de una llamada por evento. 1sto lo tra!ajaremos ms cuando estudiemos las clases 1vent y F%0.

OnRenderImage: function On7enderImage (source : 7enderTe/ture destination : 7enderTe/ture) : void

1s llamada cuando se tiene toda la informaci"n de renderi'ado de una imagen, permitiendo modificar la imagen final procesndola con filtros. /a imagen entrante -source. es de tipo render:e(ture y el resultado lo almacenamos en otro parmetro del mismo tipo -destination en el prototipo de la funci"n.. ?uando hay m3ltiples filtros de imagen vinculados a la cmara, estos procesan la imagen secuencialmente, pasando el primer filter destination como source del siguiente filtro. 1ste mensaje ser enviado a todos los scripts vinculados a la cmara.

OnDra.Gi*mosSelected: function OnDra)Gi0mosSelected () : void

0mplementa esta function si quieres di!ujar gi'mos s"lo si el o!jeto est seleccionado. >amos a verlo con un ejemplo simple. 1s necesario para ver el efecto que previo a darle al play el cu!o no est seleccionado. function @n ra4Fi'mos2elected -. O Fi'mos.color D ?olor.4hiteC Fi'mos. ra4?u!e -transform.position, >ector7 -6,6,6..C P

9o nos fijemos demasiado en los elementos de la clase Fi'mos, que ya veremos en su momento. e momento s"lo necesitamos sa!er que , cuando se seleccione el cu!o $!ien en la jerarqua, !ien en la escena, !ien con el juego activado o incluso sin que el juego est activado$ nos aparecer un gi'mo que se corresponder a un cu!o !lanco de 6 unidades de lado. #ro!moslo.

OnDra.Gi*mos: function OnDra)Gi0mos () : void

0mplementa esta funci"n si quieres di!ujar gi'mos que apare'can siempre di!ujados. 1sto te permite rpidamente seleccionar o!jetos importantes en tu escena, por ejemplo. 9otad que esta funci"n usa una posici"n del rat"n que es relativa a la vista de la escena. #ara mostrar esto en un ejemplo necesitamos unos pasos previos+ 5.$ Buscad por la red la imagen de una !om!illa -no demasiado grande.. 6.$ /a guardis y le asignis el nom!re <Bom!illa< -Mijaros en la e(tensi"n de la

imagen. 2i es distinta de la que voy a utili'ar yo, cam!iadla en el script. 7.$ Buscis la carpeta de nuestro proyecto %nity, y arrastris la imagen dentro de la carpeta assets. X.$ 1n la interfa', hacemos clic8 derecho so!re #royecto DL?reate DLMolder. /lamamos a la nueva carpeta Fi'mos -es donde por defecto !uscar %nity. K.$ 1n #royecto, arrastramos la imagen dentro de esta carpeta. T.$ o!le clic8 so!re *i#rimer2cript. :ecleamos+ function %pdate-.O transform.:ranslate-$>ector7.right Z :ime.delta:ime.C P function @n ra4Fi'mos-. O Fi'mos. ra40con -transform.position B >ector7-E,K,E. , <Bom!illa.jpeg<.C P

2i hemos seguido correctamente estos pasos, cu!o e imagen de!eran despla'arse al unsono hacia la i'quierda, tal que as+

50. CLASE CAMERA (I)

Bienvenid@s a otra de las clases importantes de %nity. /a clase cmera le permite al jugador interactuar con tu juego. /a cmara en %nity es un dispositivo a travs del cual el jugador ve el mundo. )emos de diferenciar desde el primer momento, y ah residen no pocas confusiones de los recin llegados a %nity, entre pantalla y cmara. Am!as son cosas diferentes y tienen una unidad de medida distinta+ /a unidad de medida de la pantalla est definida en p(eles. /a esquina i'quierda$inferior de la pantalla es -E,E., la derecha$superior est contenida en las varia!les -pi(el_idth,pi(el)eight., que representan la anchura y altura de la pantalla respectivamente. /a posici"n J estara en unidades glo!ales contadas desde la cmara.

2i la unidad de medida es relativa a la cmara, la esquina i'quierda$inferior de la cmara es -E,E. y la derecha$superior -5,5.. /a posici"n J estara en unidades glo!ales desde la cmara. ?on esto en mente, empecemos+

VARIABLES: (ieldO(Vie.: var fieldOf"ie) : float

>aria!le que contiene el campo de visi"n de la cmara en grados. 2e referira al campo de visi"n vertical, ya que el hori'ontal vara dependiendo del vie4portgs aspect ratio. 1l campo de visi"n es ignorado cuando la cmara est en modo ortogrfico. Antes de empe'ar con los ejemplos, vamos a retocar un par de cosillas en la interfa' de %nity. 1n primer lugar, en #royecto le damos al !ot"n derecho del rat"n so!re la carpeta Fi'mosDL elete, para deshacernos de la !om!illa. 9os aseguramos de que el cu!o est en posici"n $6,E,E. 1liminamos el script vinculado al cu!o. 9os aseguramos de que la cmara no est en modo ortogrfico, sino en perspectiva. o!le clic8 en *i#rimer 2cript+ ?amera.main.field@f>ie4 D 6EC

Arrastramos el script a #orta2cripts en la =erarqua. 9otemos antes que nada que en el script nos estamos refiriendo a la cmara principal. 2i quisiramos que el script afectara a otra cmara distinta, por un lado de!eramos quitarle el <main< del script y por otro lo tendramos que arrastrar a la cmara que queremos afectar por ste. >amos a pro!arlo, para que no haya dudas, pero antes dadle al play y compro!ar c"mo el campo de visi"n, que por defecto es TE, pasa a ser 6E y $aunque pare'ca al principio poco intuitivo$ al tener un ngulo menor de visi"n, dicho campo reducido es ampliado para que ocupe toda la pantalla. 1sto a muchos les recordar las fotos en las !odas+ cuanta ms gente queremos a!arcar -ms campo de visi"n. ms lejos tenemos que tirar la foto. #ero ha!amos prometido que aplicaramos el ejemplo a una cmara no principal, as que ah vamos. Fameo!jectDL?reate otherDL?amera. /lamamos a la ?amera <?amara 6<. Ahora la u!icaremos en la siguiente posici"n;rotaci"n+ #osicion+$E.T,5K,5 &otacion+YK,E,E ?on la cmara 6 seleccionada, le damos al play y o!servamos nuestro pequeo mundo desde otra perspectiva. 9os daremos cuenta de que %nity nos lan'a un mensaje, avisndonos de que tenemos dos receptores -listeners. de audio en la escena. 1sto es porque por defecto cada cmara tiene un Audio /istener para recoger el sonido adems de la imagen. #ara evitar pro!lemas, eliminamos el Audio/istener de la cmara 6 en el inspector. >ale, y ahora montemos otro miniscript para la segunda cmara. )acemos do!le clic8 en *i2egundo2cript -ya que el primero lo tenemos ocupado. y tecleamos+ camera.field@f>ie4 D 6EC

Arrastramos este script a la ?amara 6 -si lo arrastrramos al #orta2cripts no funcionara, ya que no sa!ra a qu cmara ha de afectar, salvo que creramos una varia!le <e(puesta< de tipo ?amera a la que arrastrar esta y etc, etc, aunque para lo que queremos hacer es ms c"modo el mtodo primero. /e damos al play y o!servaremos que funciona. Aprovecho para comentaros una cosilla que seguro que la mayora ya sa!e. ?ada cmara al ser creada tiene una varia!le -depth, que luego veremos. que esta!lece la prioridad de cada una. ?uanto ms alto el valor de depth, ms prioridad tiene la cmara. 2i os fijis en el inspector, la cmara principal de!era tener la varia!le depth en $5, y camara 6 en E. 1s por ello que cuando le damos al play, la vista que nos aparece es la que recoge la cmara 6. 2i quisiramos retomar a vista gra!ada por la cmara principal, no tendramos ms que darle un valor a depth superior al del resto de cmaras.

51. CLASE CAMERA (II)

nearCli!/lane: var near8li!5lane : float

1l plano de recorte de cerca. ?ualquier cosa que se halle ms cerca de la cmara de la distancia esta!lecida en esta varia!le no se mostrar en la cmara. >emoslo con un ejemplo un poco e(tremo. 2i a *i2egundo2cript lo dejamos como sigue... camera.near?lip#lane D 57C

... o!servaremos que todo lo que se halle a menos de 57 metros de la cmara ser recortado.

(arCli!/lane: var far8li!5lane : float

1l plano de recorte de lejos. ?ualquier cosa que se halle ms lejos de la cmara de la distancia esta!lecida en esta varia!le no se mostrar en la cmara. #ro!ad cam!iar en nuestro ejemplo el <near< por el <far<, para o!tener una especie de negativo de la toma anterior.

rendering/ath: var rendering5ath : 7endering5ath

0ndica el tipo de renderi'ado de entre los que contempla la enum &endering#ath -%se#layer2ettings, >erte(/it, Mor4ard y eferred/ighting.. esde el inspector, con la cmara en uso seleccionada, podemos intercam!iar entre las cuatro posi!ilidades para captar sus matices.

act+alRendering/ath: var actual7endering5ath : 7endering5ath

>aria!le de s"lo lectura que contiene el rendering path que se est usando.

orthogra!hicSi*e:

var orthogra!hicSi0e : float

1l campo de visi"n de la cmara cuando est en modo ortogrfico. 1n el pr"(imo ejemplo colocamos a la camara 6 primero en modo ortogrfico, y le fijamos luego un tamao de 7, de tal forma que al tener poco campo de visi"n ample los o!jetos enfocados. camera.orthographic D trueC camera.orthographic2i'e D 7C

#odramos hacer lo mismo con la cmara principal modificando *i#rimer2cript y aadiendo <*ain<. &ecordemos que con la cmara principal no es preciso que el script se incluya en el gameo!ject main?amera. ?amera.main.orthographic D trueC ?amera.main.orthographic2i'e D 7C

orthogra!hic: var orthogra!hic : boolean

>aria!le de tipo !ooleano que indica si la cmara est en modo ortogrfico -true. o en perspectiva -false. y que permite pasar de uno a otro. ?omo ya hemos visto, cuando esta varia!le esta en true, el campo de visi"n de la cmara se define por orthographic2i'e, y cuando est en false por field@f>ie4.

de!th: "ar de!th : float

/a profundidad de la cmara en el orden de renderi'ado de las cmaras. /as cmaras con profundidad ms !aja son renderi'adas antes de las cmaras con profundidad ms alta. 2i tienes varias cmaras, usa este control para decidir el orden en el que las cmaras mostrarn la escena si algunas de ellas no cu!ren la totalidad de la pantalla.

as!ect: var as!ect : float

>aria!le en la que se guarda;coloca la proporci"n de aspecto -aspect ratio., que es el nom!re con que se conoce a la anchura dividida por la altura de la cmara. #or defecto, el aspect ratio es calculado automticamente tomando como !ase la el aspect ratio de la pantalla. 1sto es as incluso si la cmara no est renderi'ando el rea entera. 2i modificas el aspect ratio de la cmara, el valor permanecer hasta que llames a la funci"n camera.&esetAspect-..

c+lling-as5: var culling3as9 : int

1s usada para renderi'ar de manera selectiva partes de la escena. 2i el layer*as8 del gameo!ject -que veremos a no mucho tardar. y el culling*as8 de la cmara son cero, entonces el game o!ject ser invisi!le para esa cmara. 1l

layer*as8 es parecido al sistema de capas de Blender, que !rinda la posi!ilidad de arrastrar o!jetos a una capa diferente. ?on esto se consigue, por ejemplo, que o!jetos pertenecientes a una fase un poco ms avan'ada del juego no sean mostrados hasta que permitamos a la cmara renderi'ar los relativos a esa capa.

"ac5gro+ndColor: var bac9ground8olor : 8olor

>aria!le que indica el color con el cual la pantalla ser completada.

52. CLASE CAMERA (III)

rect:

var rect : 7ect

1sta!lece qu parte de la pantalla esta la cmara renderi'ando. icha parte de la pantalla es fijada a travs de una instancia de la estructura &ect, en coordenadas normali'adas. #or coordenadas normali'adas nos referimos a que los valores en el rango del rect irn de E,E -i'quierda,a!ajo. a 5,5 -derecha,arri!a. As, si queremos que la cmara a la que vinculamos el script renderice toda la pantalla, meramente haremos lo siguiente. 1ditamos *i2egundo2cript -que es el que tenemos vinculado a ?amara 6. y escri!imos+ camera.rect D &ect -E, E, 5, 5.C

:ratndose de coordenadas normali'adas, lo que estamos pidindole aqu a %nity es que lo que est captando la cmara 6 se nos vea en el rectngulo que le pasamos a la varia!le rect, y que en este caso ocupa toda la pantalla -de E,E a 5,5. 2i queremos que lo que capta la cmara dos se nos vea en la esquina superior derecha de la pantalla, calcularamos estas coordenadas+ E,K+ ?orresponde al eje hori'ontal del primer punto, donde E sera i'quierda y 5 derecha. E,K+ ?orresponde al eje vertical del primer punto, donde E sera a!ajo y 5 arri!a. 1l primer punto de nuestro rectngulo, pues, estara justo en el centro de la pantalla. 5+ ?orresponde al eje hori'ontal del segundo punto. 5+ , este es el eje vertical del segundo punto. 1l segundo punto del rectntulo, por lo tanto, est justo en el vrtice derecho superior.

As que podemos rectificar el script anterior, de la manera indicada+ camera.rect D &ect -E.K, E.K, 5, 5.C

e esta manera, lo que est gra!ando cmara dos queda relegado al recuadro superior derecho y, para el resto de la pantalla, entra en acci"n la cmara principal, que ya vimos que por profundidad -depth. es la siguiente en la lista de prioridad. e!era quedar algo parecido a esto+

#ero, Rqu sucedera si no hu!iera ninguna cmara msS. #ro!moslo. 2eleccionamos *ain ?amera y en el inspector desmarcamos el chec8 !o( que aparece junto al componente camera. >olvemos a darle al play, y o!servaremos que la parte de pantalla no incluida en el rectngulo aparece en negro, tal como se muestra a continuaci"n+

!i)elRect: var !i/el7ect : 7ect

0ndica;esta!lece qu parte de la pantalla esta la cmara renderi'ando, pero a diferencia de rect, no lo indica en coordenadas normali'adas, sino en p(eles. #or lo tanto, este script sera el equivalente al anterior+ camera.pi(el&ect D &ect -2creen.4idth;6, 2creen.height;6, 2creen.4idth,

2creen.height.C

!i)el;idth: var !i/el?idth : float

0ndica la anchura de la cmara en p(eles. -2"lo lectura..

!i)el:eight: var !i/elHeight : float

, esta varia!le indica la altura de la cmara en p(eles-s"lo lectura.

2elocit%: var velocit% : "ector#

>aria!le de s"lo lectura que indica la velocidad de la cmara en el espacio glo!al.

53. CLASE CAMERA (IV)

clearFlags: var clearFlags : 8amera8learFlags

0ndica c"mo la cmara completa el !ac8ground. Admite los valores ?amera?learMlags.28y!o( -rellena el !acground con el s8y!o( ha!ilitado., ?amera?learMlags.2olid?olor -con el color que le indiquemos., ?amera?learMlags. epth -que mantiene el color que tuviera el !ac8ground el frame anterior o en cualquier estado previo.o ?amera?learMlags.9othing -no se renderi'a !ac8ground alguno..

FUNCIONES:

ResetAs!ect: function 7eset*s!ect () : void

&evierte el aspect ratio de la cmara al aspect ratio de la pantalla, aca!ando con el efecto de modificar la varia!le aspect. /o veremos mejor con un ejemplo -por cierto, si al trmino del ejemplo anterior no lo hicsteis, aprovechad ahora para volver a marcar el chec8!o( del componente ?amera de *ain camera. 1ditamos *i2egundo2cript para que lu'ca como sigue+ camera.aspect D 6C yield _aitMor2econds -K.C camera.&esetAspect-.C

/o que estamos haciendo es lo siguiente+ primero esta!lecemos la varia!le aspect en 6. &ecordemos que aspect es la anchura de la cmara dividida por la altura, esto es, en este caso la cmara ser el do!le de ancha que alta -y en consonancia lo gra!ado ser el do!le de estrecho de lo normal.. #ara ver la diferencia, intercalamos una instrucci"n yield que $como ya sa!emos$ suspende la ejecuci"n de cualquier otra instrucci"n -en este caso durante cinco segundos. y acto seguido reseteamos el aspect de la cmara para devolverlo a sus parmetros normales.

;orldToScreen/oint: function ?orldToScreen5oint (!osition : "ector#) : "ector#

:ransforma la posici"n de un transform desde el espacio glo!al al espacio de la pantalla. &ecordemos que el espacio de la pantalla est definido en p(eles -i'quierda$a!ajo es -E,E. y derecha$arri!a es -pi(el_idth,pi(el)eight.. /a posici"n ' se calcula en unidades glo!ales desde la cmara. %n ejemplo. 1ditamos *i2egundo2cript tecleando esto+ var eseGue:u>esAhi + :ransformC var posicionFlo!al + 2tringC var posicion1n#i(eles + 2tringC posicionFlo!al D eseGue:u>esAhi.position.:o2tring-.C posicion1n#i(eles D camera._orld:o2creen#oint-eseGue:u>esAhi.position..:o2tring-.C e!ug./og-</a posicion glo!al es < B posicionFlo!al B < y la posicion en pi(eles < Bposicion1n#i(eles.C

Fuardamos y arrastramos desde la =erarqua nuestro ?u!o hasta la varia!le e(puesta eseGue:u>esAhi. 1l script devuelve primero la posici"n glo!al del cu!o en la escena, en un string generado por la funci"n :o2tring. Acto seguido convertimos ese vector7 que contiene las coordenadas glo!ales en otro >ector7 que contiene la u!icaci"n en p(eles del transform del cu!o respecto de la pantalla. Al devolver un >ector7, podemos tam!in aprovechar la funci"n :o2tring para convertir dichas coordenadas en un 2tring e imprimirlas. &ecordemos que el tercer parmetro del >ector7 con la u!icaci"n en p(eles viene referido -eje J. a la distancia en unidades glo!ales -metros. entre la cmara y el transform.

;orldToVie.!ort/oint: function ?orldTo"ie)!ort5oint (!osition : "ector#) : "ector#

?onvierte la posici"n de un transform desde las coordenadas glo!ales al espacio de punto de vista -vie4port space en ingls.. 1l vie4port space es el relativo a la cmara, donde i'quierda$a!ajo es -E,E. y derecha$arri!a -5,5.. /a posici"n ' se medira en unidades glo!ales desde la cmara. /o vemos con ms claridad modificando ligeramente el script anterior+ var eseGue:u>esAhi + :ransformC var posicionFlo!al + 2tringC

var posicion1n1spacio?amara + 2tringC posicionFlo!al D eseGue:u>esAhi.position.:o2tring-.C posicion1n1spacio?amara D camera._orld:o>ie4port#oint-eseGue:u>esAhi.position..:o2tring-.C e!ug./og-</a posicion glo!al es < B posicionFlo!al B < y la posicion en espacio normali'ado de camara < Bposicion1n1spacio?amara.C

?omo vemos al darle al play, ahora se nos muestra en coordenadas relativas a la cmara la u!icaci"n del transform del cu!o. ?ontin3a inalterada, eso s, la distancia respecto del eje J -profundidad., que ya dijimos que va medido en unidades glo!ales respecto de la posici"n de la cmara.

54. CLASE CAMERA (V)

Vie.!ortTo;orld/oint: function "ie)!ortTo?orld5oint (!osition : "ector#) : "ector#

1s la funci"n inversa a _orld:o>ie4port#oint, que estudiamos en la lecci"n anterior. ?onvierte por tanto la posici"n de un transform medida en el vie4port space relativo de la cmara -E,E a 5,5. a coordenadas glo!ales. 2e suministra a la funci"n un vector donde los componentes I e , son las coordenadas de pantalla, y el componente J es la distancia del plano resultante desde la cmara en unidades glo!ales, y la funci"n los transforma en coordenadas glo!ales. As, podemos adaptar el ejemplo que nos propone el manual de referencia y di!ujar una esfera amarilla en la esquina superior derecha de la pantalla, y traducir dichas coordenadas de u!icaci"n a las generales de la escena. function @n ra4Fi'mos -. O var de/a?amaraAl*undo + >ector7 D camera.>ie4port:o_orld#oint ->ector7 -5,5,E.K..C Fi'mos.color D ?olor.yello4C Fi'mos. ra42phere -de/a?amaraAl*undo, E.5.C P

/e hemos dado una profundidad a la u!icaci"n de la esfera de E.K. )emos de tener presente que esta distancia no de!e ser inferior a la que est esta!lecida en near?lip#lane, o no se ver.

ScreenTo;orld/oint: function ScreenTo?orld5oint (!osition : "ector#) : "ector#

?onvierte la posici"n de un transform desde el espacio de pantalla en p(eles -E,E a pi(el_idth,pi(el)eight. a coordenadas glo!ales, con la posici"n ' -como en el resto de casos. medida en unidades glo!ales desde la cmara.

ScreenToVie.!ort/oint: function ScreenTo"ie)!ort5oint (!osition : "ector#) : "ector#

?onvierte la posici"n de un transform de espacio de pantalla en p(eles -E,E a pi(el_idth,pi(el)eight. a vie4port space relativo al espacio de cmara -E,E a 5,5..

Vie.!ortToScreen/oint: function "ie)!ortToScreen5oint (!osition : "ector#) : "ector#

?onvierte la posici"n del transform de vie4port space relativo al espacio de cmara -E,E a 5,5. en espacio de pantalla en p(eles -E,E a pi(el_idth,pi(el)eight.. /a posici"n ' en am!os tipo de medida es la misma, medida en unidades glo!ales desde la cmara.

Vie.!ort/ointToRa%: function "ie)!ort5ointTo7a% (!osition : "ector#) : 7a%

evuelve un rayo que sale de la cmara en coordenadas relativas a sta -E,E a 5,5.. 1l rayo comien'a en el plano ms cercano a la cmara, ra'"n por la que la posici"n J es ignorada.

Screen/ointToRa%: function Screen5ointTo7a% (!osition : "ector#) : 7a%

evuelve un rayo que va de la cmara a travs de un punto de la pantalla. 1stando el rayo en las coordenadas glo!ales, empie'a en el plano cercano a la cmara y va a travs de la posici"n ( e y en las coordenadas de p(eles -E,E a pi(el_idth,pi(el)eight. en la pantalla -la posici"n ' es ignorada..

55. CLASE CAMERA (VI)

Render: function 7ender () : void

&enderi'a la cmara manualmente, usando el clear flags de la cmara, target te(ture y otras propiedades. /a cmara puede enviar mensajes como @n#re?ull, @n#re&ender o @n#ost&ender a cualquier script que est vinculado, y renderi'ar algunos filtros de imagen. 1sto es usado para tener control preciso so!re el orden de renderi'ado. #ara hacer uso de esta caracterstica, crea una cmara y desha!ilitala, y entonces llama a la funci"n &ender para ella.

Render;ithShader: function 7ender?ithShader (shader : Shader re!lacementTag : String) : void

)ace que la cmara renderice con reempla'o de som!reado -shader. . 1sto renderi'ar la cmara, usando los clear flags de la cmara, target te(ture y otras propiedades. A direrencia de la funci"n anterior, la cmara no enviar @n#re?ull, @n#re&ender or @n#ost&ender a scripts vinculados. /os filtros de la imagen tampoco sern renderi'ados. 1sto es usado para efectos especiales, como por ejemplo renderi'ar una visi"n de calor y cosas as. #ara usar estas caractersticas, ha!itualmente crears una cmara y la desha!ilitars y luego llamars &ender_ith2hader en ella.

SetRe!lacementShader: function Set7e!lacementShader (shader : Shader re!lacementTag : String) : void

)ace que la cmara renderice con shader replacement. espus de llamar a esta funci"n, la cmara renderi'ar su vista con shader replacement. #ara volver al renderi'ado normal hay que llamar a &eset&eplacement2hader.

ResetRe!lacementShader: function 7eset7e!lacementShader () : void

Borra el shader replacement de la cmara provocado por la funci"n anterior.

RenderToC+"ema!: function 7enderTo8ubema! (cubema! : 8ubema! face3as9 : int & @#) : boolean

&enderi'a un cu!emap desde la cmara que llama a esta funci"n. 1sto es muy 3til en el editor para !a8ear cu!emaps estticos de tu escena. /a posici"n de la cmara, clear flags y clipping plane distances son usados para renderi'ar dentro de las caras de un cu!emap. face*as8 es un mapa de !its que indica qu cara del cu!emap de!e ser renderi'ada. ?ada !it se corresponde a una cara y est representado por un int dentro de una enum de tipo cu!emapface. #or defecto las seis caras del cu!e map se renderi'arn, que es lo que viene representado en la firma por el T7, que corresponde a lo que ocupan los !its de las seis caras. /a funci"n devuelve false si el renderi'ado del cu!emap falla.

1sta funci"n tiene un segundo prototipo+ function 7enderTo8ubema! (cubema! : 7enderTe/ture face3as9 : int & @#) : boolean

1sta segunda modalidad es usada para refle(iones en tiempo real dentro de render te(tures de cu!emap. #uede ser !astante caro en trminos de rendimiento, eso s, especialmente si las sei' caras del cu!emap son renderi'adas cada frame.

Co!%From: function 8o!%From (other : 8amera) : void

#ermite copiar para una cmara todas las varia!les de otra cmara -campo de vision, clear flags, culling mas8h. #uede ser 3til si queremos que una cmara coincida con la configuraci"n de otra, para conseguir efectos personali'ados de rendering, como por ejemplo los o!jetidos usando &ender_ith2hader.

VARIABLES DE CLASE: main: static var main : 8amera

2e refiere a la cmara que est ha!ilitada y con el tag ]*ain ?amera^-&ead @nly.. evuelve nulo si no hay una cmara con esas caractersticas en la escena.

allCameras: static var all8ameras : 8amera+,

evuelve todas las cmaras ha!ilitadas en la escena.

5!. CLASE LIG&T (I)

1sta clase se usa para controlar todos los aspectos de las luces en %nity. /as propiedades que aqu veremos son e(actamente las mismas que los valores que podemos encontrarnos en el inspector. 9ormalmente las luces son creadas en el editor, pero a veces puede ser que queramos crear o manipular una lu' desde un script. #odemos, para tener una primera idea de lo que podemos hacer con esta clase, aplicar el ejemplo que nos viene en el manual de referencia. Antes de nada, modifiquemos el escenario para los ejemplos que vendrn+ 5.$ 1liminamos en =erarqua ?amara 6. 6.$ 1liminamos el script vinculado a #orta2cripts.

o!le clic8 en *i#rimer2cript. :ecleamos+ function 2tart -. O var una9ueva/u' + Fame@!ject D ne4 Fame@!ject-</a lu'<.C una9ueva/u'.Add?omponent-/ight.C una9ueva/u'.light.color D ?olor.!lueC una9ueva/u'.transform.position D >ector7-E, K, E.C P

2alvamos y arrastramos el script a #orta2cripts. #ulsamos play. as+

e!era aparecer una nueva lu' en la escena, tal que

/a dinmica del script es sencilla+ ?reamos primero un gameo!ject -que sera el equivalente a crear en el men3 de la interface de %nity un gameo!ject vaco. A dicho gameo!ject vaco -que damos en llamar <la lu'<.le aadimos un componente de tipo lu' -por defecto se crea una lu' de tipo #oint.. /e damos por 3ltimo a esa lu' recin creada un color y una u!icaci"n en la escena.

VARIABLES: t%!e: var t%!e : -ightT%!e

1l tipo de lu'. #uede ser /ight:ype.2pot+ ?onsiste en una lu' tipo tipo foco. /ight:ype. irectional+ %na lu' direccional, parecida a la del sol. /ight:ype.#oint+ %n punto de lu'. #ara mostrar la diferencia entre las tres, he apagado la lu' principal de la escena desha!ilitando su chec8!o(, y he rediseado el script anterior, y a su ve' he hecho las pertinentes pro!aturas con los tres tipos de lu'. function 2tart -. O var una9ueva/u' + Fame@!ject D ne4 Fame@!ject-</a lu'<.C una9ueva/u'.Add?omponent-/ight.C una9ueva/u'.transform.position D >ector7-E, 7, E.C una9ueva/u'.light.type D /ight:ype.2potC P

Aqu os dejo las capturas de pantalla de este script con los tres tipos de lu'. #rimero con lu' tipo 2pot+

/u' directional+

, lu' tipo point+

5". CLASE LIG&T (II)

color: "ar color : 8olor

1l color de la lu'. #ara modificar la intensidad de la lu' podemos cam!iar el color de la lu'. #or ejemplo, una lu' de color negro es lo mismo que no tener ninguna lu'.

intensit%: var intensit% : float

/a intensidad de la lu' es multiplicada con el color de la lu'. 1l valor puede estar entre E y Y. 1sto nos permite crear luces muy !rillantes.

&ealicemos un pequeo ejemplo. #reviamente eliminamos el script vinculado a #orta2cripts y volvemos a ha!ilitar -si lo ha!amos desmarcado. el chec8!o( de nuestra lu' principal. o!le clic8 en *i#rimer 2cipt. :ecleamos+ function %pdate-.O var opaco + float D E.EC var !rillante + float D Y.EC light.color D ?olor.greenC light.intensity D &andom.&ange-opaco, !rillante.C P

Fuardamos y vinculamos el script a nuestra /u'. Al darle al play de!eramos asistir a una escena iluminada por una parpadeante lu' de ne"n. *eramente lo que hemos hecho es utili'ar una funci"n de la clase &andom -de pr"(imo estudio.de nom!re &ange, que genera un n3mero aleatorio entre un m(imo y un mnimo. ado que la intensidad de la lu' va de E a Y, le damos ese amplio margen de actuaci"n a &andom.&ange para que cada frame vare la intensidad de la lu' de manera aleatoria entre E y Y. 1llo, unido al color verde tpicamente apocalptico, nos da este !onito efecto.

shado.s: var shado)s : -ightShado)s

0ndica c"mo proyecta som!ras la lu'. 1sta varia!le es de tipo /ight2hado4s, que es una enumeraci"n que permite los siguientes valores+ 9one+ 9o proyecta som!ras -por defecto. )ard+ #royecta som!ras duras -sin filtro de som!ras. 2oft+ #royecta som!ras suaves -con filtro. #ongamos un ejemplo. o!le clic8 so!re *i#rimer2cript. :ecleamos+ function 2tart-.O light.color D ?olor.yello4C light.intensity D 7.EC light.shado4s D /ight2hado4s.)ardC P

@!servemos las som!ras, y comprenderemos por qu se les denomina como duras+

, si usamos el valor /ight2hado4s.2oft+

shado.Strenght: var shado)Strength : float

1sta!lece;indica la fuer'a de las som!ras.

shado.Bias: var shado)=ias : float >endra a ser la perpendicular de la som!ra respecto del o!jeto que la emite.

shado.So(tness: var shado)Softness : float

2uavidad de las som!ras de las luces direccionales.

shado.So(tnessFade: var shado)SoftnessFade : float

>elocidad de fadeout de las som!ras de las luces direccionales.

5#. CLASE LIG&T ( III)

range: var range : float

1l dimetro del rango o ha' de lu', en luces de tipo spot y point.

s!otAngle: var s!ot*ngle : float

1n ngulo en grados de las luces de tipo spotlight. %sado originalmente en luces de tipo spot, altera el tamao del foco de la galleta de lu' en luces de tipo direccional. 9o tiene efectos para luces de tipo point.

coo5ie: var coo9ie : Te/ture

>aria!le de tipo te(tura que esta!lece la te(tura de la galleta proyectada por la lu'.

(lare: var flare : Flare

2elecciona un halo para la lu'. 1ste ha de ser previamente asignado en el inspector.

render-ode:

var render3ode : -ight7ender3ode

1sta!lece c"mo renderi'ar la lu', de entre las siguientes opciones que la enumeraci"n /ight&ender*ode permite+ Auto+ 1lige el modo de renderi'ado automticamente. Morce#i(el+ Muer'a a la lu' a ser una lu' de p(eles. Morce>erte(+ Muer'a a la lu' a ser una lu' de vrtices.

c+lling-as5: var culling3as9 : int

1s usado para separar luces de la escena de manera selectiva. 2i el layer*as8 del gameo!ject y el culling*as8 de la lu' son cero, entonces el o!jeto no ser iluminado con esta lu'.

5$. CLASE MATERIAL (I)

?omo podis compro!ar en el esquema superior, hemos su!ido dos peldaos en la jerarqua respecto a las 3ltimas clases que est!amos estudiando, y vamos ahora a apro(imarnos a una serie de clases que derivan directamente de la clase !ase @!ject. /a clase material, tal como es de suponer, accede a todas las propiedades de un material, permitindonos alterarlas;animarlas. 2i pretendemos referirnos al material usado por un o!jeto, es preferi!le usar la propiedad &enderer.material, tal que as+ renderer.material.color D ?olor.redC

VARIABLES: shader: var shader : Shader

1s el shader del material. 1n modelado 7d, un shader vendra a ser el algoritmo que indica c"mo una superficie ha de responder ante la lu'. 1s una varia!le de la clase 2hader -que estudiaremos en su momento.. 9os permite utili'ar;crear;importar diferentes reacciones que tendr nuestro o!jeto al darle la lu' -diffuse, transparent, ect. #or ejemplo, podemos compro!ar qu tipo de shader tiene nuestra esfera. #ara ello, antes que nada, eliminamos el script que tenemos vinculado a la lu' -si es que estamos siguiendo las lecciones por orden., y editamos *i#rimer2cript tal como sigue+ renderer.material.shader D 2hader.Mind- <:ransparent; iffuse< .C var mi2hader + 2tringC mi2hader D renderer.material.shader.:o2tring-.C e!ug./og-mi2hader.C

?omo vemos, para o!tener el tipo de material referido a un o!jeto recurrimos a la clase &enderer. @!servamos que nuestra esfera tiene el shader por defecto, que es de tipo ifusse. , si queremos cam!iar el tipo de shader y convertirlo en especular, usamos la funci"n Mind -que estudiaremos en su momento cuando demos la clase 2hader. y se la asignamos a nuestra esfera. var mi2hader + 2tringC renderer.material.shader D 2hader.Mind- <2pecular< .C mi2hader D renderer.material.shader.:o2tring-.C e!ug./og-mi2hader.C

color: var color : 8olor

1l color principal del material. 1s lo mismo que $como veremos en !reve$ usar Fet?olor o 2et?olor con el nom!re ]N?olor^. Aadimos una declaraci"n a nuestro script para cam!iarle el color a la esfera+ var mi2hader + 2tringC renderer.material.shader D 2hader.Mind- <2pecular< .C renderer.material.color D ?olor.cyanC mi2hader D renderer.material.shader.:o2tring-.C e!ug./og-mi2hader.C

mainTe)t+re: var mainTe/ture : Te/ture /a te(tura principal del material. 1s lo mismo que usar Fet:e(ture o 2et:e(ture con el nom!re ]N*ain:e(^. 2i por ejemplo escri!iramos un script as+ var te(ture + :e(tureC renderer.material.main:e(ture D te(tureC

tendramos una varia!le <e(puesta< donde podramos arrastrar la te(tura principal que quisiramos que tuviera nuestro material.

mainTe)t+reO((set: var mainTe/tureOffset : "ector1 9os permite despla'ar la te(tura principal. )ay un ejemplo muy indicativo en el manual de referencia de %nity, que he modificado ligeramente. ?on carcter previo necesitara que os descargrais una te(tura, a poder ser alguna cuyo movimiento fuera percepti!le. ,o por ejemplo voy a utili'ar esta+ http+;;444.!logger.com;img;!lan8.gif %na ve' descargada, la guardamos dentro de la carpeta <assets< de nuestro proyecto en %nity, de tal manera que en #royecto nos salga. Acto seguido escri!imos este script+ var mi:e(tura + :e(tureC renderer.material.main:e(ture D mi:e(turaC var scroll2peed + float D E.KC function %pdate-. O var offset + float D :ime.time Z scroll2peedC renderer.material.main:e(ture@ffset D >ector6 -offset, E.C P

2alvamos y arrastramos la te(tura hasta la varia!le e(puesta del script mi:e(tura. /e damos al play y o!servaremos que la te(tura de nuestra esfera comien'a a girar -ojo, si vemos las varia!les rotate de la esfera o!servaremos que no es el o!jeto el que gira, sino la te(tura la que se despla'a so!re el o!jeto.. *eramente estamos cam!iando de sitio a nuestra te(tura con respecto a nuestro o!jeto -pensemos en aplicaciones como anuncios de ne"n en una ciudad futurista..

!0. CLASE MATERIAL (II)

mainTe)t+reScale: var mainTe/tureScale : "ector1

/a escala de la te(tura principal.

FUNCIONES: Constr+ctor: static function 3aterial (contents : String) : 3aterial

?rea un material temporal a partir de un shader descrito por un string.

static function 3aterial (shader : Shader) : 3aterial @ !ien crea un material temporal directamente desde un shader que le proporcionemos de entre los que tengamos. A grandes rasgos la creaci"n de un nuevo material sera as+ var shader + 2haderC var te(ture + :e(tureC var color + ?olorC function 2tart -. O renderer.material D ne4 *aterial -shader.C renderer.material.main:e(ture D te(tureC renderer.material.color D colorC P

Arrastrndole el shader, material y color, o cuanto menos el primero, creamos un material totalmente nuevo. static function 3aterial (source : 3aterial) : 3aterial

?rea un material temporal copiando el shader y todas las propiedades del material que le pasamos como parmetro.

SetColor: function Set8olor (!ro!ert%4ame : String color : 8olor) : void

9os permite indicar el nom!re para un determinado color. *uchos shaders usan ms de un color, por ejemplo+ <N?olor< es el color principal del material, que es el que puede ser tam!in accedido desde la propiedad <color< de la clase. <N2pec?olor< es el color especular de un material -usado en shaders specular;glossy;verte(lit.. <N1mission< es el color que emite un material -usado en verte(lit shaders.. <N&eflect?olor< es el color de refle(i"n del material -usado en reflective shaders..

1n el ejemplo siguiente, sacado del manual de referencia, asignamos el shader glossy -!rillante. a nuestra esfera, y esta!lecemos su color especular en rojo+ function 2tart -. O renderer.material.shader D 2hader.Mind -<Flossy<.C renderer.material.2et?olor -<N2pec?olor<, ?olor.red.C P

GetColor: function Get8olor (!ro!ert%4ame : String) : 8olor

@!tiene el valor de un color con nom!re. #or ejemplo+ print -renderer.material.Fet?olor-<N2pec?olor<..C

SetTe)t+re: function SetTe/ture (!ro!ert%4ame : String te/ture : Te/ture) : void

1sta!lece el nom!re de una te(tura. #ermite cam!iar el property9ame de la te(tura. /os nom!res comunes de las te(turas que encontramos ya creadas en %nity son+ <N*ain:e(< es la te(tura difusa principal. #uede ser accedida tam!in a travs de la propiedad main:e(ture. <NBump*ap< es el mapa de normales. <N?u!e< se refiere al cu!emap.

GetTe)t+re: function GetTe/ture (!ro!ert%4ame : String) : Te/ture @!tiene el nom!re de una te(tura.

!1. CLASE MATERIAL ( III)

SetTe)t+reO((set: function SetTe/tureOffset (!ro!ert%4ame : String offset : "ector1) : void

1sta!lece el lugar de despla'amiento de la te(tura pasada como primer parmetro.

GetTe)t+reO((set: function GetTe/tureOffset (!ro!ert%4ame : String) : "ector1

@!tiene la u!icaci"n del despla'amiento de la te(tura pasada como parmetro.

SetTe)t+reScale: function SetTe/tureScale (!ro!ert%4ame : String scale : "ector1) : void

1sta!lece la escala de la te(tura pasada como primer parmetro.

GetTe)t+reScale: function GetTe/tureScale (!ro!ert%4ame : String) : "ector1

@!tiene la escala de la te(tura pasada como parmetro.

SetFloat: function SetFloat (!ro!ert%4ame : String value : float) : void

1sta!lece un valor tipo float con nom!re.

GetFloat: function GetFloat (!ro!ert%4ame : String) : float

@!tiene un valor de tipo float con nom!re.

:as/ro!ert%: function Has5ro!ert% (!ro!ert%4ame : String) : boolean

?omprue!a si el shader del material tiene una propiedad con un nom!re determinado. #or ejemplo+ if-renderer.material.)as#roperty-<N?olor<.. renderer.material.2et?olor-<N?olor<,?olor.red.C

GetTag: function GetTag (tag : String searchFallbac9s : boolean default"alue : String & AA) : String

@!tiene el valor del tag del shader del material. 2i el shader del material no tiene definido el tag, devuelve default>alue. 2i el parmetro searchMall!ac8s es true, entonces esta funci"n !uscar el tag en todos los su!shaders. 2i searchMall!ac8s es falso entonces s"lo se har la consulta para el actual su!shader.

Ler!: function -er! (start : 3aterial end : 3aterial t : float) : void

0nterpola propiedades entre dos materiales. )ace que todos los colores y valores del primer material sean convertidos en los valores del segundo material en el tiempo t. ?uanto el tercer parmetro -t. es cero, se toman los valores de startC cuando es 5, los valores se toman de end.

Co!%/ro!ertiesFrom-aterial: function 8o!%5ro!ertiesFrom3aterial (mat : 3aterial) : void

?opia propiedades de otro material en este material.

!2. CLASE CUBEMAP

?omo vemos, esta clase deriva directamente de *aterial, que vimos en la lecci"n pasada. 9o es qui's la clase que ms vayamos a utili'ar, ya que por norma general utili'aremos tal cual los cu!emaps con los que contemos, pero tampoco est de ms tener un conocimiento mnimo de la clase. VARIABLES: (ormat: var format : Te/tureFormat

1l formato de los datos de los p(eles en la te(tura. 2"lo lectura.

FUNCIONES: C+"ema!: static function 8ubema! (si0e : int format : Te/tureFormat mi!ma! : boolean) : 8ubema!

?rea una nueva te(tura de cu!emap. /a te(tura puede tener tamao en cada lado y con o sin mipmaps.

Set/i)el: function Set5i/el (face : 8ubema!Face / : int % : int color : 8olor) : void

?oloca el color del pi(el en las coordenadas -face, (, y.

Get/i)el: function Get5i/el (face : 8ubema!Face / : int % : int) : 8olor

devuelve el color del pi(el en las coordenadas -face, (, y.

Get/i)els: function Get5i/els (face : 8ubema!Face mi!level : int & ') : 8olor+,

evuelve el color del pi(el de una cara del cu!emap. evuelve un array de colores de p(eles de una cara del cu!emap.

Set/i)els: function Set5i/els (colors : 8olor+, face : 8ubema!Face mi!level : int & ') : void

1sta!lece colores de pi(eles de una cara del cu!emap. 1sta funci"n toma un array de color y cam!ia los colores de los p(eles de la cara completa del cu!emap.

A!!l%: function *!!l% (u!date3i!ma!s : boolean & true) : void

Aplica en realidad todos los previos cam!ios de 2et#i(el y 2etpi(els.

!3. CLASE RENDERTE'TURE (I)

Al igual que ?u!emap, la clase &ender:e(ture hereda directamente de *aterial. )emos de advertir antes que nada que esta clase s"lo est disponi!le para %nity #ro, as que quien no tenga o confe en tener la versi"n de pago de %nity puede saltarse tranquilamente estas lecciones. &ender te(tures son te(turas que pueden ser renderi'adas. #ueden ser usadas para implementar imgenes !asadas en

efectos de renderi'ado, som!ras dinmicas, proyectores, refle(iones o cmaras de vigilancia. ?omo es posi!le que $como a m en su momento$ esa definici"n no nos diga nada, vamos a acercarnos por la va de los hechos a las renderte(tures. )emos de seguir los siguientes pasos+ 5.$ 1liminamos el script vinculado a la esfera. 6.$ Al cu!o, en scale, le damos los siguientes valores+ K,K,E.5, y en position+ $6,6,E. 7.$ 1n el men3, nos vamos a AssetsDL?reateDL&ender :e(ture. X.$ Asimismo en el men3, le damos a Fameo!jectDL?reate otherDLcamera. K.$ A esta nueva cmara le quitamos el componente Audio /istener, para que no nos d pro!lemas de duplicidad. T.$ ?on camera seleccionada, en el inspector veremos una varia!le denominada :arget :e(ture. Arrastramos hasta ah la render:e(ture creada antes y que est en #royecto. `.$ 1sta!lecemos las siguientes coordenadas para camera+ #osition, 6,5,E, &otation [E,E,E. -nos aseguramos de que la esfera est en 6,E,E... e!eramos estar viendo en la vista previa de la nueva cmara la esfera muy de cerca. Y.$Arrastramos la &ender :e(ture de #royecto al cu!o. [.$ #ulsamos play. e!eras estar viendo algo como esto+

#or lo tanto, o!servamos que render te(tures es un tipo especial de te(tura que se crea y actuali'a en tiempo de ejecuci"n, y que convierte en te(tura el fruto del renderi'ado de una cmara. #ara ello o!servamos que necesitamos crear -en la interfa' o a travs de un script. una nueva render te(tura y asignarla a una cmara para que la renderice. Acto seguido creamos o designamos una superficie que reci!a esa te(tura as creada. ecimos que se crea y actuali'a en tiempo de ejecuci"n. #ara demostrar tal aseveraci"n, vamos a crear un pequeo script. o!le clic8 en *i#rimer2cript+ var mi:e(tura + :e(tureC function %pdate-. O renderer.material.main:e(ture D mi:e(turaC transform.&otate-E,6E,E.C P

2i todava tenemos en #royecto la te(tura que nos descargamos hace un par de lecciones, la arrastramos a mi:e(tura. 2i no, hacemos lo propio con cualquier te(tura no uniforme -para que se note el efecto de la rotaci"n de la esfera. que tengamos a mano. /e damos al play. #ensemos en las enormes posi!ilidades que nos a!re esta clase, que nos permite convertir en te(tura o plasmar so!re cualquier superficie algo que est siendo gra!ado en ese momento en otro lugar -esto nos sirve tanto para implementar el contenido de una cmara de seguridad como para ela!orar todo tipo de espejos o superficies reflectantes..

VARIABLES: .idth: var )idth : int

/a anchura de la te(tura renderi'ada en p(eles. A diferencia de :e(ture.4idth, esta varia!le no es de s"lo lectura, y permite esta!lecer un valor para cam!iar la anchura.

height: 2ar height : int

/a altura de la te(tura renderi'ada en p(eles. /e es de aplicaci"n lo dicho para 4idth.

!4. CLASE RENDERTE'TURE (II)

de!th: var de!th : int

/a precisi"n en !its de la profundidad del !3fer de la render te(ture -son soportados los valores E, 5T y 6X.

(ormat: var format : 7enderTe/tureFormat 1l formato de la render te(ture. &ender:e(tureMormat es una enumeraci"n que permite estos valores+ &ender:e(tureMormat es una enum con estos valores+ A&FB76+ Mormato de color de la render te(ture, Y !its por canal. epth+ %n formato de profundidad de la render te(ture. A&FB)alf+ Mormato de color de la render te(ture, 5T !it en punto flotante por canal. &FBKTK+ Mormato de color de la render te(ture. A&FBXXXX+ Mormato de color de la render te(tura, X !it por canal. A&FB5KKK+ Mormato de color de la render te(ture, 5 !it para el canal Alpha, K !its para los canales del rojo, verde y a'ul. efault+ Mormato de color por defecto de la render te(ture, dependiendo del formato de !ufer por frame y la plataforma.

+se-i!-a!: var use3i!3a! : boolean

#or defecto, las render te(tures no tienen mipmaps. 2i esta!lecemos esta varia!le en true, se generarn niveles de mipmap asociados. 1ste flag puede ser usado s"lo en render te(tures que sean potencias de dos.

2ar isC+"ema! : "oolean var is8ubema! : boolean 2i est ha!ilitada, esta render te(ture ser usada como ?u!emap.

FUNCIONES: RenderTe)t+res: static function 7enderTe/ture ()idth : int height : int de!th : int format : 7enderTe/tureFormat) : 7enderTe/ture

?rea un nuevo o!jeto &ender:e(ture, que es creado con anchura y altura, con un !uffer de profundidad y en un determinado formato. 2era lo mismo que hicimos en el ejemplo de la lecci"n anterior, pero a travs de un script. ?uando invocamos a travs del constructor un nuevo o!jeto &ender:e(ture no estamos todava crendolo en realidad . 1l &ender:e(ture ser creado o !ien la primera ve' que se usa o !ien llamando de manera e(presa a la funci"n ?reate. As que despus de construir la render te(ture, dado que a3n no ha tomado forma la representaci"n final de la misma, es posi!le esta!lecer varia!les adicionales, como format, is?u!emap y similares. static function 7enderTe/ture ()idth : int height : int de!th : int) : 7enderTe/ture 1ste segundo prototipo del constructor es idntico al anterior, salvo que no se esta!lece de manera e(presa el formato de la renderte(ture. /a render te(ture es colocada para estar en color format por defecto.

Create: function 8reate () : boolean

:al como aca!amos de indicar, es esta funci"n la que crea en realidad la &ender:e(ture.

Release: function 7elease () : void

1sta funci"n li!era los recursos de hard4are usados por la render te(ture. /a te(ture en s no es destruida, y ser automticamente creada otra ve' cuando se use.

IsCreated:

function Is8reated () : boolean

0ndica si la render te(ture se ha creado realmente o no.

!5. CLASE RENDERTE'TURE ( III)

DiscardContents: function Discard8ontents () : void

escarta el contenido de la render te(ture.

SetGlo"alShader/ro!ert%: function SetGlobalShader5ro!ert% (!ro!ert%4ame : String) : void

Asigna esta render te(ture como la propiedad shader glo!al llamada en el parmetro property9ame.

VARIABLES DE CLASE: acti2e: static var active : 7enderTe/ture

2e refiere a la render te(ture activa. :odos los renderings van dentro de la renderte(ture activa. 2i esta es null todo se renderi'a en la ventana principal. ?uando una &ender:e(ture se convierte en activa su conte(to de hard4are de renderi'ado es automticamente creado si no se ha!a creado ya.

FUNCIONES DE CLASE: GetTem!orar%: static function GetTem!orar% ()idth : int height : int de!th=uffer : int & ' format : 7enderTe/tureFormat & 7enderTe/tureFormat(Default) : 7enderTe/ture

Asigna una render te(ture temporal. 1sta funci"n es optimi'ada para cuando necesitas una &ender:e(ture rpida para hacer algunos clculos temporales. /i!rala usando &elease:emporary tan pronto hayas hecho el tra!ajo, as podrs reusarla otra ve' en una nueva llamada si la necesitas.

ReleaseTem!orar%:

static function 7eleaseTem!orar% (tem! : 7enderTe/ture) : void

/i!era una te(tura temporal asignada con Fet:emporary.

!!. CLASE PARTICLEEMITTER (I)

Antes que nada, pediros disculpas porque esa clase se me ha!a pasado. ?omo podis ver en el grfico, #article1mitter deriva de ?omponent -como ?ollider, &igid!ody, :ransform.... y por lo tanto la de!era ha!er e(plicado antes, pero !ueno, su!sanamos el error ahora. >amos a preparar antes que nada nuestra escena para acoger los nuevos ejemplos de esta clase+ 5.$ Borramos la cmara que creamos en la clase &ender:e(ture 6.$ evolvemos el cu!o a sus valores previos+ position -$6,E,E. scale-5,5,5. 7.$ 1liminamos el script vinculado a la esfera. X.$ 1liminamos la render te(ture en la carpeta #royecto. K.$ 9os vamos al men3 Fameo!jectDL?reate otherDL#article 2ystem. T.$ %!icamos nuestro nuevo gameo!ject en E,E,E y lo renom!ramos como <#articulas<. `.$ 2alvamos la escena. e!eramos tener ahora una escena parecida a esta+

>ale, ya estamos listos. VARIABLES: emit: var emit : boolean

Booleano que indica si de!en las partculas ser automticamente emitidas cada frame o no. #odemos usar esta varia!le para <encender o apagar< la emisi"n de partculas. 1ditemos nuestro script de la siguiente manera+ yield _aitMor2econds-K.C particle1mitter.emit D falseC yield _aitMor2econds-K.C particle1mitter.emit D trueC

@!servaremos que tras los cinco segundos iniciales, nuestro sistema de partculas comien'a a e(tinguirse hasta desaparecer, y pasados otros cinco, vuelve a encenderse.

minSi*e: var minSi0e : float

1l tamao mnimo que cada partcula puede tener cuando se genera.

ma)Si*e: var ma/Si0e : float

1l tamao m(imo que cada particular puede tener al tiempo de ser generada.

2i tenemos el gameo!ject #articulas seleccionado, podemos compro!ar que por defecto el tamao mnimo -y m(imo. es E.5. >eamos qu pasa si alteramos estos valores+ particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC

minEnerg%: var min6nerg% : float

1l mnimo tiempo de vida de cada particular, medido en segundos.

ma)Energ%: var ma/6nerg% : float

1l m(imo tiempo de vida de cada partcula, medido en segundos. 1n el inspector esta varia!le y la anterior est colocada en 7 por defecto. Aadamos al script anterior unos valores distintos. particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC

>emos que conseguimos as una mayor variedad en la persistencia de cada partcula, dndole mayor dinamismo a nuestro sistema de partculas. ejamos aqu esta lecci"n. 2i a3n te queda algo de tiempo no cierres el editor de scripts, ya que seguiremos en la pr"(ima lecci"n aadiendo modificaciones a nuestro ejemplo.

!". CLASE PARTICLEEMITTER (II)

minEmission: var min6mission : float

1l mnimo n3mero de partculas que sern generadas cada segundo.

ma)Emission: var ma/6mission : float

1l m(imo n3mero de partculas que sern generadas cada segundo. /os valores por defecto en el inspector son KE. 1ditemos nuestro script para alterarlo. particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC

:enemos ahora un sistema de partculas ms denso y compacto, como vemos.

emitterVelocit%Scale: var emitter"elocit%Scale : float

/a cantidad de la velocidad de emisi"n que las partculas heredan. #or defecto E.EK.

.orldVelocit%: var )orld"elocit% : "ector#

/a velocidad inicial de las partculas en el mundo glo!al, a lo largo de (,y,'.

0ncorporemos estas dos 3ltimas varia!les a nuestro ejemplo, dndole a nuestro sistema de partculas una mayor velocidad de emisi"n y haciendo que nuestras partculas se desplacen hacia arri!a -en coordenadas glo!ales.+ particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC particle1mitter.emitter>elocity2cale D E.XC particle1mitter.4orld>elocity D >ector7-E,7,E.C

localVelocit%: var local"elocit% : "ector# 1s como la anterior, pero el despla'amiento se efect3a en las coordenadas locales del propio sistema de partculas.

rndVelocit%: var rnd"elocit% : "ector# %na velocidad aleatoria con relaci"n a los ejes (,y,' que es aadida a la velocidad. 1n nuestro ejemplo+ particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C

particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC particle1mitter.emitter>elocity2cale D E.XC particle1mitter.4orld>elocity D >ector7-E,7,E.C particle1mitter.rnd>elocity D >ector7-5,E.K,E.K.C

+se;orldS!ace: var use?orldS!ace : boolean

2i est ha!ilitado, las partculas no se mueven cuando el emitter se mueve. 2i est en false, cuando muevas el emitter, las partculas lo siguen.

rndRotation: var rnd7otation : boolean

2i est ha!ilitado, las partculas sern generadas con rotaciones aleatorias. #or defecto est en false, as que o!servemos qu ocurre si lo ha!ilitamos+ particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC particle1mitter.emitter>elocity2cale D E.XC particle1mitter.4orld>elocity D >ector7-E,7,E.C particle1mitter.rnd>elocity D >ector7-5,E.K,E.K.C particle1mitter.rnd&otation D trueC

ang+larVelocit%: var angular"elocit% : float /a velocidad angular de las nuevas partculas en grados por segundo.

rndAng+larVelocit%: var rnd*ngular"elocit% : float

%n modificador aleatorio de velocidad angular para nuevas partculas. %n valor aleatorio en el rango de U$ rndAngular>elocity,rndAngular>elocityV ser aplicado a todas las nuevas partculas, en adici"n a #article1mitter. angular>elocity. particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC particle1mitter.emitter>elocity2cale D E.XC

particle1mitter.4orld>elocity D >ector7-E,7,E.C particle1mitter.rnd>elocity D >ector7-5,E.K,E.K.C particle1mitter.rnd&otation D trueC particle1mitter.angular>elocity D 5C particle1mitter.rndAngular>elocity D TTC

!#. CLASE PARTICLEEMITTER ( III)


!articles: var !articles : 5article+,

evuelve una copia de todas las partculas y asigna un array de todas las partculas. )emos de tener en cuenta que despus de modificar el array de partculas de!emos asignarlo de vuelta al particle1mitter para ver el cam!io. #artculas con energa de cero o menos sern elmiminadas cuando se asignen las partculas. As cuando se crea un completo nuevo array de partculas, necesitaremos colocar la energa de todas las partculas e(plicitamente.

!articleCo+nt: var !article8ount : int

1l corriente n3mero de partculas. >aria!le de s"lo lectura.

ena"led: var enabled : boolean

1sta!lece el #article1mitter en on o off. %n #article1mitter que no est ha!ilitado no emitir ninguna partcula, y las partculas emitidas no se animarn. As, este valor nos permite pausar un sistema de partculas. &eutilicemos el ejemplo anterior para pausar nuestro sistema de partculas transcurridos cinco segundos. particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D `EC particle1mitter.ma(1mission D 55EC particle1mitter.emitter>elocity2cale D E.XC particle1mitter.4orld>elocity D >ector7-E,7,E.C particle1mitter.rnd>elocity D >ector7-5,E.K,E.K.C particle1mitter.rnd&otation D trueC particle1mitter.angular>elocity D 5C particle1mitter.rndAngular>elocity D TTC yield _aitMor2econds-K.C particle1mitter.ena!led D falseC

FUNCIONES: Clear/articles: function 8lear5articles () : void

Borra todas las partculas del sistema de partculas.

Emit: function 6mit () : void

1mite un n3mero de partculas. )ace que el emitter escupa un n3mero aleatorio de partculas que se esta!lecen entre las propiedades min1mission y ma(1mission. #ro!emos+ particle1mitter.min2i'e D E.6C particle1mitter.ma(2i'e D E.KC particle1mitter.min1nergy D 5C particle1mitter.ma(1nergy D KC particle1mitter.min1mission D 6EC particle1mitter.ma(1mission D 5KEC particle1mitter.emitter>elocity2cale D E.XC particle1mitter.angular>elocity D 5C particle1mitter.rndAngular>elocity D TTC particle1mitter.1mit-.C

function 6mit (count : int) : void 1sta variante de la funci"n emite el n3mero count de partculas inmediatamente. #asmosle el parmetro 7EE a la funci"n 1mit del ejemplo anterior, por poner un caso muy e(agerado. function 6mit (!os : "ector# velocit% : "ector# si0e : float energ% : float color : 8olor) : void 1ste tercer prototipo de la funci"n 1mit emite una partcula individual con unos parmetros dados. 1(pliquemos !revemente qu representa cada parmetro+

pos+ /a posici"n de la partcula. velocity+ /a velocidad de la partcula. si'e+ 1l tamao de la partcula. energy+ 1l tiempo de vida restante de la partcula. color+ 1l color de la partcula. particle1mitter.1mit->ector7.'ero, >ector7.up, E.X, X, ?olor.yello4.C

?uando le damos al play veremos una partcula en la posici"n central, con direcci"n hacia arri!a, un tamao de E.X unidades, que tardar X segundos en desvanecerse y tendr color amarillo. function 6mit (!os : "ector# velocit% : "ector# si0e : float energ% : float color : 8olor rotation : float angular"elocit% : float) : void , a3n tenemos una tercera variante de la funci"n, que incluye la rotaci"n inicial de la partcula en grados y la velocidad angular por segundo. particle1mitter.1mit->ector7.'ero, >ector7.up, E.X, X, ?olor.yello4, `K, 5KE.C

Sim+late: function Simulate (deltaTime : float) : void Avan'ado sistema de simulaci"n de partculas por un tiempo dado. 1s 3til para precalentar un sistema de partculas,

como si se estuviera gestando+ particle1mitter.2imulate-K.C

!$. CLASE MES& (I)

1sta clase permite crear o modificar mallas desde scripts. /as mallas contienen vrtices y m3ltiples arrays de tringulos. /os arrays de tringulos son meramente ndices dentro del array de vrtices, tres ndices para cada tringulo. #ara cada vrtice puede ha!er un normal, dos coordenadas de te(turas, color y tangentes. :oda la informaci"n de los vrtices es almacenada en arrays separados del mismo tamao, as que si tu malla tiene 5E vrtices, de!e tener tam!en arrays de 5E de tamao para normales y otros atri!utos.

VARIABLES: 2ertices: var vertices : "ector#+,

evuelve una copia de la posici"n del vrtice o asigna un nuevo array de posiciones de vrtices. 1l n3mero de vrtices en la malla es cam!iado asignando un array de vrtices con un diferente n3mero de vrtices. e!emos tener en cuenta que si redimensionamos el array de vrtices entonces todos los otros atri!utos -normales, colores, tangentes, %vs. sern automticamente redimensionados tam!in. &ecalculateBounds automticamente ser invocado si no se han asignado vrtices a la malla cuando se esta!lecieron los vrtices.

normals: var normals : "ector#+,

/os normales de la malla. 2i la malla no contiene normales un array vaco es retornado.

tangents: var tangents : "ectorB+,

/as tangentes de la malla. /as tangentes son mayormente usadas en !ump$mapped shaders. %na tangente es un vector de una unidad de longitud que sigue la malla a lo largo de la direcci"n de te(tura hori'ontal. /as tangentes en %nity son representadas como >ectorX con componentes (,y,' definiendo el vector, y 4 usada para dar la vuelta a la !inormal si es necesario. %nity calcula los otros vectores de supervicie -!inormal. tomando un producto cru'ado entre normal y tangente y multiplicando el resultado por la tangente 4. As 4 de!e ser siempre 5 o $5. e!es calcular tangentes por ti mismo si planeas usar !ump$mapped shaders en la malla. Asigna tangentes despus de asignar normals o usando &ecalculate9ormals.

+2: var uv : "ector1+,

/as coordenadas de la te(tura !ase de la malla.

r29: var uv1 : "ector1+,

1l segundo conjunto de coordenadadas de te(tura de la malla, si lo hu!iere.

"o+nds: var bounds : =ounds

1l volumen de !ordes de la malla. 1sto es la caja de !ordes alineadas en el eje de la malla en el espacio local -esto es, no afectada por el transform.. 1(iste por otro lado la propiedad &enderer.!ounds que retorna los !ordes en espacio glo!al.

colors: var colors : 8olor+,

evuelve los colores del vrtice de la malla. 2i no hay colores devuelve un array vaco.

triangles: var triangles : int+,

%n array conteniendo todos los tringulos de la malla. 1l array es una lista de tringulos que contiene ndices dentro del array de vrtices. 1l tamao del array de tringulos de!e siempre ser m3ltiplo de 7. /os vrtices pueden ser compartidos meramente inde(ando dentro del mismo vrtice. 2i la malla contiene m3ltiples su! mallas -materiales. la lista de tringulos contendr todos los tringulos de todas las su!mallas. ?uando asignas un array de tringulos, su!*esh?ount es colocado a 5. 2i quieres tener m3ltiples su!mallas, usa su!*esh?ount y 2et:riangles. 1s recomenda!le asignar el array de tringulos despus de asignar el array de vrtices para evitar errores de fuera de lmite -out of !ounds.

2erte)Co+nt: var verte/8ount : int

>aria!le de s"lo lectura que devuelve el n3mero de vrtices en la malla.

s+"-eshCo+nt: var sub3esh8ount : int

1l n3mero de su!mallas. ?ada material tiene una lista de tringulos separada.

"one;eights: var bone?eights : =one?eight+,

/a pintura de pesos de cada vrtice. 1l tamao del array es o el mismo que verte(?ount o vaco. ?ada vrtice puede ser afectado por un m(imo de X diferentes huesos. /as cuatro pinturas de peso de!en sumar hasta 5.

"0. CLASE MES& ( II)

FUNCIONES: -esh: static function 3esh () : 3esh

?rea una malla vaca.

Clear: function 8lear () : void

/impia todos los datos de los vrtices y todos los ndices de los tringulos. reconstruir el array de tringulos.

e!es llamar esta funci"n antes de

Recalc+lateBo+nds: function 7ecalculate=ounds () : void

&ecalcula el volumen de !ordes de la malla desde los vrtices. espus de modificar los vrtices de!es llamar a esta funci"n para asegurarte de que el volumen de !ordes es correcto. Asignando tringulos automticamente se recalcula el volumen de !ordes.

Recalc+lateNormals: function 7ecalculate4ormals () : void

&ecalcula los normales de la malla desde los tringulos y vrtices. espus de modificar los vrtices es a menudo 3til actuali'ar los normales para reflejar el cam!io. /os normales son calculados desde todos los vrtices compartidos. /as mallas importadas a veces no comparten todos los vrtices. #or ejemplo un vrtice en una costura %> se partir en dos vrtices. 1n consecuencia la funci"n &ecalculate9ormals crear normales que no son lisos en las costuras %v. 9otemos tam!in que &ecalculate9ormals no genera tangentes automticamente, asi que los !umpmap shaders no tra!ajarn con la malla despus de llamar a esta funci"n. 9osotros podemos sin em!argo proveer nuestras propias tangentes.

O!timi*e: function O!timi0e () : void

@ptimi'a la malla para mostrarla. 1sta operaci"n podra tomar un rato pero hace que la geometra se muestre ms rpido. e!es usarla si generas una malla desde cero procedimentalmente y quieres un mayo rendimiento en tiempo de ejecuci"n en lugar de un mayor tiempo de carga. #ara modelos importados no de!es nunca llamarla porque el import pipeline ya lo hace por ti.

GetTriangles: function GetTriangles (submesh : int) : int+,

evuelve la lista de tringulos de la su!malla. %na su!malla es simplemente una lista de tringulos separada. ?uando el mesh renderer usa m3ltiples materiales, de!es asegurarte de que hay tantas su!mallas como materiales.

SetTriangles: function SetTriangles (triangles : int+, submesh : int) : void

1sta!lece la lista de tringulos para la su!malla. 1s recomenta!le asignar el array de tringulos despus de asignar el array de vrtices para evitar el error de fuera de !ordes.

Com"ine-eshes: function 8ombine3eshes (combine : 8ombineInstance+, mergeSub3eshes : boolean & true use3atrices : boolean & true) : void

?om!ina varias mallas dentro de la malla. ?om!inar mallas es 3til para optimi'aci"n de rendimiento. 2i merge2u!*eshes es true, todas las mallas sern com!inadas en una 3nica su!malla. 1n caso contrario cada malla ir dentro de una su!malla diferente. 2i todas las mallas comparten el mismo material, coloca esto a true. 2i use*atrices es false, el transform matrices en la estructura ?om!ine0nstance ser ignorado.

"1. CLASE GAMEOBJECT (I)

1stamos en la clase central, en la clase con may3sculas de %nity. e hecho, muchas de las clases que hasta la fecha hemos estudiado -y algunas que nos faltan. no son ms que diferentes mim!res cuya funci"n primordial era confluir en esta clase. 9o de!er sorprendernos, por tanto, que !uena parte de las varia!les o propiedades de la clase Fame@!ject no son sino instancias de las clases que ya hemos estudiado, de tal forma que cualquier gameo!ject en la escena -recordemos que todo lo que est en la escena son gameo!jects. tenga la ms amplia funcionalidad.

VARIABLES: isStatic: var isStatic : boolean >aria!le s"lo utili'a!le va interface que especifica si un o!jeto es esttico. 1sto es 3til cuando estemos tra!ajando con occlusion culling, para determinar si un o!jeto puede ser considerado un oclusor esttico. #ara quien no sepa qu diantres es lo de occlusion culling, decir que es una caracterstica que desha!ilita el renderi'ado de o!jetos cuando no estn siendo actualmente vistos por la cmara porque son oclusionados;tapados por otros o!jetos. 1l proceso de occlusion culling va a trav de la escena usando una cmara virtual construyendo una jerarqua de o!jetos potencialmente visi!les. 1stos datos sern usados en tiempo de ejecuci"n por cada cmara para identificar qu es visi!le y qu no. 9ecesitamos etiquetar todos los o!jetos de la escena que queramos que sean parte de la occlusion como 2tatic en el inspector. /a manera ms rpida de hacerlo es convertir todos los o!jetos que queramos marcar como estticos en hijos de un Fame@!ject vaco y esta!lecer ste como 2tatic, eligiendo luego en la opci"n de dilogo que la condici"n de static afecte tam!in a todos sus hijos. espus de eso, ya podemos tranquilamente desparentarlos del gameo!ject vaco, y seguirn teniendo la consideraci"n de static.

trans(orm: var transform : Transform

1l transform del gameo!ject, si lo tiene. 9ull si no tiene ning3n transform vinculado. :al como e(plica!a antes, sta va a ser la t"nica de la mayora de propiedades de la clase Fameo!ject+ integrar o!jetos;instancias de diferentes clases para conformar la utilidad !sica de nuestro juego+ los gameo!jects. #odemos demostrar que todo lo que est en la escena es un gameo!ject+ 1liminamos antes que nada el gameo!ject particulas que creamos en la clase anterior. 2i tenemos alg3n script vinculado al cu!o o la esfera, los eliminamos. >amos a editar ahora *i#rimer2cript+ var unFame@!ject+ Fame@!jectC function %pdate-. O unFame@!ject.transform.&otate-E,K,E.C P

1l script de!era resultarnos fcil a estas alturas. eclaramos una varia!le e(puesta de tipo Fameo!ject, de tal manera que posteriormente podamos acceder al transform de la que arrastremos y rotar el gameo!ject so!re el eje ,. 2alvamos. Arrastramos el script a #orta2cripts en la jerarqua. ?on #orta2cripts seleccionado, arrastramos el cu!o a la varia!le e(puesta. #lay. :al como era de esperar, el cu!o comien'a a girar. #ero vamos a ver qu otros elementos en la escena son considerados por %nity Fameo!jects, y por tanto suscepti!les de tener un transform. 2i con #orta2cripts seleccionado nos vamos al inspector, o!servaremos que a la derecha de la varia!le e(puesta que hemos iniciali'ado con el cu!o hay una pequea flecha. 2i hacemos clic8 so!re ella, se nos a!re un men3 emergente con :@ @2 los gameo!jects de la escena. e hecho hasta nuestro #orta2cripts $a pesar de no ser ni visi!le$ es considerado un gameo!ject. As, si en ese mismo popup hacemos do!le clic8 en main camera y le damos al play, o!servaremos en la vista del juego que lo que empie'a a girar es la cmara.

rigid"od%: var rigidbod% : 7igidbod%

1l rigid!ody vinculado a nuestro gameo!ject, o null si ste no tiene rigid!ody.

camera: var camera : 8amera

/a cmara vinculada a nuestro gameo!ject, o null si ste no tiene una cmara. #or ejemplo, nuestra main camera es un gameo!ject que tiene vinculado una cmara -y un transform..

light: var light : -ight

/a lu' vinculada al gameo!ject. 9ull si no tiene.

"2. CLASE GAMEOBJECT (II)

animation: var animation : *nimation

/a animaci"n vinculada al gameo!ject. 9ull si no tiene. 9o hemos tratado a3n nada relacionado con animaciones, clips y sonidos, ya que he preferido reservarlo para ms adelante y tratarlo todo junto.

constantForce: var constantForce : 8onstantForce

la constantMorce vinculada a este gameo!ject. 9ull si no tiene ninguna vinculada. 9o ha!amos tratado todava la miniclase ?onstantMorce, pero vamos a su!sanar ese pequeo lapsus ahora mismo+ /a clase ?onstantMorce deriva de Behaviour -como camera, light, animation.... y cuenta s"lo con cuatro varia!les;propiedades -amn de las heredadas., que son+ (orce: var force : "ector# /a fuer'a aplicada al rigid!ody cada frame. 1sto 3ltimo es lo que la diferencia de rigid!ody.AddMorce-.. 1n AddMorce se aplica la fuer'a al rigid!ody una ve' por frame, lo que o!liga a llamar a la funci"n varias veces -por ejemplo dentro de una funci"n fi(ed%pdate.. constantMorce.force aplicar la fuer'a indicada cada frame hasta que cam!iemos el contenido de la varia!le force a un nuevo valor. 1sto es aplica!le a las cuatro varia!les de esta clase. relati2eForce: var relativeForce : "ector# /a fuer'a $relativa al sistema de coordenadas local del rigid!ody$ aplicada cada frame. tor,+e: var tor2ue : "ector# /a torsi"n aplicada al rigid!ody cada frame. relati2eTor,+e: var relativeTor2ue : "ector# /a torsi"n $relativa al sistema de coordenadas local del rigid!ody$ aplicada cada frame.

#ongamos un ejemplo glo!al+ Antes que nada seleccionamos el cu!o, y nos vamos al men3DL?omponentDL#hysicsDL?onstant Morce. 1ditamos una ve' ms *i#rimer2cript+ var unFame@!ject+ Fame@!jectC unFame@!ject.constantMorce.force D >ector7-7,5E,E.C unFame@!ject.constantMorce.torque D >ector7-E,Y,E.C

2alvamos. &ecordemos que este script lo tenemos vinculado al gameo!ject #orta2cripts, as que lo seleccionamos. Arrastramos el cu!o a la varia!le e(puesta. @!servemos que am!os atri!utos estn fuera de toda funci"n o !ucle, esto es, que tal como hemos dicho, tanto la fuer'a -hacia la derecha y hacia arri!a. como la torsi"n -so!re el eje ,. que le aplicamos tendrn carcter peri"dico de!ido 3nica y e(clusivamente a las propias caractersticas de la clase

constantMorce. #lay.

renderer: var renderer : 7enderer

1l renderer vinculado al gameo!ject. 9ull si no tiene.

a+dio: var audio : *udioSource

el audiosource vinculado al gameo!ject. 9ull si no tiene.

"3. CLASE GAMEOBJECT (III)

g+iTe)t: var guiTe/t : G:ITe/t 1l gui:e(t -de pr"(imo estudio. vinculado al gameo!ject. 9ulo si no e(iste.

net.or5Vie.: var net)or9"ie) : 4et)or9"ie) 1l net4or8>ie4 -a estudiar mucho ms adelante. vinculado al gameo!ject. 9ulo si no e(iste.

g+iTe)t+re: var guiTe/ture : G:ITe/ture

1l gui:1Iture -en !reve. vinculado al gameo!ject. 9ull si carece de l.

collider: var collider : 8ollider

1l collider vinculado al gameo!ject, si lo tiene. 9ull en caso contrario.

hinge7oint: var hinge>oint : Hinge>oint

1l hinge=oint vinculado al gameo!ject, o null.

!articleEmitter: var !article6mitter : 5article6mitter

1l particle1mitter vinculado al gameo!ject, null si no tiene.

la%er: var la%er : int

1s una varia!le de tipo int comprendida entre el rango E y 75 que indica;coloca la capa en la que el gameo!ject se encuentra. 1l layer sirve entre otras cosas para reali'ar un renderi'ado selectivo de lo que una cmara de!e mostrar o para determinar si a un determinado gameo!ject les afectar o no un raycast.

acti2e:

var active : boolean

R1st el gameo!ject activoS. #odemos ha!ilitarlo;desha!ilitarlo cam!iando a true o false este !ooleano.

tag: var tag : String

1l tag -etiqueta. de este game o!ject. #uede ser usado para identificar a un gameo!ject. )emos de recordar que antes de poder usar esta varia!le de!emos ha!er declarado el tag en el inspector

"4. CLASE GAMEOBJECT (IV)


FUNCIONES: GameO"'ect: static function GameObject (name : String) : GameObject

/a funci"n constructora de gameo!ject tiene tres prototipos diferentes. 1l primero, como vemos, nos permite crear un nuevo gameo!ject y pasarle un parmetro que constituir el nom!re de dicho gameo!ject. >eamos un ejemplo sencillo. 1ditamos *i#rimer2cript+ var nuevoFame@!ject+ Fame@!jectC nuevoFame@!ject D ne4 Fame@!ject-<mi9uevo@!jeto<.C

/o salvamos. 2i no lo esta!a, lo arrastramos a #orta2cripts. /e damos al play. Aparentemente no ocurre nada. 9o aparece ning3n o!jeto en la escena ni en la ventana del juego. 1sto es porque nuestro nuevo gameo!ject est vaco, como podremos compro!ar si $con el juego reproducindose$ seleccionamos el nuevo gameo!ject de nom!re mi9uevo@!jeto que aparece en la jerarqua. @!servamos que tan s"lo tiene un elemento transform -que se crea por defecto.. #ero, ya teniendo un gameo!ject creado en tiempo de ejecuci"n -y volveremos so!re este concepto pasado no demasiado tiempo., podemos de la misma forma aadirle componentes+ var nuevoFame@!ject+ Fame@!jectC nuevoFame@!ject D ne4 Fame@!ject-<mi9uevo@!jeto<.C nuevoFame@!ject.Add?omponent -<Bo(?ollider<.C nuevoFame@!ject.Add?omponent -<*esh&enderer<.C

1n este caso le aadimos un collider de cu!o y una meshrenderer. 2eguir sin verse nuestro nuevo gameo!ject $salvo que lo seleccionemos en la jerarqua, en cuyo caso veremos la malla. porque para ello le de!eramos ha!er creado una malla desde cero, pero a los efectos de este ejemplo con esto de!era !astar. static function GameObject () : GameObject

?rea un gameo!ject, pero sin nom!re nom!re, lo cual no o!sta para que luego se le pueda asignar uno.

static function GameObject (name : String !arams com!onents : T%!e+,) : GameObject 1sta variante del constructor crea un gameo!ject con nom!re y ya vinculado a una serie de componentes prefijados.

GetCom!onent: function Get8om!onent (t%!e : T%!e) : 8om!onent

1sta funci"n devuelve el componente de tipo :ype que tenga el gameo!ject. 1n caso de que el gameo!ject que lan'a el mensaje no tenga ning3n componente de ese tipo, devuelve null. Adems de acceder a componentes 2tandard de unity, puedes acceder a scripts por esta va. 1n este caso, el nom!re del script equivaldr al :ype del parmetro de !3squeda. @jo, porque aunque pongamos el nom!re del script, como en realidad sustituye y equivale a un tipo de componente, lo escri!iremos sin comillas -no es un string. 1s decir, si por ejemplo quisiramos $no hace falta que realicis este ejemplo, es s"lo para aclarar conceptos$ hacer algo en caso de que un determinado gameo!ject tenga un determinado script, haramos algo como esto+ var un@!jeto?ualquiera + Fame@!jectC if-un@!jeto?ualquiera.Fet?omponent-mi#rimer2cript. O )a'Alguna?osa-.C P

Arrastraramos luego el gameo!ject que quisiramos consultar, y si ste tuviera vinculado un script de nom!re mi#rimer2cript $en caso contrario devolvera null$ se ejecuta la funci"n )a'Alguna?osa. 1sta funci"n nos permite adems acceder a varia!les p3!licas -no private ni dentro de funciones. y funciones que se hallen en otro script que est vinculado al mismo gameo!ject. #ongamos que el script del ejemplo lo vinculamos directamente a un gameo!ject -no como el anterior, en que arrastramos el gameo!ject a la varia!le e(puesta. y dicho gameo!ject a su ve' tiene vinculado otro script llamado otro2cript. #odemos capturarlo con esta funci"n y asignarlo a una varia!le de tipo 2cript9ame. var un2egundo2cript + 2cript9ame D game@!ject.Fet?omponent-otro2cript.C ;; %na ve' ya hemos capturado ese script, como decimos, podemos acceder a sus ;;funciones y varia!les p3!licas. un2egundo2cript.)a'@tra?osa -.C un2egundo2cript.tengo%na>aria!le D KC P

function Get8om!onent (name : String) : 8om!onent 1s identica a la anterior, pero en lugar de acceder a un componente por su tipo, lo hacemos por su nom!re a travs de un string -aqu s colocaremos comillas.. 1s preferi!le la primera firma por motivos de rendimiento, pero si no recordamos el tipo del componente, podemos !uscar por el nom!re. &ecordemos que el nom!re de un script ajeno pero vinculado al gameo!ject que hace la consulta es tam!in su tipo, lo cual no o!sta a que siga siendo su nom!re y podamos consultarlo por l, aunque con comillas -]otro2cript^, sera en este caso la manera de escri!ir el parmetro de !3squeda.

"5. CLASE GAMEOBJECT (V)

GetCom!onentInChildren: function Get8om!onentIn8hildren (t%!e : T%!e) : 8om!onent

evuelve un componente activo de tipo que le pasamos como parmetro que pueda tener o !ien el Fameo!ject que lan'a el mensaje o !ien sus hijos. /a !3squeda empie'a por los hijos.

GetCom!onents: function Get8om!onents (t%!e : T%!e) : 8om!onent+,

1sta funci"n devuelve todos los componentes del tipo :ype y los devuelve en forma de array del tipo de componente solicitado. 1sto nos permitira hacer cosas como las del ejemplo que nos !rinda el manual de referencia -no es preciso seguir el ejemplo, es s"lo a modo oritentativo.+ ;;>amos a desconectar la varia!le spring de todos los )inge=oints que tenga este ;;gameo!ject. #rimero crearemos un array de tipo )inge=oint y lo almacenamos ;;en la varia!le !isagras.

var !isagras + )inge=ointUVC ;;, colocamos todos los )inge=oint que encontremos en el array. !isagras D game@!ject.Fet?omponents -)inge=oint.C ;;&ecorremos ahora en un !ucle for in todos los componentes hallados y les ;;desactivamos la varia!le spring. for -var joint + )inge=oint in !isagras. O joint.use2pring D falseC P

GetCom!onentsInChildren: function Get8om!onentsIn8hildren (t%!e : T%!e includeInactive : boolean & false) : 8om!onent+,

evuelve todos los componentes del tipo pasado como primer parmetro que tenga ese gameo!jects y sus hijos. /a peculiaridad es que la funci"n incluye un segundo parmetro opcional de tipo !ooleano que si esta!lecemos en true nos permite recuperar tam!in los componentes inactivos de ese tipo.

SetActi2eRec+rsi2el%: function Set*ctive7ecursivel% (state : boolean) : void

Munci"n que activa o desactiva el estado del gameo!ject que la invoca y de todos sus hijos, en funci"n de si el !olean que tiene como parmetro est en true o false.

Com!areTag: function 8om!areTag (tag : String) : boolean

1sta funci"n nos permite averiguar si un determinado gameo!jet tiene como tag el string colocado como parmetro de la funci"n. 2i lo tiene, la funci"n devuelve true.

Send-essageU!.ards: function Send3essage:!)ards (method4ame : String value : object & null o!tions : Send3essageO!tions & Send3essageO!tions(7e2uire7eceiver) : void

1sta funci"n llama a una funci"n cuyo nom!re pasamos en el parmetro method9ame y que se encuentre en cualquier script que tengamos vinculado al gameo!ject que hace la llamada o en los <padres< de dicho gameo!ject. /e podemos, si procede, pasar un valor a dicho mtodo -value.. 1l parmetro options es del tipo 2end*essage@ptions, que es un enum con dos valores D require&eceiver -que necesita respuesta. y dont&equire&eceiver, que no la requiere. #or defecto la funci"n requiere respuesta, lo cual quiere decir que si se le pasa un argumento a la funci"n receptora y sta no precisa ninguno, imprimir un mensaje de error. 2i no lo requiriera -dont&equire&eceiver., puede optar por ignorar dicho argumento sin ms. >amos a intentar aclararlo un poco ms con un ejemplo. #reviamente eliminemos el script que tenemos vinculado en #orta2cripts. Acto seguido, editamos mi#rimer2cript y lo dejamos como sigue+ function ame?olor -tono + ?olor. O renderer.material.colorD tonoC P ame?olor-?olor.!lac8.C

/a funci"n no requiere ms e(plicaci"n. /a arrastramos al cu!o y al darle al play ste se torna de color negro. Ahora vamos a editar el script mi2egundo2cript, que si hemos seguido las lecciones de!emos tener en #royecto. -y si no creamos uno, tampoco nos volvamos locos.. :ecleamos+ function @n*ouse1nter-. O game@!ject.2end*essage%p4ards -< ame?olor<, ?olor.cyan.C P

Arrastramos tras salvar este script tam!in al cu!o. e esta manera y a travs de 2end*essage%p4ards podemos acceder a la funci"n ame?olor de mi#rimers2cript y usarla a nuestro gusto. 1n este caso nos limitamos a cam!iar el color del cu!o al pasar el rat"n por ste, pero o!viamente y en caso de gameo!jects con un mont"n de scripts vinculados -que a eso llegaremos. esta posi!ilidad de acceder desde un scripts a las funciones que hay en otros es toda

una ventaja.

Send-essage: function Send3essage (method4ame : String value : object & null o!tions : Send3essageO!tions & Send3essageO!tions(7e2uire7eceiver) : void

0gual que la funci"n anterior, con la diferencia de que en esta s"lo podemos llamar a funciones que estn en scripts vinculados al gameo!ject, pero no en sus ancestros.

Broadcast-essage: function =roadcast3essage (method4ame : String !arameter : object & null o!tions : Send3essageO!tions & Send3essageO!tions(7e2uire7eceiver) : void

/lama a un mtodo con nom!re method9ame que est en cualquier script vinculado a ese game o!ject o a cualquiera de sus hijos, a diferencia de las funciones anteriores.

"!. CLASE GAMEOBJECT ( VI)

AddCom!onent: function *dd8om!onent (class4ame : String) : 8om!onent

Aade un componente a nuestro gameo!ject. 1se componente ha de ser una instancia de la clase que ponemos en el parmetro class9ame, o !ien puede ser el nom!re de un script. 1s 3til para aadir componentes en tiempo de ejecuci"n. Algunos componentes requieren de la presencia de otros para e(istir, as que al aadir aqullos automticamente se nos aadirn estos. #ej, si aadimos un )inge=oint automticamente se nos aadir un &igid!ody.

function *dd8om!onent (com!onentT%!e : T%!e) : 8om!onent /a 3nica variaci"n es que en lugar de string, introducimos el tipo de componente o el nom!re del script sin comillas. 9"tese que no e(iste la funci"n &emove?omponent o similar. #ara destruir un componente al vuelo, usad @!ject. estroy

FUNCIONES DE CLASE: Create/rimiti2e: static function 8reate5rimitive (t%!e : 5rimitiveT%!e) : GameObject

?rea un gameo!ject con una malla de tipo primitivo y el apropiado collider. /os tipos primitivos son sphere, capsule, cylinder, cu!e y plane. >eamos alg3n ejemplo -recordemos que es una funci"n de clase, no vinculada a un o!jeto concreto. 1liminemos antes que nada los dos scripts vinculados al cu!o. , luego editamos mi#rimer2cript+ function 2tart-. O var mi?ilindro + Fame@!ject D Fame@!ject.?reate#rimitive-#rimitive:ype.?ylinder.C mi?ilindro.transform.position D >ector7-E,E,$6.C P

2alvamos y arrastramos a #orta2cripts. >emos que hemos creado en ejecuci"n un tipo primitivo -un cilindro en este caso. de entre los que la enum #rimitive:ype nos permite., con su malla y su collider. 1ste cilindro lo almacenamos en una varia!le de tipo Fameo!ject que a partir de ah podemos tratar como un gameo!ject ms, cam!indole, por ejemplo, de u!icaci"n.

Find;ithTag: static function Find?ithTag (tag : String) : GameObject

evuelve un gameo!ject con el tag que le pasamos a la funci"n como string en su 3nico parmetro. 2i no e(iste ninguno. evuelve null. ado que es una funci"n de clase y no va vinculada a ning3n o!jeto, ha de quedar claro que el gameo!ject con el tag que !uscamos no tiene por qu hacer referencia a ning3n gameo!ject vinculado al script, sino a cualquier gameo!ject del juego que est activo. 1l tag, eso s, previamente de!e estar declarado en el tag manager del inspector.

FindGameO"'ect;ithTag: static function FindGameObjects?ithTag (tag : String) : GameObject+,

1sta funci"n de clase devuelve una lista de gameo!jects activos que tengan el tag requerido.

Find: static function Find (name : String) : GameObject

Busca un gameo!ject por nom!re y lo devuelve. Aqu no !uscamos por tag, sino por nom!re. )emos de reiterar que es una funci"n de clase, no vinculada a un determinado gameo!ject, o sea, podemos !uscar con esta funci"n cualquier gameo!ject activo del juego.

2e puede usar el slash -;. para !uscar a travs de una jerarqua. #or motivos de rendimiento es aconseja!le no usar esta funci"n cada frame. 1s mejor o, una ve' hallado el gameo!ject, almacenarlo en una varia!le, o !ien usar la funci"n gameo!ject.find4ithtag. #or poner un ejemplo sencillo, reeditemos

una ve' ms mi#rimer2cript+ var !usca/a1sfera + Fame@!jectC !usca/a1sfera D Fame@!ject.Mind-<1sfera<.C e!ug./og-!usca/a1sfera.name.:o2tring-..C !usca/a1sfera.renderer.material.color D ?olor.greenC

:al como indic!amos en la definici"n, !uscamos con Mind un gameo!ject de nom!re 1sfera, lo almacenamos en una varia!le de tipo gameo!ject, y ya a partir de ah podemos, por ejemplo, imprimir su nom!re o cam!iarle el color.

"". CLASE S&ADER

A!ordamos esta clase pequea y poco importante ms por seguir un orden en la jerarqua de clases que por otra cosa. 9o o!stante, aunque ser raro que nos topemos a menudo con la misma, no est de ms tener una idea !sica de su funcionalidad. ?reo que ya indicamos en otro lugar que un shader es en 7d el algoritmo que especifica c"mo una superficie reaccionar ante la lu'. *uchos de los renders avan'ados son controlados va la clase *aterial. /a clase 2hader es ms usada para compro!ar si un shader puede correr en el hard4are del usuario -propiedad is2upported. y para encontrar shaders por el nom!re -mtodo Mind..

VARIABLES: isS+!!orted: var isSu!!orted : boolean

Bool de s"lo lectura que indica si un determinado shader puede correr en la tarjeta grfica del usuario. 2e usa a veces cuando se implementan efectos especiales. #or ejemplo, image effects en %nity #ro automticamente se desha!ilitan si el shader no es soportado.

FUNCIONES DE CLASE:

Find: static function Find (name : String) : Shader

1ncuentra un shader con el nom!re dado. 9ame es el nom!re que vemos en el popup del shader de cualquier material. 2on nom!res comunes+ < iffuse<, <Bumped iffuse<, <>erte(/it<, :ransparent; iffuse< etc.

"#. CLASE P&YSICMATERIAL

1sta clase descri!e c"mo manejar los o!jetos que chocan -fricci"n, capacidad de re!otar, etc.. 1s posi!le que recordemos cuando estudi!amos la clase ?ollider, que sta tena dos varia!les;atri!utos $material y shared*aterial$ de tipo #hysic*aterial. #or norma general para crear;modificar las capacidades de fricci"n y re!ote de un gameo!ject, pues, lo haremos a travs de la propiedad collider.material de dicho gameo!ject. VARIABLES: d%namicFriction: var d%namicFriction : float

/a fricci"n usada cuando ya hay movimiento. 1ste valor ha de estar entre E y 5, siendo E la fricci"n del hielo y 5 la del caucho. #ro!emos un ejemplo. #ara ello empecemos por eliminar el script vinculado a #orta2cripts. /uego editamos mi#rimer2cript, de esta guisa+ collider.material.dynamicMriction D EC function Mi(ed%pdate-. O rigid!ody.AddMorce-E,E,$[.C P

2alvamos y le asignamos el script al cu!o. ?omo vemos, le hemos dado al material la mnima fricci"n. /e damos al play y o!servamos que la fuer'a arrastra el cu!o sin pro!lemas. #ero ahora pro!ad a darle a dynamicMriction un valor de E.X.

staticFriction: var staticFriction : float

/a fricci"n usada cuando un o!jeto est reposando en una superficie. %sualmente un valor de E a 5. 2iguiendo con nuestro ejemplo, podemos teclear+ collider.material.staticMriction D EC collider.material.dynamicMriction D E.6C function Mi(ed%pdate-. O rigid!ody.AddMorce-E,E,$[.C P

Aqu nuestro cu!o tendra una fricci"n en reposo nula y una en movimiento !aja. #odemos tratar de invertir las tornas

entre am!os valores e ir e(perimentando.

"o+nciness: var bounciness : float

Gu capacidad de re!ote tiene la superficie. E es no re!ote. %n valor de 5 implica re!ote sin prdida de energa. #ara verlo con un ejemplo, eliminamos el script vinculado a nuestro cu!o, primero, y luego colocamos la esfera en la posici"n -6,K,E.. 1ditamos entonces mi#rimer2cript+ collider.material.!ounciness D E.`C

/o vinculamos a la esfera. @!servamos que sta re!ota un poco, so!re todo si comparamos el comportamiento de la esfera si esta!lecemos esta propiedad en cero. 9o o!stante, nos puede sorprender que a un valor tan alto como E.` la capacidad de re!ote de nuestra esfera no sea superior. icha sorpresa se acrecienta si le asignamos el valor m(imo -5. a !ounciness. /o que sucede es que %nity esta!lece una media entre los valores de re!ote de las dos superficies en contacto. #ro!ad a arrastrar mi#rimer2cript tam!in al 2uelo y veris la diferencia.

(rictionDirection9: var frictionDirection1 : "ector#

2e refiere a la direcci"n de anisotropa. /a fricci"n anisotr"pica est ha!ilitada salvo que su vector est a cero. /a anisotropa es aquella cualidad -forma, tamao, temperatura, etc. que cam!ia en un o!jeto cuando se mueve. ynamicMriction6 y staticMriction6, que estudiaremos a continuaci"n, sern aplicadas a lo lardo de friction irection6. /a direcci"n de anisotropa es relativa al sistema de coordenadas local del collider. %tili'aremos un pequeo ejemplo para entender c"mo funciona esto. #reviamente devolvemos a la esfera al suelo -position.yDE. y luego eliminamos el script mi#rimer2cript que tenemos vinculado al suelo y la esfera. 1ditamos despus de nuevo mi#rimer2cript+ collider.material.dynamicMriction D 5C collider.material.friction irection6 D >ector7.for4ardC collider.material.dynamicMriction6 D EC function Mi(ed%pdate-. O rigid!ody.AddMorce-K,E,E.C P

Arrastramos tras salvar el script al cu!o. Bien. >amos a tratar de e(plicar qu tenemos aqu. 1n primer lugar esta!lecemos la fricci"n dinmica del cu!o al m(imo, esto es, 5. e esta manera de!era resultar difcil poderlo arrastrar. #ero, a continuaci"n, le damos a friction irection6 un valor distinto a E,E,E, esto es, lo activamos. /o que le estamos diciendo aqui a %nity es que a lo largo del eje J -for4ard. la fricci"n del cu!o ser distinta que cuando se mueva a lo largo de los otros dos ejes -esto es la anisotropa.. ?oncretamente, en la tercera declaraci"n le indicamos a %nity que la fricci"n dinmica en ese eje J dynamicMriction9 ser nula -E.. 1n consecuencia, el resultado de este script de!era hacer que el cu!o se resistiera a moverse en los ejes I e , pero en cam!io no tuviera pro!lemas en hacerlo en el eje J. #ara a!rir !oca, le aplicamos al script acto seguido una fuer'a en el eje I. #ulsemos el play y compro!emos que el cu!o si se mueve. #ero ahora cam!iemos los parmetros de AddMorce a -K,E$K., esto es, aplicndole la misma fuer'a en el eje J -que no de!era tener resistencia. que al I. 2i funciona como de!iera, el cu!o empe'ar a moverse hacia delante, pero seguir

negndose a hacerlo hacia la derecha, aunque la presi"n en un eje y otro es la misma. #ro!ad.

d%namicFriction9: var d%namicFriction1 : float

2i la fricci"n anisotr"pica est ha!ilitada -friction irection6 no vale cero., dynamicMriction6 ser aplicada a lo largo del eje;s de friction irection6 que no valga cero.

staticFriction9: var staticFriction1 : float

2i la fricci"n anisotr"pica est ha!ilitada, staticMriction6 ser aplicada a lo largo de friction irection6.

(rictionCom"ine: var friction8ombine : 5h%sic3aterial8ombine

etermina c"mo se com!ina la fricci"n. :al como e(plica!a hace unas lneas en relaci"n con el re!ote, asimismo las propiedades de fricci"n son dependientes de la com!inaci"n de los dos materiales en contacto. #hysic*aterial?om!ine -el tipo de este atri!uto. es una enumeraci"n con las diferentes posi!ilidades de com!inaci"n de fricciones y capacidades de re!ote. Average+ /a media de la fricci"n o re!ote de los materiales de los dos colliders. *ultiply+ *ultiplica la fricci"n o re!ote de los materiales de los dos colliders. *inimum+ %sa el valor ms !ajo de fricci"n o re!ote de los dos colliders. *a(imum+ 1l valor ms alto de los dos.

As, la sinta(is para esta!lecer la fricci"n entre dos colliders en el valor ms alto de los dos sera as -a modo indicativo, nada ms.+ collider.material.friction?om!ine D #hysic*aterial?om!ine.*a(imumC

"o+nceCom"ine: var bounce8ombine : 5h%sic3aterial8ombine

etermina c"mo la capacidad de re!ote es com!inada. Al igual que la anterior, recurriremos al enum #ysic*aterial?om!ine.

FUNCIONES: /h%sic-aterial: static function 5h%sic3aterial () : 5h%sic3aterial

/a funci"n constructora crea un nuevo material. 1s normalmente ms fcil, sin em!argo, usar meramente un

collider.material y modificar el material vinculado directamente.

static function 5h%sic3aterial (name : String) : 5h%sic3aterial ?rea un nuevo material con un nom!re dado.

"$. CLASE COMPONENT

2i reali'amos un vista'o ms o menos fuga' a las varia!les y funciones contenidas en esta clase, ms de uno llegar a la conclusi"n de que guardan mucha similitud con las de la clase Fame@!ject. :ras compararlas ms detenidamente, podemos hacer la siguiente afirmaci"n+ la clase ?omponent no tiene ning3n atri!uto ni propiedad que no tenga la clase Fame@!ject. 1n aras de ser e(actos, podemos decir que la clase ?omponent es igual que la clase Fame@!ject, sin las propiedades is2tatic, layer y active y sin los mtodos 2etActive&ecursively, Add?omponent, y o!viamente su constructor. 1sto es as porque ?omponent no est pensada para ser usada directamente -para ello ya tenemos Fameo!ject. sino para que sus mtodos y atri!utos sean heredados por !uena parte de clases -de rigid!ody a camera y de joint a light pasando por transform.

#0. CLASE GUIELEMENT

>olvemos a !ajar de nuevo en nuestra jerarqua de clases para !uscar otra heredera de Behaviour. F%01lement es a su ve' una clase !ase, que esta!lece la funcionalidad mnima para todos los elementos de la F%0 -0nterfa' Frfica de %suario., entendiendo <elementos< como las imgenes y cadenas de te(to mostradas en la F%0.

FUNCIONES: :itTest: function HitTest (screen5osition : "ector# camera : 8amera & null) : boolean 1s un punto en la pantalla dentro del elemento. evuelve true si la posici"n pasada como parmetro screen#osition est contenida en este F%01lement. /a screen#osition es especificada en coordenadas de pantalla, a semejan'a de los valores retornados por 0nput.mouse#osition property. 2i no se proporciona a la funci"n una cmara en concreto, se asumir por esta una cmara cu!riendo la ventana del juego entera. )emos de tener en cuenta que si la posici"n est dentro del elemento, esta funci"n devolver true incluso si el gameo!ject pertenece al layer 0gnore &aycast.

GetScreenRect: function GetScreen7ect (camera : 8amera & null) : 7ect

evuelve lo !ordes del rectngulo del F%01lement en coordenadas de pantalla. 2i no se proporciona a la funci"n una cmara en concreto, se asumir por esta una cmara cu!riendo la ventana del juego entera.

#1. CLASE GUITE'T (I)

/a clase F%0:e(t es una de las dos que derivan de F%01lement -vista en la lecci"n anterior.. 1n concreto, la clase F%0:e(t es la que se ocupa de los string de te(to mostrados en un F%0 -de las imgenes se ocupa F%0:e(ture, que veremos luego..

VARIABLES: te)t: var te/t : String

>aria!le que contiene el te(to que se muestra en el F%0. 1mpecemos con la ha!itual tanda de ejemplos. #ara empe'ar, eliminamos el script que tenemos en el cu!o. /uego vamos a crear un gameo!ject de tipo F%0:e(t, para lo que nos vamos al men3DLFameo!jectDL?reate otherDLFui :e(t. &enom!ramos a nuestro nuevo gameo!ject como <mi:e(to<. @!servaremos que en la ventana Fame nos aparece un te(to -<gui te(t<. por defecto. 1ditamos mi#rimer2cript+ gui:e(t.te(t D <Bienvenidos a unityscripts<C

Arrastramos tras salvar el script a mi:e(to. #lay. @!servamos que el te(to que hemos introducido se nos muestra en la ventana Fame, tal como se ve en esta captura+

material: var material : 3aterial

1l material usado para renderi'ar el te(to. 1sta varia!le nos permite acceder a l para modificarlo o crear uno. 2i le damos un valor null se mostrar la fuente por defecto. #odemos por ejemplo completar un poco ms nuestro anterior script+ gui:e(t.te(t D <Bienvenidos a unityscripts<C gui:e(t.material.color D ?olor.magentaC

, ha!remos alterado el color de nuestras letras de !ienvenida.

!i)elO((set: var !i/elOffset : "ector1

1l despla'amiento en p(eles del te(to desde su posici"n inicial -marcada por su transform. en !ase a los valores contenidos en un >ector6.

%n ejemplo sencillo que no merece ms comentario+ gui:e(t.te(t D <Bienvenidos a unityscripts<C gui:e(t.material.color D ?olor.magentaC gui:e(t.pi(el@ffset D >ector6 -$5KE, 5EE.C

#2. CLASE GUITE'T ( II)

(ont: var font : Font

/a fuente usada para el te(to. #odemos asignar una de entre las que tengamos disponi!les.

alignment: var alignment : Te/t*lignment

/a alineaci"n del te(to. :e(tAlignment es una estructura con los valores /eft, ?enter y &ight. #ara pro!ar esto hemos de aadir ms te(to a nuestro ejemplo del captulo con algunos saltos de linea+ gui:e(t.te(t D <Bienvenidos a unityscripts. inAadimos una insegunda y tercera linea<C gui:e(t.material.color D ?olor.magentaC gui:e(t.alignment D :e(tAlignment.?enterC

#odemos compro!ar que el te(to se alinea centrado.

anchor: var anchor : Te/t*nchor

1l ancla del te(to. :e(tAnchor es una enumeraci"n que permite indicar d"nde se colocar el ancla o fijaci"n del te(to. :iene estas posi!ilidades+ %pper/eft+ 1l te(to se fija en la esquina superior i'quierda. #ara entendernos, la parte superior de la B de nuestro <Bienvenidos< del ejemplo estar u!icada en el punto marcado por las coordenadas de posici"n del transform del F%0:e(t. %pper?enter+ 1l te(to se fija en el lado central superior, esto es, la mitad de nuestra frase, medida hori'ontalmente, en su lado superior, coincidir con la u!icaci"n marcada por el transform. %pper&ight+ 1l te(to se fija en la esquina superior derecha. *iddle/eft+ 1l te(to se fija en el lado i'quierdo, centrado verticalmente. *iddle?enter+1l te(to se centra tanto vertical como hori'ontalmente respecto de su transform. *iddle&ight+ 1l te(to se ancla en el lado derecho, centrado verticalmente.

/o4er/eft+ 1l te(to se fija en la esquina inferior i'quierda. /o4er?enter+ 1l te(to se ancla en la parte inferior, centrada hori'ontalmente. /o4er&ight+ 1l te(to se fija en la esquina inferior derecha.

>amos a centrar nuestra frase respecto la posici"n del transform del F%0:e(t. Aadimos al script+ gui:e(t.te(t D <Bienvenidos a unityscripts. inAadimos una insegunda y tercera linea<C gui:e(t.material.color D ?olor.magentaC gui:e(t.alignment D :e(tAlignment.?enterC gui:e(t.anchor D :e(tAnchor.*iddle?enterC

Ahi lo tenemos.

lineS!acing: var lineS!acing : float

1l multiplicador del espacio de interlineado. 1sta cantidad ser multiplicada por el espacio de lnea definido en la fuente.

ta"Si*e: var tabSi0e : float

1l multiplicador de la anchura del ta!. 1sta cantidad se multiplicar con la anchura de ta! definida en la fuente.

(ontSi*e: var fontSi0e : int

1l tamao de fuente a usar -para fuentes dinmicas.. 2i lo esta!lecemos en una cantidad distinta de cero, el tamao de fuente especificado en la fuente importada es so!reescrito con un tamao personali'ado. 1sto s"lo es soportado para fuentes que usen fuentes dinmicas de renderi'ado. @tras fuentes siempre usarn el tamao de fuente por defecto.

(ontSt%le: var fontSt%le : FontSt%le

/o mismo que la anterior para el estilo de Muentes dinmicas.

#3. CLASE GUITE'TURE

?lase <hermana< de F%0:e(t, F%0:e(ture se encarga de manejar las imgenes que compondrn nuestra F%0 en 6d. #ara una mejor comprensi"n, no tenis ms que hacer lo siguiente+ eliminad el gameo!ject <mi:e(to< y acto seguido ir al men3DLgameo!jectDLcreate otherDLF%0 te(ture. Aparecer por defecto el icono de %nity en nuestra escena. /lamemos a nuestro nuevo gameo!ject <logo%nity<.

VARIABLES: color: var color : 8olor

1l color de la te(tura de la F%0. %n ejemplo muy sencillo. 1ditamos mi#rimer2cipt+ gui:e(ture.color D ?olor.!lueC

/o arrastramos a logo%nity, play, y nuestra imagen;te(tura pasa a ser de color a'ul.

te)t+re: var te/ture : Te/ture

/a te(tura usada para di!ujar. 1s posi!le que conservemos todava en #royecto la imagen que llamamos <multicolor< que usamos para que diera vueltas alrededor de la esfera. 2i la tenis ah, perfecto, y si no arrastrad hasta la carpeta assets donde tengis guardado vuestro proyecto cualquier imagen. /uego editamos mi#rimer2cript como sigue+ var una:e(tura + :e(tureC gui:e(ture.te(ture D una:e(turaC

2alvamos y arrastramos la te(tura a la varia!le e(puesta. Al darle al play o!servamos que la misma sustituye al logo de %nity.

!i)elInset: var !i/elInset : 7ect

0nserci"n de pi(els usada para ajustar p(eles para tamao y posi"n. #ueder poner el transform.local2cale a >ector7.'ero para hacer que la F%0 te(ture siempre tenga el mismo tamao de p(eles. &eeditemos una ve' ms nuestro script+ transform.position D >ector7.'eroC transform.local2cale D >ector7.'eroC gui:e(ture.pi(el0nset D &ect -5EE, 6K, 5YE, 5YE.C

Antes de darle al play e(pliquemos lo que hemos hecho. #rimero colocamos el transform de nuestra F%0:e(ture en el centro de la escena. Acto seguido colocamos la escala del transform a cero para que tenga el tamao que posteriormente le indiquemos, sin ning3n tipo de variaci"n. Acto seguido encuadramos la te(tura dentro de un rectngulo situado a 5EE p(eles desde la i'quierda y 6K desde arri!a, con una anchura y altura de 5YE p(eles. adle al play. Bye.

#4. CLASE GUI (I)

Bueno. )asta ahora nos hemos centrado en estudiar las clases que conforma!an el r!ol de herencia que ocupa !uena parte de la A#0 de %nity. )emos ido repasndolas -casi. todas, ms o menos en orden. A partir de ahora, en cam!io, vamos a recorrer clases que no estn vinculadas por relaci"n de herencia alguna con las ya e(plicadas -salvo alguna e(cepci"n, que anunciaremos como tal cuando corresponda.. #or tanto la cuesti"n del orden en su estudio o!edecer a criterios un poco ms liviamos, como su mayor o menor importancia o su vinculaci"n funcional con la clase que se haya estudiado con anterioridad. 1n !ase a ese 3ltimo criterio, y dado que las tres 3ltimas clases esta!an relacionadas con la inferfa' grfica de usuario, vamos a dedicar las siguientes lecciones a darle unas vueltas a diferentes clases que de una manera u otra estn vinculadas con la F%0. ,, como no poda ser de otra forma, empe'amos por la clase F%0, que representa la interfa' de %nity+

VARIABLES DE CLASE: s5in: static var s9in : G:IS9in

/a s8in -que podemos traducir por <piel< o <aspecto<. en uso. ?am!iando esta varia!le podemos cam!iar el loo8 de nuestra F%0. 2i su valor es null, se muestra la s8in que est por defecto. 1s una instancia de la clase F%028in, que estudiaremos a continuaci"n de sta.

color: static var color : 8olor

?olor del tintero glo!al de la F%0. Afectar tanto a la parte trasera de los elementos -!ac8ground. como a los colores del te(to que escri!amos so!re cualquier superficie. >amos con el primer ejemplo. 1mpe'amos por eliminar el o!jeto logo%nity. A continuaci"n editamos mi#rimer2cript+ function @nF%0-. O F%0.color D ?olor.yello4C F%0./a!el -&ect -5E, 5E, 6EE, 6E., <1sto es una etiqueta<.C F%0.Bo(-&ect-5E, KE, 5EE, KE., <%na caja<.C F%0.Button-&ect-5E,55E,[E,KE., <%n !ot"n<.C P

2alvamos y la arrastramos a #orta2cripts. 2i pulsamos play o!servaremos algo como esto+

Aqu hemos de e(plicar varias cosas. 1mpe'ando por el final, compro!amos en la imagen que el te(to de la F%0, so!re las diferentes superficies, es del color que le hemos indicado a la varia!le color. Asimismo, los !ordes de elementos como el !ot"n adquieren en su parte posterior -!ac8ground. ese color amarillo. 1sa declaraci"n y las anteriores estn contenidas dentro de una funci"n que vimos un poco de puntillas cuando estudiamos la clase *onoBehaviour+ la funci"n @nF%0 renderi'a y maneja eventos F%0. icho de otra manera, al llamar a esta funci"n activamos un evento F%0, que en este caso asigna un color a la letra y luego crea una etiqueta, una caja y un !ot"n.

"ac5gro+ndColor: static var bac9ground8olor : 8olor

?olor del tintero para todas las partes traseras -!ac8ground. de los elementos renderi'ados para la F%0. icho de otra manera, esta varia!le de clase hace parte del tra!ajo que efectua!a color, ya que colorea el !ac8ground pero no el te(to.

&eeditamos mi#rimer2cript como sigue+ function @nF%0-. O F%0.!ac8ground?olor D ?olor.redC F%0.Button-&ect-5E,5E,`E,7E., <*i !ot"n<.C P

Al darle al play podemos o!servar que los !ordes del !ot"n que hemos creado son de color rojo, color que se acrecienta cuando colocamos el rat"n encima. 1n cam!io, el color del te(to sigue siendo !lanco -el color por defecto.

contentColor: static var content8olor : 8olor

?olor de tinta para todo el te(to renderi'ado en la F%0. 1sta funci"n es la complementaria de la anterior con relaci"n a color, ya que no afecta al color del !ac8ground, sino al del te(to. #or ejemplo+ function @nF%0-. O F%0.content?olor D ?olor.yello4C F%0.!ac8ground?olor D ?olor.redC F%0.Button-&ect-5E,5E,`E,7E., <*i !ot"n<.C P

>emos aqu claramente las diferencias entre ?ontent?olor -amarillo. y !ac8ground?olor -rojo..

#5. CLASE GUI ( II)

changed: static var changed : boolean

evuelve true si alg3n control cam!ia el valor de los datos de entrada de la F%0. #odemos aprovechar el ejemplo que aparece en el manual de referencia para ilustrarnos. 1ditamos mi#rimer2cript como sigue+ var mi:e(to + 2tring D <?am!iame<C function @nF%0 -. O mi:e(to D F%0.:e(tMield -&ect -5E, 5E, 6EE, 6E., mi:e(to, 6K.C if -F%0.changed. e!ug./og-<1l campo de te(to se modific"<.C P

1l contenido del script es !astante intuitivo+ creamos un campo de te(to edita!le con la funci"n :e(tMield, que en !reve estudiaremos, y, si procedemos a cam!iar su contenido inicial se nos imprimir en pantalla un te(to avisndonos de

dicha modificaci"n.

ena"led: static var enabled : boolean )a!ilita;desha!ilita la F%0. 2i esta!lecemos esta varia!le en false se desha!ilitan todas las interacciones de la F%0. :odos los controles se di!ujarn semitransparentes, y no responern a las entradas del usuario.

toolti!: static var toolti! : String

%n tooltip es ese pequea nota emergente que aparece a veces con determinada informaci"n cuando colocamos un rat"n so!re un control, o dicho control tiene el foco del teclado. >amos con el pertinente ejemplo. A!rimos nuestro script y+ function @nF%0 -. O F%0.Button -&ect -5E,5E,5EE,6E., F%0?ontent -<#ulsame<, <1ste es el tooltip<..C F%0./a!el -&ect -5E,XE,5EE,XE., F%0.tooltip.C P

1l script funciona de la siguiente manera+ ?omo viene siendo ha!itual, empe'amos creando un evento F%0 con la funci"n @nF%0. Acto seguido creamos un !ot"n con una determinada u!icaci"n y dimensiones, y le pasamos como segundo parmetro la funci"n constructora de la clase F%0?ontent -de cercano estudio., que a su ve' admite como parmetros el te(to del !ot"n, una imagen -en este caso no. y en su caso el te(to del tooltip que se de!a activar al pasarle el rat"n por encima. Acto seguido hemos de crear propiamente la etiqueta del tooltip, indicando su u!icaci"n y dimensiones. Al darle al play y colocar el rat"n so!re el !ot"n, automticamente nos aparecer un tooltip con el te(to indicado, que desaparecer al retirar el rat"n de dicho control.

de!th: static var de!th : int

1l orden de profundidad que tendr cada actividad F%0 en ejecuci"n. Guiere esto decir que cuando tengamos varios scripts ejecutndose simultneamente, los elementos F%0 que tengan valores de profundidad ms !ajos aparecern en la pantalla encima de los que lo tengan ms altos

#!. CLASE GUI (III)

FUNCIONES DE CLASE: la"el: static function -abel (!osition : 7ect static function -abel (!osition : 7ect static function -abel (!osition : 7ect static function -abel (!osition : 7ect static function -abel (!osition : 7ect static function -abel (!osition : 7ect te/t : String) : void image : Te/ture) : void content : G:I8ontent) : void te/t : String st%le : G:ISt%le) : void image : Te/ture st%le : G:ISt%le) : void content : G:I8ontent st%le : G:ISt%le) : void

?rea una etiqueta -la!el. de te(to o de imagen en la pantalla. ?omo podemos o!servar, esta funci"n tiene varios prototipos, permitindonos pasarle distintos parmetros en !ase a la necesidad y datos que tengamos en cada momento. ichos parmetros seran+ position+ &ectangulo en la pantalla a usar para la etiqueta. te(t+ :e(to a mostrar en la etiqueta. image+ :e(tura;imagen a mostrar en la etiqueta. content+ :e(to, imagen y tooltip para esta etiqueta. style+ 1l estilo a usar. 2i no se indica, se aplicar el estilo para etiquetas que tenga el F%028ing que se est usando.

1n !ase al significado de estos parmetros, podemos fcilmente deducir la diferencia entre los distintos prototipos de esta funci"n. /as etiquetas o la!els en s no implican ning3n tipo de interacci"n con el usuario, no captan clic8s del rat"n y son siempre renderi'adas en un estilo normal -no por ejemplo como los !otones, que aparte del estilo normal tienen otro para cuando se pasa el rat"n por encima, otro cuando se presionan, o cuando se activan, etc.. #ongamos el ms sencillo de los ejemplos+ mostremos en pantalla el famoso hello 4orld. function @nF%0 -. O F%0./a!el -&ect -5E, 5E, 5EE, 6E., <)ello _orld<.C P

?omo vemos, hemos optado por el primer prototipo de la funci"n de los que mostramos al inicio. *eramente el rectngulo con la posici"n -5E,5E. y tamao -5EE,6E. del rectngulo donde u!icaremos la etiqueta, y como segundo parmetro un string con el te(to. 2i en lugar de mostrar un te(to quisiramos hacer lo propio con una imagen, modificaramos la funci"n como sigue+ var una:e(tura + :e(ture6 C function @nF%0 -. O F%0./a!el -&ect -5E, XE, una:e(tura.4idth, una:e(tura.height., una:e(tura.C P

2alvamos y arrastramos la te(tura que tenamos en la carpeta assets de ejemplos anteriores a la varia!le e(puesta de este script que tenemos vinculado a #orta2cripts. 1n este prototipo de nuevo pasamos como parmetro primero un rectngulo con la posici"n del rectngulo -5E,XE. y, en lugar de indicar directamente las dimensiones que ha de tener dicho rectngulo, aprovechamos la anchura y altura originales de la imagen arrastrada para no recortarla -aunque por supuesto podemos sentirnos li!res de esta!lecer unas dimensiones fijas.. 1l segundo parmetro es donde difiere este prototipo del anterior, ya que en lugar de suministrar un string pasamos una te(tura.

Dra.Te)t+re:

static function Dra)Te/ture (!osition : 7ect image : Te/ture scale3ode : Scale3ode & Scale3ode(StretchToFill al!ha=lend : boolean & true image*s!ect : float & ') : void

i!uja una te(tura dentro de un rectngulo. :iene los siguientes parmetros+ position+ &ectngulo en la pantalla para di!ujar la te(tura dentro. image+ :e(tura a mostrar. scale*ode+ ?"mo escalar la imagen cuando la proporci"n hace que no encaje !ien dentro del rectngulo. alphaBlend+ 2i el canal alfa es me'clado en la imagen -por defecto. imageAspect+ #roporci"n a usar para la imagen fuente. 2i vale E -por defecto., es usada la proporci"n de la imagen. #asad un 4;h para la deseada proporci"n, lo cual permite cam!iar la proporci"n de la imagen original sin cam!ier la anchura y altura de p(eles.

1l parmetro scale*ode es a su ve' una enumeraci"n que acepta los siguientes valores+ 2tretch:oMill+ 1stira la te(tura para rellenar el rectangulo entero. 2caleAnd?rop+ 1scala la te(tura, manteniendo la proporci"n, hasta cu!rir completamente el rectngulo. 2i la te(tura se di!uja en un rectngulo con una proporci"n diferente, la imagen se recorta. 2cale:oMit+ 1scala la te(tura, manteniendo la proporci"n, hasta encajar completamente dentro del rectngulo.

>amos ahora a di!ujar una te(tura en la esquina i'quierda de la pantalla, te(tura que se di!ujar en una ventana de TE ( TE p(eles. A la te(tura original le daremos una proporci"n de 5E ( 5 y la haremos encajar luego en el rectngulo anterior con el 2calemode.2cale:oMit, de tal manera que la te(tura se escalar hasta encajar hori'ontalmente con el rectngulo, manteniendo la proporci"n de 5E;5. function @nF%0-. O P F%0. ra4:e(ture-&ect-5E,5E,TE,TE., a:e(ture, 2cale*ode.2cale:oMit, true, 5E.Ef.C P

Bo):

static function =o/ (!osition : 7ect static function =o/ (!osition : 7ect static function =o/ (!osition : 7ect static function =o/ (!osition : 7ect static function =o/ (!osition : 7ect static function =o/ (!osition : 7ect

te/t : String) : void image : Te/ture) : void content : G:I8ontent) : void te/t : String st%le : G:ISt%le) : void image : Te/ture st%le : G:ISt%le) : void content : G:I8ontent st%le : G:ISt%le) : void

?omo su nom!re indica, crea un cuadro o caja. 2us diferentes prototipos cuentan con estos parmetros+ position+ &ectngulo en la pantalla a usar para la caja. te(t+ :e(to a mostrar en la caja. image+ :e(tura a mostrar en la caja. content+ :e(to, imagen y tooltip para la caja. style+ 1l estilo a usar. 2i no se indica e(presamente, el estilo de la caja ser el del F%028in en uso.

#ongamos un ejemplo sencillo+

function @nF%0-. O F%0.Bo(-&ect-5E,6E,5EE,XE.,<)ola, mundo<.C P

#". CLASE GUI (IV)


B+tton: static function =utton (!osition : 7ect static function =utton (!osition : 7ect static function =utton (!osition : 7ect static function =utton (!osition : 7ect static function =utton (!osition : 7ect static function =utton (!osition : 7ect te/t : String) : boolean image : Te/ture) : boolean content : G:I8ontent) : boolean te/t : String st%le : G:ISt%le) : boolean image : Te/ture st%le : G:ISt%le) : boolean content : G:I8ontent st%le : G:ISt%le) : boolean

Munci"n que crea un !ot"n que, al ser pulsado por un usuario, dispara alg3n tipo de evento. %na cosa que puede llamar la atenci"n inicialmente, y que tiene mucho que ver con la manera un poco atpica de usar esta funci"n, es que retorna un !ooleano que es esta!lecido en true cuando el usuario hace clic8 so!re el !ot"n. e esta suerte, la funci"n devolver false hasta que se pulse el !ot"n, lo que implica en la prctica que esta funci"n se suele usar tras una declaraci"n if, como enseguida veremos. Antes detengmonos un momento en los parmetros, que ya nos de!eran sonar+ position+ &ectangulo en la pantalla a usar para el !ot"n. te(t+ :e(to a mostrar en el !ot"n. image+ :e(tura;imagen a mostrar en el !ot"n. content+ :e(to, imagen y tooltip para este !ot"n. style+ 1l estilo a usar. 2i no se indica, se aplicar el estilo para !otones que tenga el F%028ing que se est usando.

, ahora es el momento de entender con un ejemplo lo que os comenta!a antes so!re la peculiar manera de usar la funci"n !utton+ var una:e(tura + :e(tureC function @nF%0-. O if -Quna:e(tura. O e!ug./og1rror-<Asigne por favor una te(tura en el inspector<.C returnC P if -F%0.Button-&ect-5E,5E,KE,KE.,una:e(tura.. e!ug./og-<)as hecho clic8 en el !ot"n que tiene una imagen<.C if -F%0.Button-&ect-5E,`E,KE,7E.,<?lic8<.. e!ug./og-<)as hecho clic8 en el !ot"n con te(to<.C P

>amos por partes. 2alvamos el script y, sin arrastrar ninguna te(tura a la varia!le e(puesta que nos de!era aparecer en el inspector al tener #orta2cripts seleccionado, pulsamos play. 9os aparecer un mensaje de error avisndonos de que de!emos arrastrar dicha te(tura. 1s esta una variande de e!ug./og llamada e!ug./og1rror, que hace que el mensaje apare'ca en rojo. etenemos el reproductor, arrastramos la te(tura y volvemos a pulsar play. @!servaremos que nos aparecen dos !otones, uno con la te(tura arrastrada por nosotros, otros con el te(to indicado, y que al pulsarlos aparecen en pantalla sendos te(tos. /o que personalmente me parece ms interesante de todo esto es la manera de utili'ar la funci"n+ if -F%0.Button-&ect-5E,`E,KE,7E.,<?lic8<..

#ensemos que con esta declaraci"n estamos haciendo dos cosas+ primero, al pasarla como condici"n de if nos aseguramos de que una ve' el user clic8e el !ot"n y por ende la funci"n Button devuelva true, se ejecutar las declaraciones que se vean afectadas por ese if. #ero, adems, previo a devolver true o false, %nity ejecuta la funci"n, y por consiguiente se renderi'a el !ot"n en la pantalla.

Re!eatB+tton: static function 7e!eat=utton (!osition : 7ect static function 7e!eat=utton (!osition : 7ect static function 7e!eat=utton (!osition : 7ect static function 7e!eat=utton (!osition : 7ect static function 7e!eat=utton (!osition : 7ect static function 7e!eat=utton (!osition : 7ect te/t : String) : boolean image : Te/ture) : boolean content : G:I8ontent) : boolean te/t : String st%le : G:ISt%le) : boolean image : Te/ture st%le : G:ISt%le) : boolean content : G:I8ontent st%le : G:ISt%le) : boolean

Munci"n que crea un !ot"n que est activo mientras el usuario lo presiona.

Te)tField:

static function Te/tField (!osition : 7ect static function Te/tField (!osition : 7ect static function Te/tField (!osition : 7ect static function Te/tField (!osition : 7ect

te/t : String) : String te/t : String ma/-ength : int) : String te/t : String st%le : G:ISt%le) : String te/t : String ma/-ength : int st%le : G:ISt%le) : String

?rea un campo de te(to de una lnea donde el usuario puede editar un string. evuelve un string con el te(to editado. :iene estos parmetros+ position+ &ectngulo en la pantalla a usar para el campo de te(to. te(t+ :e(to a editar. 1l valor de retorno de!e ser reasignado de vuelta al string tal como se ensea en el pr"(imo ejemplo. ma(/ength+ /a longitud m(ima del string. 2i no se indica, el usuario puede escri!ir sin ning3n tipo de lmite. style+ 1l estilo a usar. 2i no se indica, se aplicar el estilo para te(tMield que tenga el F%028in en uso.

1sta funci"n es importante porque permite una mayor interactividad con el usuario que meramente pulsar determinamos !otones. #or ello es importante que el te(to que dicho usuario introduce se almacene de!idamente. :al como indica el manual de referencia al ha!lar del parmetro te(t, la soluci"n ideal es iniciali'ar una varia!le string con el valor que le damos por defecto, y reutili'ar dicha varia!le para posteriormente contener el string ya modificado y devuelto por la funci"n. 1n definitiva+ var mensaje + 2tring D <1scri!e algo<C function @nF%0 -. O mensaje D F%0.:e(tMield -&ect -5E, 5E, 6EE, 6E., mensaje, 6K.C e!ug./og-mensaje.C P

?omo veis, la idea es que <mensaje< sirva tanto para contener el string inicial como el modificado. /e he aadido a continuaci"n un e!ug./og para que compro!is en tiempo real c"mo va cam!iando el contenido de la varia!le.

/ass.ordField: static function 5ass)ordField (!osition : 7ect !ass)ord : String mas98har : char) : String

static function 5ass)ordField (!osition : 7ect !ass)ord : String mas98har : char ma/-ength : int) : String static function 5ass)ordField (!osition : 7ect !ass)ord : String mas98har : char st%le : G:ISt%le) : String static function 5ass)ordField (!osition : 7ect !ass)ord : String mas98har : char ma/-ength : int st%le : G:ISt%le) : String ?rea un campo de te(to donde el usuario puede introducir una contrasea. editada. evuelve un string con la contrasea

?uenta con los siguientes parmetros+ position+ &ectngulo en la pantalla a usar para el campo de te(to. pass4ord+ ?ontrasea a editar. 1l valor de retorno de esta funci"n de!e ser reasignado al string que contena el valor original. mas8?har+ 1l carcter con el que queremos enmascarar la contrasea. ma(/ength+ /a longitud m(ima del string. 2i no se indica, el usuario no tendr lmite para escri!ir. style+ 1l estilo a usar. 2i no se indica, se usar el estilo para te(tfield que tenga el F%028in que se est usando.

#odemos apreciar que en definitiva esta funci"n es como la anterior, con la salvedad de que en la presente le aadimos un carcter -tradicionalmente un asterisco. que queremos que apare'ca en pantalla cuando el usuario teclee su contrasea. var mi#in + 2tring D <<C function @nF%0 -. O mi#in D F%0.#ass4ordMield -&ect -5E, 5E, 6EE, 6E., mi#in, <Z<UEV, 6K.C P

##. CLASE GUI (V)

Te)tArea: static function Te/t*rea (!osition : 7ect static function Te/t*rea (!osition : 7ect static function Te/t*rea (!osition : 7ect static function Te/t*rea (!osition : 7ect te/t : String) : String te/t : String ma/-ength : int) : String te/t : String st%le : G:ISt%le) : String te/t : String ma/-ength : int st%le : G:ISt%le) : String evuelve el string editado.

?rea un rea de te(to de varias lneas donde el usuario puede editar un string.

SetNe)tControlName: static function Set4e/t8ontrol4ame (name : String) : void

Munci"n que esta!lece el nom!re del siguiente control. 1sto hace que el siguiente control sea registrado con un nom!re dado.

GetNameO(Foc+sedControl: static function Get4ameOfFocused8ontrol () : String

@!tiene el nom!re del control que tiene el foco. 1l nom!re de los controles es asignado usando 2et9e(t?ontrol9ame. ?uando un control tiene el foco, esta funci"n devuelve su nom!re. Fet9ame@fMocused?ontrol funciona especialmente !ien cuando tratamos con ventanas para loguearse.

Foc+sControl: static function Focus8ontrol (name : String) : void

*ueve el foco del teclado a un control nom!rado.

Toggle: static function Toggle (!osition : 7ect static function Toggle (!osition : 7ect static function Toggle (!osition : 7ect static function Toggle (!osition : 7ect static function Toggle (!osition : 7ect static function Toggle (!osition : 7ect value : boolean value : boolean value : boolean value : boolean value : boolean value : boolean te/t : String) : boolean image : Te/ture) : boolean content : G:I8ontent) : boolean te/t : String st%le : G:ISt%le) : boolean image : Te/ture st%le : G:ISt%le) : boolean content : G:I8ontent st%le : G:ISt%le) : boolean

?rea un !ot"n de tipo interruptor -on;off.. evuelve el nuevo valor del !ot"n-true;false..

Tool"ar: static function Toolbar (!osition : 7ect static function Toolbar (!osition : 7ect static function Toolbar (!osition : 7ect static function Toolbar (!osition : 7ect static function Toolbar (!osition : 7ect static function Toolbar (!osition : 7ect selected : int selected : int selected : int selected : int selected : int selected : int te/ts : string+,) : int images : Te/ture+,) : int content : G:I8ontent+,) : int te/ts : string+, st%le : G:ISt%le) : int images : Te/ture+, st%le : G:ISt%le) : int contents : G:I8ontent+, st%le : G:ISt%le) : int

Munci"n que crea una !arra de herramientas. evuelve $un int$ el ndice de la tool!ar seleccionado. :iene estos parmetros+ position+ &ectngulo en la pantalla a usar para la !arra de herramientas. selected+ 1l ndice del !ot"n seleccionado. te(ts+ %n array de strings a ensear en los !otones de la !arra. images+ %n array de te(tras para los !otones de la !arra de herramientas. contents+ %n array de te(to, imgenes y tooltips para los !otones del tool!ar. style+ 1l estilo a usar. 2i no se indica, se usar el estilo para !otones que tenga la F%028in que se est usando.

>emoslo con un ejemplo+ var tool!ar0ndice + int D EC var tool!ar2trings + 2tringUV D U<:ool!ar5<, <:ool!ar6<, <:ool!ar7<VC function @nF%0 -. O tool!ar0ndice D F%0.:ool!ar -&ect -6K, 6K, 6KE, 7E., tool!ar0ndice, tool!ar2trings.C e!ug./og-<1l ndice pulsado es < B tool!ar0ndice.C P

@!servaremos que nos aparece en pantalla al pulsar play una !arra con tres !otones, estando por defecto activado el primero, que corresponde con el ndice cero que le hemos pasado como parmetro. /e hemos aadido la funci"n e!ug./og para acreditar que al presionar los distintos !otones se le asigna a la varia!le el ndice de cada !ot"n.

#$. CLASE GUI (VI)

SelectionGrid: static function SelectionGrid (!osition : 7ect static function SelectionGrid (!osition : 7ect static function SelectionGrid (!osition : 7ect static function SelectionGrid (!osition : 7ect static function SelectionGrid (!osition : 7ect static function SelectionGrid (!osition : 7ect selected : int selected : int selected : int selected : int selected : int selected : int te/ts : string+, /8ount : int) : int images : Te/ture+, /8ount : int) : int content : G:I8ontent+, /8ount : int) : int te/ts : string+, /8ount : int st%le : G:ISt%le) : int images : Te/ture+, /8ount : int st%le : G:ISt%le) : int contents : G:I8ontent+, /8ount : int st%le : G:ISt%le) : int

)ace una cuadrcula -grid. de !otones.

evuelve un int con el ndice del !ot"n seleccionado.

#ermite los siguientes parmetros+ position+ &ectndulo de la pandalla a usar para la cuadrcula. selected+ 1l ndice del !ot"n seleccionado de la cuadrcula. te(ts+ %n array de strings que mostrar en los !otones de la cuadrcula. images+ %n array de te(turas en los !otones de la cuadrcula. contents %n array de te(to, imgenes y tooltips para los !otones de la cuadrcula (?ount+ ?untos elementos ca!en en la direcci"n hori'ontal. /os controles sern escalados para encajar a meno que el estilo elegido para usar sea fi(ed_idth. style+ 1l estilo a usar. 2i no se indica, se usa el estilo de !ot"n marcado por el F%028in que se est usando.

>eamos un !reve ejemplo+ var selFrid0nt + int D EC var sel2trings + 2tringUV D U<Frid 5<, <Frid 6<, <Frid 7<, <Frid X<VC function @nF%0 -. O selFrid0nt D F%0.2electionFrid -&ect -6K, 6K, 5EE, 7E., selFrid0nt, sel2trings, 6.C P

:ori*ontalSlider: static function Hori0ontalSlider (!osition : 7ect value : float left"alue : float right"alue : float) : float static function Hori0ontalSlider (!osition : 7ect value : float left"alue : float right"alue : float slider : G:ISt%le thumb : G:ISt%le) : float ?rea una !arra de despla'amiento hori'ontal que el usuario puede arrastrar para cam!iar un valor entre un mnimo y un

m(imo. evuelve un float con el valor que ha sido elegido por el usuario. #armetros+ position+ &ectngulo en la pantalla a usar para la !arra. value+ 1l valor que muestra la !arra. 1sto determina la posici"n del desli'a!le m"vil. left>alue+ 1l valor del e(tremo i'quierdo de la !arra. right>alue 1l valor del e(tremo derecho de la !arra. slider+ 1l F%02tyle a usar para mostrar el rea de arrastre. 2i no se utili'a, se usar el estilo de hori'ontal2lider que tenga por defecto el F%028in que se est usando. thum!+ 1l F%02tyle a usar para mostrar el desli'a!le m"vil. 2i no se usa, se usar el estilo de hori'ontal2lider:hum! style que tenga por defecto el F%028in que se est usando.

, por 3ltimo el ejemplo+ var valor el2lider + float D E.EC function @nF%0 -. O valor el2lider D F%0.)ori'ontal2lider -&ect -6K, 6K, 5EE, 7E., valor el2lider, E.E, 5E.E.C P

VerticalSlider: static function "erticalSlider (!osition : 7ect value : float to!"alue : float bottom"alue : float) : float static function "erticalSlider (!osition : 7ect value : float to!"alue : float bottom"alue : float slider : G:ISt%le thumb : G:ISt%le) : float

?rea una !arra de desli'amiento vertical que el usuario puede arrastrar para cam!iar un valor entre un mnimo y un m(imo. evuelve un float con el valor que ha sido escogido por el usuario. :iene los siguientes parmetros+ position+ &ectngulo en la pantalla a usar para la !arra. value+ 1l valor que muestra la !arra. 1sto determina la posici"n del desli'a!le m"vil. top>alue+ 1l valor en lo alto de la !arra !ottom>alue+ 1l valor en lo !ajo de la !arra slider+ 1l F%02tyle a usar para mostrar el rea de arrastre. 2i no se utili'a, se usar el estilo de vertical2ider que tenga por defecto el F%028in que se est usando. thum!+ 1l F%02tyle a usar para mostrar el desli'a!le m"vil. 2i no se usa, se usar el estilo de vertical2lider:hum! que tenga por defecto el F%028in que se est usando.

:ori*ontalScroll"ar:

static function Hori0ontalScrollbar (!osition : 7ect value : float si0e : float left"alue : float right"alue : float) : float static function Hori0ontalScrollbar (!osition : 7ect value : float si0e : float left"alue : float right"alue : float st%le : G:ISt%le) : float

?rea una !arra de despla'amiento -scroll!ar. hori'ontal. %n scroll!ar es lo que usamos para despla'arnos por un documento. #or norma general en lugar de scroll!ar usaremos scrollie4s. evuelve un float con el valor modificado. 1ste puede ser cam!iado por el usuario arrastrando el scroll!ar o clic8ando en las flechas de los e(tremos.

%n !reve ejemplo+ var valor eBarra + floatC function @nF%0 -. O valor eBarra D F%0.)ori'ontal2croll!ar -&ect -6K, 6K, 5EE, 7E., valor eBarra, 5.E, E.E, 5E.E.C P

VerticalScroll"ar: static function "erticalScrollbar (!osition : 7ect value : float si0e : float to!"alue : float bottom"alue : float st%le : G:ISt%le) : float

?rea una !arra de despla'amiento -scroll!ar. vertical.

$0. CLASE GUI ( VII)

BeginGro+!: static function =eginGrou! (!osition : 7ect) : void static function =eginGrou! (!osition : 7ect te/t : String) : void static function =eginGrou! (!osition : 7ect image : Te/ture) : void static function =eginGrou! (!osition : 7ect content : G:I8ontent) : void static function =eginGrou! (!osition : 7ect st%le : G:ISt%le) : void static function =eginGrou! (!osition : 7ect te/t : String st%le : G:ISt%le) : void static function =eginGrou! (!osition : 7ect image : Te/ture st%le : G:ISt%le) : void static function =eginGrou! (!osition : 7ect content : G:I8ontent st%le : G:ISt%le) : void

?omien'a un grupo. 1sta funci"n de!e emparejarse con una llamada a 1ndFroup. ?uando comen'amos un grupo, el sistema de coordenadas para los controles F%0 ser tal que coincidir la coordenada -E,E. con la esquna superior i'quierda del grupo. /os grupos pueden ser anidados, estando lo hijos agrupados respecto de sus padres. 1sto es muy 3til cuando movemos un mont"n de elementos F%0 a lo largo de la pantalla. %n caso de uso com3n es disear nuestros men3s para que encajen en un especfico tamao de pantalla, centrando la F%0 en pantallas ms amplias. /os distintos prototipos de funci"n usan estos parmetros+ position+ &ectngulo en la pantalla a usar para el grupo. te(t+ :e(to a mostrar en el grupo.

image+ content+

style+

:e(tura a mostrar en el grupo. :e(to, imagen y tooltip para este grupo. 2i el parmetro es proporcionado, cualquier clic8 de rat"n es capturado por el grupo y si no se proporciona, no se renderi'a ing3n !acground y los clic8s del rat"n son renderi'ados. 1l estilo a usar para el !ac8ground.

>eremos muy claramente la funcionalidad de este mtodo con un ejemplo+ function @nF%0 -. O F%0.BeginFroup -ne4 &ect -2creen.4idth ; 6 $6EE , 2creen.height ; 6 $ 5KE, XEE, 7EE..C F%0.Bo( -ne4 &ect -E,E,XEE,7EE., <1ste cuadrado est ahora centrado, y dentro del mismo podemos colocar nuestro men3<.C F%0.1ndFroup -.C P

1(pliquemos pso a paso en qu consiste lo que hemos hecho. #ara empe'ar usamos la funci"n BeginFroup para crear un grupo en un rectngulo que se iniciar en el centro de la pantalla. 2i lo u!icramos en 4idth;6 el rectngulo quedara despla'ado, pues no se estara teniendo en cuenta en este caso la anchura del propio rectngulo. e esta manera, le hemos de restar al centro de la pantalla la mitad de la anchura del rectngulo, asegurndonos as que queda justo en el centro. )acemos lo propio con la altura. %na ve' ya tenemos definido para el grupo un rectngulo centrado con unas dimensiones de XEE I 7EE, ahora para los controles dentro de dicho grupo la esquina superior i'quierda del rectngulo pasa a ser la coordenada E,E. As, cuando a continuaci"n invocamos una caja con un te(to y la u!icamos en las coordenadas E,E, sta se nos viene a colocar al inicio del rectngulo del grupo. 9o hemos de olvidarnos, por 3ltimo, que si usamos una funci"n BeginFroup hemos de usar cuando aca!emos de disear el grupo una funci"n 1ndFroup o!ligatoriamente, para indicarle a %nity que las instrucciones referidas al grupo ya se han aca!ado.

EndGro+!: static function 6ndGrou! () : void

Minali'a un grupo.

BeginScrollVie.: static function =eginScroll"ie) (!osition : 7ect scroll5osition : "ector1 static function =eginScroll"ie) (!osition : 7ect scroll5osition : "ector1 boolean al)a%sSho)"ertical : boolean) : "ector1 static function =eginScroll"ie) (!osition : 7ect scroll5osition : "ector1 verticalScrollbar : G:ISt%le) : "ector1 static function =eginScroll"ie) (!osition : 7ect scroll5osition : "ector1 boolean al)a%sSho)"ertical : boolean hori0ontalScrollbar : G:ISt%le

vie)7ect : 7ect) : "ector1 vie)7ect : 7ect al)a%sSho)Hori0ontal : vie)7ect : 7ect hori0ontalScrollbar : G:ISt%le vie)7ect : 7ect al)a%sSho)Hori0ontal : verticalScrollbar : G:ISt%le) : "ector1

0nicia una vista de despla'amiento -scrollvie4. dentro de la F%0. %n scrollvie4 nos permite poner una rea ms pequea en la pantalla dentro de un rea mucho mayor, usando !arras de despla'amiento -scroll!ars. a los lados. 1sta funci"n devuelve la posici"n del scroll modificada. Al igual que con otras varia!les, se recomienda reintroducir en la varia!le que se le pasa a la funci"n los datos nuevos que sta devuelve. :iene estos parmetros+ position+ &ectngulo en la pantalla a usar para el 2croll>ie4.

scroll#osition+

/a distancia en p(eles que la vista es despla'ada en las direcciones I e ,. vie4&ect+ 1l rectngulo usado dentro del scrollvie4. al4ay2ho4)ori'ontal+ #armetro opcional para ensear siempre el scroll!ar hori'ontal. 2i lo esta!lecemos en falso o no lo aportamos a la funci"n, s"lo se ensear cuando client&ect sea ms ancho que la posici"n. al4ay2ho4>ertical+ /o mismo para el scroll!ar vertical. hori'ontal2croll!ar+ F%02tyle opcional a usar por el scroll!ar hori'ontal. 2i no se aporta, se usar el estilo hori'ontal2croll!ar del F%028in que se est usando. vertical2croll!ar+ /o mismo para el scroll!ar vertical

EndScrollVie.: static function 6ndScroll"ie) () : void

Aca!a un scrollvie4 iniciado con una llamada a Begin2croll>ie4.

ScrollTo:

static function ScrollTo (!osition : 7ect) : void espla'a todos los scrollvie4s incluidos para tratar de hacer visi!le una determinada posici"n.

;indo.: static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int client7ect : 7ect client7ect : 7ect client7ect : 7ect client7ect : 7ect client7ect : 7ect client7ect : 7ect func : ?indo)Function func : ?indo)Function func : ?indo)Function func : ?indo)Function func : ?indo)Function func : ?indo)Function te/t : String) : 7ect image : Te/ture) : 7ect content : G:I8ontent) : 7ect te/t : String st%le : G:ISt%le) : 7ect image : Te/ture st%le : G:ISt%le) : 7ect title : G:I8ontent st%le : G:ISt%le) : 7ect

?rea una ventana emergente y devuelve el rectngulo en el que dicha ventana se u!ica. /as ventanas flotan so!re los controles F%0 normales, _indo4s float a!ove normal F%0 controls, y pueden ser opcionalmente arrastrados por los usuarios finales. A diferencia de otros controles, necesitamos pasarles una funci"n separada para los controles F%0 para colocarlos dentro de la ventana. 9ota+ 2i usamos F%0/ayout -de pr"(ima e(plicaci"n. para colocar nuestros componentes dentro de la ventana, de!emos usar F%0/ayout._indo4. #armetros+ id+ %na 0 3nica a usar para cada ventana. client&ect+ &ectngulo en la pantalla a usar por el grupo. func+ /a funci"n que crea el F%0 dentro de la ventana. 1sta funci"n de!e tomar un parmetro, que ser la 0 de la ventana para la que se est creando la F%0. te(t+ :e(to a mostrar como ttulo para la ventana. image+ :e(tura que muestra una imagen en la !arra del ttulo. content+ :e(to, imagen y tooltip para esta ventana.

style+

%n estilo opcional a usar por la ventana. 2i no se aporta, se usar el estilo de ventana del F%028in corriente.

, vamos con un ejemplo+ var 4indo4&ect + &ect D &ect -6E, 6E, 56E, KE.C function @nF%0 -. O 4indo4&ect D F%0._indo4 -E, 4indo4&ect, ?rea*i>entana, <*i ventana<.C P function ?rea*i>entana -4indo40 + int. O if -F%0.Button -&ect -5E,6E,5EE,6E., <)ola mundo<.. print -<&eci! un clic8<.C P

?reamos una ventana con 0 E, que u!icamos en un rectngulo cuyas coordenadas y dimensiones estn almacenadas en una varia!le, varia!le en la cual almacenaremos el rectngulo retornado por la funci"n. ?omo tercer parmetro le pasamos una funci"n que es la que crea los controles que irn dentro de la ventana, y por 3ltimo el ttulo de dicha ventana. /a funci"n que crea los controles toma como parmetro a su ve' el primer parmetro de F%0._indo4, que es la id de la ventana, y en este caso meramente creamos un !ot"n con un te(to, que al ser pulsado imprime un mensaje en plantalla.

$1. CLASE GUI ( VIII)


Drag;indo.: static function Drag?indo) (!osition : 7ect) : void ?rea una ventana que puede arrastrarse. 2i llamamos a esta funci"n dentro del c"digo de la ventana, automticamente sta podr arrastrarse. /e hemos de pasar a la funci"n un parmetro que indica la parte de la ventana que puede ser arrastrada, dando un rectngulo que recorta la ventana original. #ara constatar lo que estoy diciendo, s"lo tenis que aadir esta lnea a la funci"n ?rea*i>entana del ejemplo anterior+ F%0. rag_indo4 -&ect -E,E, 5EE, 6E..C

#ensad que E,E viene referido a la ventana emergente, no a las coordenadas generales.

static function Drag?indo) () : void 1sta funci"n tiene un segundo prototipo que no requiere parmetros. 2i queremos que nuestra ventana pueda ser arrastrada desde cualquier parte del !ac8ground de la misma, es preferi!le utili'ar esta forma de la funci"n y colocarla al final de las funciones de la ventana. As, si modificamos esta parte del script+ function ?rea*i>entana -4indo40 + int. O if -F%0.Button -&ect -5E,6E,5EE,6E., <)ola mundo<.. print -<&eci! un clic8<.C F%0. rag_indo4 -.C P

podremos arrastrar nuestra ventana emergente desde cualquier punto de sta.

Bring;indo.ToFront: static function =ring?indo)ToFront ()indo)ID : int) : void

:rae una ventana determinada al frente del resto de ventanas flotantes. :iene como 3nico parmetro la 0 de la ventana que queremos poner en primer plano.

Bring;indo.ToBac5: static function =ring?indo)To=ac9 ()indo)ID : int) : void ?oloca una ventana determinada al fondo de las ventanas flotantes.

Foc+s;indo.: static function Focus?indo) ()indo)ID : int) : void

)ace que una ventana se convierta en la ventana activa. 2e le pasa como parmetro la 0 de dicha ventana.

UnFoc+s;indo.: static function :nfocus?indo) () : void

Guita el foco de todas las ventanas.

$2. CLASE GUILAYOUT (I)

1sta clase es la interfa' para la gui de %nity con distri!uci"n automtica. *e e(plico+ )ay dos maneras que podemos usar para organi'ar y distri!uir nuestras interfaces grficas de usuario+ fija y automtica. )asta ahora hemos tra!ajado con la clase F%0, que es la forma fija de distri!uci"n. 1sto entraa que cada ve' que se crea un nuevo elemento o control, se le u!ica en un punto concreto -casi siempre a travs de un &ect.. 1n cam!io, con la forma automtica de distri!uci"n -que es la que permite la clase F%0/ayout. esto no es necesario. 2e pueden usar am!os modos en la misma funci"n @nF%0-.. 1l modo fijo de distri!uci"n se suele usar cuando tenemos una interfa' prediseada con la que tra!ajamos. 1l modo automtico en cam!io se suele usar cuando no sa!emos cuntos elementos aca!aremos necesitando, o no queremos preocuparnos de colocar a mano cada control. )ay dos diferencias a tener en cuenta cuando usamos distri!uci"n automtica+ 5.$ )emos de usar F%0/ayout en lugar de F%0. 6.$ #ara la distri!uci"n automtica no se usa la funci"n &ect-..

FUNCIONES DE CLASE: La"el: static function -abel (image : Te/ture !arams o!tions : G:I-a%outO!tion+,) : void static function -abel (te/t : String !arams o!tions : G:I-a%outO!tion+,) : void static function -abel (content : G:I8ontent !arams o!tions : G:I-a%outO!tion+,) : void static function -abel (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function -abel (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function -abel (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void

)ace una etiqueta de distri!uci"n automtico. /as etiquetas no proveen interaci"n con el usuario, no capturan clic8s de rat"n y son siempre renderi'adas en estilo normal. 2i quieres tener un control que responda visualmente a las entradas de usuario usa un !o( control. :odos los parmetros menos uno son idnticos a los de la funci"n hom"nima de la clase F%0, as que a ellos me remito. #ero quiero detenerme en ese parmetro distinto, que de hecho es el que marca la diferencia entre la distri!uci"n fija -mediante &ect-. y la automtica. *e estoy refiriendo al parmetro params option, que es de tipo F%0/ayout@ption. F%0/ayout@ption es una clase internamente usada por %nity para pasar diferentes opciones de distri!uci"n en las funciones de la clase F%0/ayout. 9o se usa directamente, sino a travs de funciones de tipo F%0/ayout, como por ejemplo+ F%0/ayout._idth, F%0/ayout.)eight, F%0/ayout.*in_idth, F%0/ayout.*a(_idth, F%0/ayout.*in)eight, F%0/ayout.*a()eight, F%0/ayout.1(pand_idth y F%0/ayout.1(pand)eight. *s adelante en esta clase estudiaremos dichas funciones.

Bo): static function =o/ (image : Te/ture !arams o!tions : G:I-a%outO!tion+,) : void static function =o/ (te/t : String !arams o!tions : G:I-a%outO!tion+,) : void static function =o/ (content : G:I8ontent !arams o!tions : G:I-a%outO!tion+,) : void static function =o/ (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =o/ (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =o/ (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void crea una caja de distri!uci"n automtica. 2i queremos crear una caja con alg3n contenido dentro, hemos de usar el parmetro de estilo de uno de los su!grupos de funciones -Begin)ori'ontal, Begin>ertical, etc.....

B+tton: static function =utton (image : Te/ture !arams o!tions : G:I-a%outO!tion+,) : boolean static function =utton (te/t : String !arams o!tions : G:I-a%outO!tion+,) : boolean static function =utton (content : G:I8ontent !arams o!tions : G:I-a%outO!tion+,) : boolean static function =utton (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean static function =utton (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean static function =utton (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean

?rea un !ot"n con distri!uci"n automtica qevuelve true cuando el usuario lo presiona.

Re!eatB+tton: static function 7e!eat=utton (image : Te/ture !arams o!tions : G:I-a%outO!tion+,) : boolean static function 7e!eat=utton (te/t : String !arams o!tions : G:I-a%outO!tion+,) : boolean static function 7e!eat=utton (content : G:I8ontent !arams o!tions : G:I-a%outO!tion+,) : boolean static function 7e!eat=utton (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean static function 7e!eat=utton (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean static function 7e!eat=utton (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean

?rea un !ot"n que devuelve true tanto tiempo como el usuario lo mantiene pulsado.

Te)tField:

static function Te/tField (te/t : String static function Te/tField (te/t : String static function Te/tField (te/t : String static function Te/tField (te/t : String

!arams o!tions : G:I-a%outO!tion+,) : String ma/-ength : int !arams o!tions : G:I-a%outO!tion+,) : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : String ma/-ength : int st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : String

?rea un campo de te(to de una linea donde el usuario puede editar un string.

/ass.ordField:

static function 5ass)ordField (!ass)ord : String static function 5ass)ordField (!ass)ord : String : String static function 5ass)ordField (!ass)ord : String : String static function 5ass)ordField (!ass)ord : String G:I-a%outO!tion+,) : String

mas98har : char !arams o!tions : G:I-a%outO!tion+,) : String mas98har : char ma/-ength : int !arams o!tions : G:I-a%outO!tion+,) mas98har : char st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) mas98har : char ma/-ength : int st%le : G:ISt%le !arams o!tions :

?rea un campo de te(to donde el usuario puede entrar una contrasea. evuelve la contrasea editada.

Te)tArea: static function Te/t*rea (te/t : String static function Te/t*rea (te/t : String static function Te/t*rea (te/t : String static function Te/t*rea (te/t : String !arams o!tions : G:I-a%outO!tion+,) : String ma/-ength : int !arams o!tions : G:I-a%outO!tion+,) : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : String ma/-ength : int st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : String

?rea un campo de te(to multilnea donde el user puede editar un string, y devuelve dicho string

$3. CLASE GUILAYOUT (II)

Toggle: static function Toggle (value : boolean static function Toggle (value : boolean static function Toggle (value : boolean static function Toggle (value : boolean static function Toggle (value : boolean static function Toggle (value : boolean boolean image : Te/ture !arams o!tions : G:I-a%outO!tion+,) : boolean te/t : String !arams o!tions : G:I-a%outO!tion+,) : boolean content : G:I8ontent !arams o!tions : G:I-a%outO!tion+,) : boolean image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : boolean content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) :

?rea un !ot"n que alterna on;off. evuelve un !ooleano que indica el estado de dicho !ot"n

Tool"ar: static function Toolbar (selected : int static function Toolbar (selected : int static function Toolbar (selected : int static function Toolbar (selected : int static function Toolbar (selected : int images : Te/ture+, !arams o!tions : G:I-a%outO!tion+,) : int content : G:I8ontent+, !arams o!tions : G:I-a%outO!tion+,) : int te/ts : string+, st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : int images : Te/ture+, st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : int contents : G:I8ontent+, st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : int

?rea un tool!ar -!arra de herramientas.. evuelve un int que contiene el ndice del !ot"n seleccionado.

SelectionGrid: static function SelectionGrid (selected : int static function SelectionGrid (selected : int static function SelectionGrid (selected : int int static function SelectionGrid (selected : int G:I-a%outO!tion+,) : int static function SelectionGrid (selected : int G:I-a%outO!tion+,) : int static function SelectionGrid (selected : int G:I-a%outO!tion+,) : int te/ts : string+, /8ount : int !arams o!tions : G:I-a%outO!tion+,) : int images : Te/ture+, /8ount : int !arams o!tions : G:I-a%outO!tion+,) : int content : G:I8ontent+, /8ount : int !arams o!tions : G:I-a%outO!tion+,) : te/ts : string+, /8ount : int st%le : G:ISt%le !arams o!tions : images : Te/ture+, /8ount : int st%le : G:ISt%le !arams o!tions : contents : G:I8ontent+, /8ount : int st%le : G:ISt%le !arams o!tions :

?rea una cuadrcula de selecci"n, devolviendo el int con el ndice del !ot"n seleccionado.

:ori*ontalSlider: static function Hori0ontalSlider (value : float left"alue : float right"alue : float !arams o!tions : G:I-a%outO!tion+,) : float static function Hori0ontalSlider (value : float left"alue : float right"alue : float slider : G:ISt%le thumb : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : float ?rea una !arra de despla'amiento hori'ontal que el usuario puede arrastrar desde un mnimo hasta un m(imo. evuelve un float con el valor que ha sido escogido por el usuario.

VerticalSlider: static function "erticalSlider (value : float left"alue : float right"alue : float !arams o!tions : G:I-a%outO!tion+,) : float static function "erticalSlider (value : float left"alue : float right"alue : float slider : G:ISt%le thumb : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : float ?rea una !arra de despla'amiento vertical que el usuario puede arrastrar desde un mnimo hasta un m(imo.

:ori*ontalScroll"ar: static function Hori0ontalScrollbar (value : float si0e : float left"alue : float right"alue : float !arams o!tions : G:I-a%outO!tion+,) : float static function Hori0ontalScrollbar (value : float si0e : float left"alue : float right"alue : float st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : float ?rea un scroll!ar hori'ontal. evuelve el valor modificado en float, que puede ser cam!iado por el usuario arrastrando el scroll!ar o haciendo clic8 en las flechas al final.

VerticalScroll"ar: static function "erticalScrollbar (value : float si0e : float to!"alue : float bottom"alue : float !arams o!tions : G:I-a%outO!tion+,) : float static function "erticalScrollbar (value : float si0e : float to!"alue : float bottom"alue : float st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : float ?rea un scroll!ar vertical.

$4. CLASE GUILAYOUT (III)

S!ace: static function S!ace (!i/els : float) : void

0nserta un espacio en el actual grupo de distri!uci"n. /a direcci"n de dicho espacio depender del la direcci"n del grupo de distri!uci"n en el que estemos tra!ajando. 2i por ejemplo se trata de un grupo vertical, el espacio ser vertical. @!servemos la diferencia con dos ejemplos+ function @nF%0 -. O F%0/ayout.Button -<#rimer !ot"n<.C F%0/ayout.2pace -6E.C F%0/ayout.Button -<2egundo !ot"n<.C P

2i ejecutamos este primer script, o!servaremos dos !otones situados uno encima del otro, con un espacio -vertical. entre am!os de 6E p(eles. 1n cam!io, si estuviramos tra!ajando con un grupo de distri!uci"n hori'ontal... function @nF%0 -. O F%0/ayout.Begin)ori'ontal-.C F%0/ayout.Button -<#rimer !ot"n<.C F%0/ayout.2pace -6E.C F%0/ayout.Button -<2egundo !ot"n<.C F%0/ayout.1nd)ori'ontal-.C

... nos encontraramos con un !ot"n al lado del otro separados por un espacio -hori'ontal. de 6E p(eles. -1n !reve estudiaremos las funciones Begin)ori'ontal y 1nd)ori'ontal, aunque supongo que se intuye su cometido.

Fle)i"leS!ace: static function Fle/ibleS!ace () : void

0nserta un elemento de espacio fle(i!le. 1sta funci"n utili'a cualquier espacio que so!ra en un diseo.

Begin:ori*ontal: static function =eginHori0ontal (!arams o!tions : G:I-a%outO!tion+,) : void static function =eginHori0ontal (st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =eginHori0ontal (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =eginHori0ontal (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =eginHori0ontal (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void 1mpie'a un grupo de controles hori'ontal. :odos los controles dentro de este elemento sern colocados hori'ontalmente uno junto a otro. 1l grupo de!e cerrarse con una llamada a 1nd)ori'ontal. End:ori*ontal: static function 6ndHori0ontal () : void

?ierra el grupo a!ierto por Begin)ori'ontal.

BeginVertical: static function =egin"ertical (!arams o!tions : G:I-a%outO!tion+,) : void static function =egin"ertical (st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =egin"ertical (te/t : String st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =egin"ertical (image : Te/ture st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void static function =egin"ertical (content : G:I8ontent st%le : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : void 1mpie'a un grupo de controles vertical. :odos los controles dentro de este elemento sern situados verticalmente uno de!ajo del otro. 1l grupo de!e cerrarse con 1nd>ertical

EndVertical: static function 6nd"ertical () : void

?ierra un grupo iniciado por Begin>ertical.

BeginArea:

static function =egin*rea (screen7ect : 7ect) : void static function =egin*rea (screen7ect : 7ect te/t : String) : void static function =egin*rea (screen7ect : 7ect image : Te/ture) : void

static function =egin*rea (screen7ect : 7ect static function =egin*rea (screen7ect : 7ect static function =egin*rea (screen7ect : 7ect static function =egin*rea (screen7ect : 7ect static function =egin*rea (screen7ect : 7ect

content : G:I8ontent) : void st%le : G:ISt%le) : void te/t : String st%le : G:ISt%le) : void image : Te/ture st%le : G:ISt%le) : void content : G:I8ontent st%le : G:ISt%le) : void

?omien'a un !loque F%0/ayout de controles F%0 en un determinado rea de la pantalla. #or defecto, cualquier control F%0 hecho usando F%0/ayout es situado en la parte superior i'quierda de la pantalla. 2i queremos colocar una serie de controles en una 'ona ar!itraria, hemos de usar esta funci"n para definir un nuevo area. por ejemplo+ function @nF%0 -. O F%0/ayout.BeginArea -&ect -5E,5E,5EE,5EE..C F%0/ayout.Button -<%n !ot"n<.C F%0/ayout.Button -<@tro !ot"n<.C F%0/ayout.1ndArea -.C P

Aqu iniciamos un rea de controles u!icada en las coordenadas 5E,5E y con unas dimensiones de 5EE I 5EE.

EndArea: static function 6nd*rea () : void

?ierra un rea de controles a!ierto con BeginArea.

BeginScrollVie.: static function =eginScroll"ie) (scroll5osition : "ector1 !arams o!tions : G:I-a%outO!tion+,) : "ector1 static function =eginScroll"ie) (scroll5osition : "ector1 al)a%sSho)Hori0ontal : boolean al)a%sSho)"ertical : boolean !arams o!tions : G:I-a%outO!tion+,) : "ector1 static function =eginScroll"ie) (scroll5osition : "ector1 hori0ontalScrollbar : G:ISt%le verticalScrollbar : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : "ector1 static function =eginScroll"ie) (scroll5osition : "ector1 st%le : G:ISt%le) : "ector1 static function =eginScroll"ie) (scroll5osition : "ector1 al)a%sSho)Hori0ontal : boolean al)a%sSho)"ertical : boolean hori0ontalScrollbar : G:ISt%le verticalScrollbar : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : "ector1 static function =eginScroll"ie) (scroll5osition : "ector1 al)a%sSho)Hori0ontal : boolean al)a%sSho)"ertical : boolean hori0ontalScrollbar : G:ISt%le verticalScrollbar : G:ISt%le bac9ground : G:ISt%le !arams o!tions : G:I-a%outO!tion+,) : "ector1 ?omien'a un scrollvie4 -o vista de despla'amiento. automticamente distri!udo. 1ste puede tomar cualquier contenido que le metas dentro y lo muestra normalmente -sin que se vea el scroll.. 2i no ca!e el contenido, aparece la !arra. %na llamada a esta funci"n de!e siempre aca!ar con una llamada a 1nd2croll>ie4. 1sta funci"n devuelve un >ector6 con la posici"n del scroll modificada. ?uenta con los siguientes parmetros+ scroll#osition+ /a posici"n de uso de la pantalla. al4ay2ho4)ori'ontal+ #armetro opcional para ensear siempre el scroll!ar hori'ontal. 2i est en falso o no se aporta, s"lo se mostrar el scroll!ar cuando el contenido dentro del scrollvie4 sea ms ancho que ste. al4ay2ho4>ertical+ /o mismo que el anterior para el scroll!ar vertical. hori'ontal2croll!ar+ F%02tyle opcional a usar para el scroll!ar hori'ontal. 2i no se indica, se usar el estilo de hori'ontal2croll!ar del F%028in

vertical2croll!ar

que se est usando. /o mismo pra el scroll!ar vertical.

EndScrollVie.: static function 6ndScroll"ie) () : void

Minali'a un scroll vie4 empe'ado con una llamada a Begin2croll>ie4.

$5. CLASE GUILAYOUT ( IV)

;indo.: static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int static function ?indo) (id : int 7ect static function ?indo) (id : int : 7ect

screen7ect : 7ect screen7ect : 7ect screen7ect : 7ect screen7ect : 7ect screen7ect : 7ect

func : G:I(?indo)Function func : G:I(?indo)Function func : G:I(?indo)Function func : G:I(?indo)Function func : G:I(?indo)Function

te/t : String : ) : 7ect image : Te/ture : ) : 7ect content : G:I8ontent : ) : 7ect te/t : String st%le : G:ISt%le : ) : 7ect image : Te/ture st%le : G:ISt%le : ) :

screen7ect : 7ect func : G:I(?indo)Function content : G:I8ontent st%le : G:ISt%le : )

?rea una ventana emergente que distri!uye su contenido automticamente. /as ventanas flotan so!re los controles F%0 normales y pueden opcionalmente ser arrastradas por el usuario final. A diferencia de otros controles, necesitas pasarles una funci"n separada a los controles F%0 para ponerlos dentro de la ventana. evuelve un rect, que es el rectngulo en el que est la ventana y que puede tener una posici"n y tamao diferentes que aqulla.

;idth: static function ?idth ()idth : float) : G:I-a%outO!tion @pci"n pasada a un control para darle una anchura a!soluta. function @nF%0-. O F%0/ayout.Button-<Bot"n con una anchura fija<, F%0/ayout._idth-7EE..C P

-in;idth: static function 3in?idth (min?idth : float) : G:I-a%outO!tion

$!. CLASE TE'TURE @pci"n pasada a un control para especificar una anchura mnima.
-a);idth: static function 3a/?idth (ma/?idth : float) : G:I-a%outO!tion

@pci"n pasada a un control para especificar una anchura m(ima.

:eight: static function Height (height : float) : G:I-a%outO!tion

@pci"n pasada a un control para darle una altura a!soluta.

-in:eight: static function 3inHeight (minHeight : float) : G:I-a%outO!tion

@pci"n pasada a un control para especificar una altura mnima. ?lase !ase para el manejo de te(tures. ?ontiene funcionalidades que son comuntes tanto en la clase :e(ture6 como en la clase &ender:e(ture. -a):eight: VARIABLES: static function 3a/Height (ma/Height : float) : G:I-a%outO!tion .idth: @pci"n pasada a un control para especificar una altura m(ima. >aria!le de s"lo lectura que indica la anchura de la te(tura en p(eles. E)!and;idth: height: static function 6/!and?idth (e/!and : boolean) : G:I-a%outO!tion var height : int @pci"n pasada a un control para ha!ilitar o desha!ilitar la e(pansi"n hori'ontal. >aria!le de s"lo lectura que indica la alturade la te(tura en p(eles. E)!and:eight: (ilter-ode: tatic function 6/!andHeight (e/!and : boolean) : G:I-a%outO!tion var filter3ode : Filter3ode

*odo de filtradoade te(tura. /a ha!ilitar varia!le o Milter*ode es la una enumeraci"n que permite estos valores+ @pci"n pasada unla control para desha!ilitar e(pansi"n vertical. #oint+ Miltrado de puntos, los p(eles de la te(tura se convierten en !loques de cerca. Bilinear+ Miltrado !ilinear, las muestras de la te(tura se promedian. :rilinear+ Miltrado trilinear, los p(eles de la te(tura se promedian y tam!in son me'clados entre los niveles del mipmap.

anisoLe2el: var aniso-evel : int

9ivel de filtro anisotr"pico de la te(tura -anisotropa recordemos que implica que algunas caractersticas del o!jeto, como la lu', dependen del lugar desde donde ste es o!servado.. 1l filtrado anisotr"pico hace que las te(turas lu'can mejor cuando son vistas en un ngulo !ajo, pero a cam!io de un importante coste de rendimiento en la tarjeta grfica. %sualmente se usa esto en te(turas de suelo, tierra o carreteras para que se vean mejor. 1l rango de valor de esta varia!le va de 5 a [, donde 5 equivale no filtro aplicado y [ implica filtro totalmente aplicado. A medida que el valor es ms grande, la te(tura es ms clara en los ngulos !ajos.

.ra!-ode: var )ra!3ode : Te/ture?ra!3ode

*odo de envoltura de la te(tura. 1sta puede esta!lecerse en clamp -que podemos traducir por fija o pin'ada. o en repear, que <a'uleja< la te(tura en un n3mero de repeticiones. renderer.material.main:e(ture.4rap*ode D :e(ture_rap*ode.?lampC

:e(ture_rap*ode como decimos es una enum con estos valores+ &epeat+ A'uleja la te(tura, creando un patr"n de repetici"n. ?lamp+ 2ujeta la te(tura al 3ltimo pi(el en el !orde de sta.

$". CLASE TE'TURE2D (I)

1s esta una clase para manejo de te(turas. 2e suele usar para crear te(turas <al vuelo< -en tiempo de ejecuci"n. o para modificar los assets de te(turas e(istentes.

VARIABLES: mi!ma!Co+nt: var mi!ma!8ount : int

>aria!le de s"lo lectura que indica cuntos niveles de mipmap hay en la te(tura. 1l valor retornado incluye el nivel !ase tam!in, ra'"n por la cual esta varia!le siempre vale 5 o ms. 1l conteo de mipmaps se usa en caso de que utilicemos las funciones Fet#i(els o 2et#i(els para o!tener o modificar respecti!amente los diferentes niveles de mipmal. #or ejemplo, podemos querer cam!iar una te(tura de tal manera que cada nivel de mipmap se tinte de un color diferente, y as en el juego veramos cuantos niveles de mipmap son en realidad visi!les.

te)t+reFormat: var format : Te/tureFormat 1l formato de los datos de los p(eles en la te(tura -s"lo lectura..

FUNCIONES: Te)t+re9D: static function Te/ture1D ()idth : int height : int) : Te/ture1D

?rea una nueva te(tura vaca. 1sta tendr un tamao dado por anchura y altura, con un formato de te(tura A&F>76 y con mipmaps. 9ormalmente querremos poner los colores de la te(tura despus de crearla, usando las funciones 2et#i(el, 2et#i(els y

Apply. function 2tart -. O var nueva:e(tura D ne4 :e(ture6 -56Y, 56Y.C renderer.material.main:e(ture D nueva:e(turaC P

1ste sera el ejemplo !sico. ?reamos una nueva te(tura de dimensiones 56Y I 56Y y se la asignamos como principal te(tura al gameo!ject al que le vinculemos el script. 1n este caso eliminamos *i#rimer2cript del gameo!ject #orta2cripts y se lo vinculamos a la 1sfera. @!servaremos, si la tenemos seleccionada al darle al play, que sta importa a vuelo la nueva te(tura, que por defecto es de color negro.

static function Te/ture1D ()idth : int height : int format : Te/tureFormat mi!ma! : boolean) : Te/ture1D 1ste segundo prototipo se diferencia del primero en que se le pasa a la funci"n como parmetro un determinado formato para la te(tura y a la ve' se indica si se crea con o sin mipmaps.

Set/i)el: function Set5i/el (/ : int % : int color : 8olor) : void

Munci"n que nos permite indicar el color de los p(eles en las coordenadas que le pasamos. 9o o!stante, para actuali'ar en realidad el color de dichos p(eles en la tarjeta grfica del usuario, de!eremos acto seguido llamar a la funci"n Apply. ado que esta manera de actuali'ar las te(turas consume !astantes recursos, as que sera desea!le que cam!iramos tantos p(eles como fuera posi!le entre cada llamada a la funci"n Apply. 2i tenemos pensado regenerar constantemente te(turas en tiempo de ejecuci"n, puede ser ms rpido generar un array de colores de p(eles y asignarlos todos a la ve' con la funci"n 2et#i(els. 1sta funci"n, por 3ltimo, tra!aja s"lo con los formatos A&FB76, &FB6X y AlphaY. #ara el resto de formatos 2et#i(el es ignorada. >amos a verlo con un ejemplo. #reviamente sera interesante colocar la cmara en las siguientes coordenadas+ position-E,5.K,$T., rotation-5E,E,E.. As tendremos una mejor visi"n de lo que le acontecer a la esfera en el pr"(imo script. 1ditamos *i#rimer2cript ahora+ function 2tart -. O var nueva:e(tura D ne4 :e(ture6 -56Y, 56Y.C renderer.material.main:e(ture D nueva:e(turaC var mitad) + int D nueva:e(tura.4idth;6C var mitad> + int D nueva:e(tura.height;6C var un?olor + ?olor D ?olor.greenC for -var ( + int D EC ( W mitad)C (BB.O for -var y + int D EC y W mitad>C yBB.O nueva:e(tura.2et#i(el-(, y, un?olor.C P P nueva:e(tura.Apply-.C P

>amos por partes. ?reamos primero una nueva te(tura y se la pasamos al gameo!ject al que tenemos vinculado el script. Almacenamos acto seguido en sendos integers la mitad de la altura y la anchura de la nueva te(tura. e esta manera, en un !ucle for podemos asignar un determinado color a esa mitad. &ecordemos en todo caso dejar la funci"n Apply fuera del !ucle, a los efectos de no so!recargar el pc.

Get/i)el: function Get5i/el (/ : int % : int) : 8olor

evuelve el color del p(el que se halla en las coordenadas dadas. 2i stas estn fuera de los !ordes -ms grandes de la anchura;altura o ms pequeas que cero. sern fijadas o repetidas en !ase al 4rapmode de la te(tura 2i quieres leer un !loque amplio de p(eles de una te(tura, ser ms rpido usar Fet#i(els, la cual devuelve un !loque entero de colores de p(eles. /a te(tura de!e tener activa la varia!le 0s &eada!le en import settings, ya que de lo contrario fallar la funci"n.

$#. CLASE TE'TURE2D ( II)

Get/i)elBilinear: function Get5i/el=ilinear (u : float v : float) : 8olor

evuelve el color de los p(eles filtrado en coordenadas normali'adas -u, v.. dichas coordenadas normali'adas u y v van de E.E a 5.E, al igual que las coordenadas %> en mallas.

Set/i)els: function Set5i/els (colors : 8olor+, mi!level : int & ') : void

1sta!lece un !loque de colores de p(eles. 1sta funci"n toma un array de colores y cam!ia los colores de los p(eles del nivel mip entero de la te(tura. #recisa una posterior llamada a Aply para que los cam!ios se actualicen en la tarjeta grfica. 1l array de colores es un array 6d plano, donde los p(eles se distri!uyen de i'quierda a derecha y de a!ajo arri!a. 1l tamao del array de!e ser al menos la anchura por la altura o el level de mapeo mip usado. %sar 2et#i(els puede ser ms rpido que llamar a 2et#i(el repetidamente, especialmente para te(turas grandes. Adems, 2et#i(els puede acceder a niveles de mipmap individuales. function Set5i/els (/ : int % : int bloc9?idth : int bloc9Height : int colors : 8olor+, mi!level : int & ') : void 1sta versi"n de la funci"n no modifica el nivel mip entero, sino s"lo la parte comprendida entre los parmetros !loc8_idth y !loc8)eight empe'ando desde (,y. 1l array de colores de!e tener un tamao de !loc8_idthZ!loc8)eight, y el !loque modificado de!e ca!er dentro del nivel mip usado.

Set/i)els19: function Set5i/els#1 (colors : 8olor#1+, mi!level : int & ') : void

1sta!lece un !loque de colores de p(eles. 1sta funci"n toma un array de tipo ?olor76 y cam!ia los colores de los p(eles del nivel de mip entero de la te(tura. 9o nos olvidemos de llamar despus a Apply.

LoadImage: function -oadImage (data : b%te+,) : boolean

?arga una imagen de tipo =#F o #9F desde un array de !ytes.

Get/i)els: function Get5i/els (mi!level : int & ') : 8olor+, 1sta funci"n devuelve un array de colores de p(eles del nivel de mip entero de la te(tura. function Get5i/els (/ : int % : int bloc9?idth : int bloc9Height : int mi!level : int & ') : 8olor+, 1ste segundo prototipo retorna s"lo el mip de la regi"n !loc8_idth por !loc8)eight empe'ando por (,y.

Get/i)els19: function Get5i/els#1 (mi!level : int & ') : 8olor#1+,

@!tiene un !loque de colores de p(eles en formato ?olor76.

A!!l%: function *!!l% (u!date3i!ma!s : boolean & true ma9e4o-onger7eadable : boolean & false) : void

Aplica en la prctica todos los cam!ios previamente efectuados con las funciones 2et#i(el y 2et#i(els. 2i el parmetro update*ipmaps es true, los niveles de mipmap son recalculados tam!in, usando el nivel !ase como fuente. 9ormalmente tendremos este parmetro en true salvo cuando queramos modificar los niveles mip nosotros mismos usando 2et#i(els. 2i el parmetro ma8e9o/onger&eada!le es true, la te(tura se marcar como no legi!le y la memoria ser li!erada en la siguiente actuali'aci"n. #or defecto ma8e9o/onger&eada!le se pone en false. 1sta funci"n, como ya dijimos previamente, consume muchos recurso, as que es desea!le hacer el mayor n3mero de cam!ios precisos entre cada llamada a la misma.

Resi*e: function 7esi0e ()idth : int height : int format : Te/tureFormat has3i!3a! : boolean) : boolean

&edimensiona la te(tura, y en concreto modifica la anchura, altura, formato y en ocasiones crea mipmaps. 1sta funci"n es muy similar al constructor, salvo que esta tra!aja con una te(tura que ya e(iste. precisa llamar a Apply para que los cam!ios tengan efecto en la tarjeta grfica.

function 7esi0e ()idth : int height : int) : boolean 1sta variante cam!ia meramente la altura y o la anchura de la te(tura.

Read/i)els: function 7ead5i/els (source : 7ect destC : int destD : int recalculate3i!3a!s : boolean & true) : void

/ee p(eles de pantalla dentro de los datos de la te(tura guardada. ?opia un rea de p(eles rectangular de la &ender:e(ture en uso o !ien la vista -especificada por el parmetro source. dentro de la posici"n definida por destI y dest,. Am!as coordenadas usan el espacio de p(eles, donde -E,E. is a!ajo a la i'quierda. 2i recalculate*ip*aps est esta!lecido en true, los mip maps de la te(tura sern tam!ien actuali'ados. 1n caso contrario de!eremos llamar a Apply para recalcularlos. 1sta funci"n tra!aja s"lo con los formatos de te(tura A&FB76 y &FB6X.

EncodeTo/NG:

function 6ncodeTo54G () : b%te+,

?odifica esta te(tura en formato #9F. 1l array de !ytes que devuelve es el archivo #9F. #uedes escri!irlo entonces en disco o enviarlo a travs de la rec, por ejemplo. 1sta funci"n solo tra!aja con los formatos de te(tura A&FB76 y &FB6X. /a te(tura tam!in de!e tener el flag 0s &eada!le marcado en import settings.

$$. CLASE INPUT (I)

1s la interfa' que controla todo el sistema de entradas -inputs. de %nity. 1sta clase se usa, por ejemplo, para leer la configuraci"n de ejes en el input *anager. #ara leer un eje usaramos 0nput.FetA(is con uno de los ejes por defecto+ ])ori'ontal^ y ]>ertical^ estn configurados para joystic8, as como A,_,2, , y las teclas de flecha. ]*ouseI^ y ]*ouse ,^ estn configurados para el movimiento del rat"n. #or su parte ]Mire5<, <Mire6< y <Mire7< estn configurados para ?trl, Alt y tres !otones de rat"n o joystic8. #ueden aadirse nuevos ejes de entrada en el 0nput *anager. 2i hemos se usar inputs para cualquier tipo de comportamiento que entrae movimiento, es aconseja!le usar 0nput.FetA(is. 1sto nos dar una entrada ms suave y configura!le que puede servir para teclado, joystic8 o mouse. 1n cam!io es mejor usar 0nput.FetButton para acciones como eventos, mejor que para movimientos. /as llamadas a inputs se de!en hacer dentro de la funci"n update.

VARIABLES DE CLASE: mo+se/osition: static var mouse5osition : "ector#

>aria!le de s"lo lectura que indica la posici"n actual del rat"n en coordenadas de p(eles, donde la esquina inferior i'quierda de la pantalla o ventana est en -E, E. y la superior derecha en -2creen.4idth, 2creen.height.. #odemos pro!arlo con un ejemplo sencillo, para el cual eliminamos el script vinculado a la esfera, y reeditamos *i#rimer2cript como sigue+ function %pdate-.O var apunten + >ector7 D 0nput.mouse#ositionC e!ug./og-apunten.C P

2alvamos y arrastramos hasta #orta2cripts. *eramente se nos imprimir en pantalla la posici"n e(acta en p(eles de nuestro cursor. #odemos o!servar que la esquina inferior i'quierda se mueve en parmetros del E,E.

an%6e%:

static var an%<e% : boolean

Booleano de s"lo lectura que comprue!a si hay alguna tecla o !ot"n del rat"n apretada en ese momento. #odemos modificar nuestro script anterior para ilustrar esta varia!le+ function %pdate-.O if-0nput.anyaey.O e!ug./og-<2e ha pulsado una tecla o !ot"n<.C P P

9o tenemos ms que apretar cualquier tecla o !ot"n del rat"n para ver el mensaje impreso.

an%6e%Do.n: static var an%<e%Do)n : boolean

>aria!le de s"lo lectura que devuelve true el primer frame en que el usuario golpea cualquier tecla o !ot"n del rat"n. e!emos colocar esta varia!le dentro de la funci"n update, ya que el estado de la misma se resetea cada frame. 9o devolver true de nuevo hasta que el usuario li!ere todas las teclas;!otones y presione alguna tecla;!ot"n otra ve'. #ara entender grficamente la diferencia entre la varia!le anterior y la siguiente vamos a hacer una cosa+ volvemos a darle al play -sigue en vigor el ejemplo anterior. y hacemos un clic8 con un !ot"n del rat"n. Automticamente nos aparece el mensaje impreso !ajo la ventana del juego. )acemos un clic8 ahora so!re dicho mensaje, para que nos apare'ca el popup de la consola, tal como muestra la captura+

>ale. Ahora, sin retirar dicho popup, presionamos sin soltar el !ot"n del mouse so!re la ventana Fame. >emos que se imprime de manera continuada el mensaje -una por cada frame que mantenemos pulsado el !ot"n del rat"n.. , ahora sustituimos en el script la varia!le <anyaey< por <anyaey o4n<, y repetimos los pasos anteriorer. ?ompro!aremos que aunque mantengamos el !ot"n del rat"n presionado, el mensaje s"lo se imprime el primer frame que lo pulsamos, y no se vuelve a imprimir hasta que lo soltamos y lo volvemos a apretar.

in!+tString: static var in!utString : String

>aria!le de s"lo lectura que devuelve la entrada de teclado introducida este frame. /a misma s"lo puede contener caracteres A2?00 o un par de caracteres especiales que de!en ser manejados+ el carcter ]i!^ significa retroceso y ]in^ representa return o enter.

acceleration: static var acceleration : "ector#

%ltima medicion de aceleraci"n lineal de un dispositimo en espacio tridimensional. 2"lo lectura

100. CLASE INPUT (II)

accelerationE2ents: static var acceleration6vents : *cceleration6vent+, >aria!le de s"lo lectura que devuelve una lista de mediciones de aceleraci"n ocurridas durante el 3ltimo frame. ichas medidas son alojadas en varia!les temporales. ichas varia!les temporales son un array del tipo Acceleration1vent, que es una estructura con dos valores+ acceleration+ e tipo >ector7, es el valor de aceleraci"n. delta:ime+ e tipo float, el tiempo transcurrido desde la 3ltima medici"n de aceleraci"n.

accelerationE2entCo+nt: static var acceleration6vent8ount : int

93mero de mediciones de aceleraci"n ocurrida durante el 3ltimo frame.

eat6e%/ressOnTe)tFieldFoc+s: static var eat<e%5ressOnTe/tFieldFocus : boolean

#ropiedad que indica si las teclas impresas son comidas por la entrada de te(to si esta tiene el foco -por defecto true..

FUNCIONES DE CLASE: GetA)is: static function Get*/is (a/is4ame : String) : float

evuelve el valor del eje virtual identificado por a(is9ame. 1l valor estar en el rango $5...5 para entradas de teclado -tradicionalmente la flechas de despla'amiento. y joystic8. 2i el a(is es indicado por el movimiento del rat"n, ste ser multiplicado por el eje de sensi!ilidad y su rango ser distinto a $5h5. 1s una de las funciones con las que ms trope'aremos cuando programemos con %nity, as que merece la pena que nos detengamos para ilustrarla con alg3n ejemplo. 1l primer ejemplo lo hemos sacado del manual de referencia. #ara que funciones !ien -recordemos que tenemos en la

actualidad *i#rimer2cript vinculado a la esfera. es necesario que eliminemos el componente &igid!ody de la esfera. , acto seguido editamos nuestro script como sigue+ var velocidad + float D 6.EC var velocidad&otacion + float D XK.EC function %pdate -. O var translacion + float D 0nput.FetA(is -<>ertical<. Z velocidadC var rotacion + float D 0nput.FetA(is -<)ori'ontal<. Z velocidad&otacionC translacion ZD :ime.delta:imeC rotacion ZD :ime.delta:imeC transform.:ranslate -E, E, translacion.C transform.&otate -E, rotacion, E.C P

:ratemos de e(plicar lo que hemos hecho. A travs de 0nput.FetA(is recogemos las entradas de teclado provinentes de las flechas de despla'amiento verticales y hori'ontales. As, la flecha de despla'amiento hacia arri!a vale 5 y la de despla'amiento hacia a!ajo vale $5, y lo mismo hacia la derecha -5. y la i'quierda -$5.. ichos valores son multiplicados por la velocidad contenida en la varia!le <velocidad< en el caso del eje arri!a;a!ajo, y por la contenida en la varia!le <velocidad&otacion< para el eje derecha;i'quierda. Am!os valores son almacenados en varia!les de tipo >ector7 que luego $tras ser reconvertidos en velocidad por frame a velocidad por segundo$ se utili'an para participar en el movimiento del game o!ject tanto en el eje delante;detrs de translaci"n como en el eje , de rotaci"n. 1n suma, nos queda un script $muy !sico y torpe, eso s$ para manejar el despla'amiento y giro de nuestra esfera en !ase a las flechas de despla'amiento. #ro!moslo un rato. )emos dicho que 0nput.FetA(is tam!in acepta como entrada el provocado por el movimiento vertical y hori'ontal del rat"n, as que ilustrmoslo+ var velocidad)ori'ontal + float D 6E.EC var velocidad>ertical + float D 6E.EC function %pdate -. O var h + float D velocidad)ori'ontal Z 0nput.FetA(is -<*ouse I<.C var v + float D velocidad>ertical Z 0nput.FetA(is -<*ouse ,<.C transform.&otate -v, h, E.C P

1s un ejemplo sencillo. 2e almacena en sendas varia!les el fruto de multiplicar el valor de los ejes de despla'amiento hori'ontal y vertical del rat"n -que recordemos que no es $5,5. por el valor de velocidad que le hayamos dado a las varia!les e(puestas del inicio de script. 1n !ase a ello, nuestra esfera girar so!re su eje I e , en respuesta a los movimientos vertical y hori'ontal de nuestro rat"n.

GetA)isRa.: static function Get*/is7a) (a/is4ame : String) : float

evuelve el valor del eje virtual identificado por el parmetro a(is9ame sin ning3n filtro de suavi'ado aplicado. 1l valor estar en el rango de $5h5 para entrada de teclado y joystic8. ?omo a la entrada $al contrario de la funci"n anterior$ no se le aplica smooth -suavi'ado.,la entrada de teclado ser siempre o $5 o cero o 5. 1sta funci"n puede sernos 3til para el caso de que queramos hacer todo el proceso de suavi'ado de entrada nosotros mismos manualmente.

GetB+tton: static function Get=utton (button4ame : String) : boolean

evuelve true mientras el !ot"n virtual que le pasemos como parmetro en formato string est presionado. #odemos

pensar por ejemplo en un disparador automtico, que devolvera true mientras el !ot"n estuviera presionado. 1so s, as como esta funci"n es "ptima para acciones como disparar un arma, para cualquier tipo de movimiento es mejor usar FetA(is, que a ste le introduce valores de suavi'ado que en FetButton no hallaremos -ni podremos implementar manualmente, al contrario que en FetA(is&a4. %n ejemplo+ var proyectil + Fame@!jectC var frecuencia isparo + float D E.KC private var pro(imo isparo + float D E.EC function %pdate -. O if -0nput.FetButton -<Mire5<. ee :ime.time L pro(imo isparo. O pro(imo isparo D :ime.time B frecuencia isparoC var clon + Fame@!ject D 0nstantiate-proyectil, transform.positionB>ector7.for4ard, transform.rotation. as Fame@!jectC P P

2alvamos y arrastramos el cu!o a la varia!le e(puesta proyectil. #ulsamos play y o!servaremos que estamos clonando;disparando cu!os cada ve' que $dentro del lapso de tiempo permitido$ pulsamos el !ot"n i'quierdo del rat"n o la tecla ?trl situada a la i'quierda del teclado -que son por defecto los dos elementos que tenemos vinculados al evento Mire5. #or otro lado, si mantenemos pulsado de manera ininterrumpida !ien el !ot"n o !ien la tecla indicados, o!servaremos que disparamos un cu!o cada medio segundo. 1n s el script comprue!a si hemos pulsado la tecla o !ot"n que tengamos asignada a Mire5. 1n caso afirmativo pasa a compro!ar si ha transcurrido un lapso de tiempo superior al que le hemos fijado en frecuencia isparo -que para el primer disparo valdr cero.. 2i tam!in es true esta segunda condici"n se le aade medio segundo de espera al resto de disparos ms el tiempo transcurrido en hacerlo, el script nos permite clonar;disparar otro proyectil ms.

GetB+ttonDo.n: static function Get=uttonDo)n (button4ame : String) : boolean

evuelve true durante el frame en que el jugador aprieta el !ot"n virtual identificado como !utton9ame. e!emos llamar siempre a esta funci"n desde la funci"n %pdate, dado que el estado se resetea cada frame. 9o devolver true hasta que el usuario li!ere la tecla y la presione de nuevo, al igual que suceda con anyaey o4n.

GetB+ttonU!: static function Get=utton:! (button4ame : String) : boolean

evuelve true el primer frame en que el jugador li!era el !ot"n virtual identificado como !utton9ame. &ecordemos llamar esta funci"n desde %pdate ya que se resetea su estado cada frame. 9o devolver true hasta que se li!ere la tecla y se vuelva a presionar.

101. CLASE INPUT (III)

Get6e%: static function Get<e% (name : String) : boolean

evuelve true mientras el jugador aprieta la tecla identificada como name -pensemos de nuevo en un disparador automtico. #ara ver la lista de indentificadores de tecla podemos consultar 0nput *anager en el men3DL1ditDL#roject 2ettingsDL0nput. %n ejemplo sencillo+ function %pdate -. O if -0nput.Fetaey -<up<.. print -<)as presionado la flecha de despla'amiento superior<.C if -0nput.Fetaey -<do4n<.. print -<)as presionado la flecha de despla'amiento inferior<.C P

static function Get<e% (9e% : <e%8ode) : boolean

1n este segundo prototipo la funci"n devuelve true mientras el jugador presiona la tecla identificada por el parmetro de tipo aey?ode. As, el ejemplo anterior en esta segunda modalidad se quedara as+ function %pdate -. O if -0nput.Fetaey -aey?ode.%pArro4.. print -<)as presionado la flecha de despla'amiento superior<.C if -0nput.Fetaey -aey?ode. o4nArro4.. print -<)as presionado la flecha de despla'amiento inferior<.C P

#aso a relacionar todo el enum aey?ode+ 9one 9ot assigned -never is pressed. Bac8space :he !ac8space 8ey elete :he for4ard delete 8ey :a! :he ta! 8ey ?lear :he ?lear 8ey &eturn &eturn 8ey #ause #ause on #? machines

1scape 1scape 8ey 2pace 2pace 8ey aeypadE 9umeric 8eypad E aeypad5 9umeric 8eypad 5 aeypad6 9umeric 8eypad 6 aeypad7 9umeric 8eypad 7 aeypadX 9umeric 8eypad X aeypadK 9umeric 8eypad K aeypadT 9umeric 8eypad T aeypad` 9umeric 8eypad ` aeypadY 9umeric 8eypad Y aeypad[ 9umeric 8eypad [ aeypad#eriod 9umeric 8eypad b.b aeypad ivide 9umeric 8eypad b;b aeypad*ultiply 9umeric 8eypad bZb aeypad*inus 9umeric 8eypad b$b aeypad#lus 9umeric 8eypad bBb aeypad1nter 9umeric 8eypad enter aeypad1quals 9umeric 8eypad bDb %pArro4 %p arro4 8ey o4nArro4 o4n arro4 8ey &ightArro4 &ight arro4 8ey /eftArro4 /eft arro4 8ey 0nsert 0nsert 8ey 8ey )ome )ome 8ey 1nd 1nd 8ey #age%p #age up #age o4n #age do4n M5 M5 function 8ey M6 M6 function 8ey M7 M7 function 8ey MX MX function 8ey MK MK function 8ey MT MT function 8ey M` M` function 8ey MY MY function 8ey M[ M[ function 8ey M5E M5E function 8ey M55 M55 function 8ey M56 M56 function 8ey M57 M57 function 8ey M5X M5X function 8ey M5K M5K function 8ey AlphaE :he bEb 8ey on the top of the alphanumeric 8ey!oard. Alpha5 :he b5b 8ey on the top of the alphanumeric 8ey!oard. Alpha6 :he b6b 8ey on the top of the alphanumeric 8ey!oard. Alpha7 :he b7b 8ey on the top of the alphanumeric 8ey!oard. AlphaX :he bXb 8ey on the top of the alphanumeric 8ey!oard. AlphaK :he bKb 8ey on the top of the alphanumeric 8ey!oard. AlphaT :he bTb 8ey on the top of the alphanumeric 8ey!oard. Alpha` :he b`b 8ey on the top of the alphanumeric 8ey!oard. AlphaY :he bYb 8ey on the top of the alphanumeric 8ey!oard. Alpha[ :he b[b 8ey on the top of the alphanumeric 8ey!oard. 1(claim 1(claim 8ey ou!leGuote ou!le quote 8ey )ash )ash 8ey ollar ollar sign 8ey Ampersand Ampersand 8ey Guote Guote 8ey /eft#aren /eft #arent 8ey

&ight#aren &ight #arent 8ey Asteris8 Asteris8 8ey #lus #lus 8ey ?omma ?omma b,b 8ey *inus *inus b$b 8ey #eriod #eriod b.b 8ey 2lash 2lash b;b 8ey ?olon ?olon b,b 8ey 2emicolon 2emicolon bCb 8ey /ess /ess bWb 8ey 1quals 1quals bDb 8ey Freater Freater bLb 8ey Guestion Guestion mar8 bSb 8ey At At 8ey /eftBrac8et /eft !rac8et 8ey Bac8slash Bac8slash 8ey &ightBrac8et Bac8slash 8ey ?aret ?aret 8ey %nderscore %nderscore bNb 8ey Bac8Guote Bac8 quote 8ey A bab 8ey B b!b 8ey ? bcb 8ey bdb 8ey 1 beb 8ey M bfb 8ey F bgb 8ey ) bhb 8ey 0 bib 8ey = bjb 8ey a b8b 8ey / blb 8ey * bmb 8ey 9 bnb 8ey @ bob 8ey # bpb 8ey G bqb 8ey & brb 8ey 2 bsb 8ey : btb 8ey % bub 8ey > bvb 8ey _ b4b 8ey I b(b 8ey , byb 8ey J b'b 8ey 9umloc8 9umloc8 8ey ?aps/oc8 ?apsloc8 8ey 2croll/oc8 2croll loc8 8ey &ight2hift &ight shift 8ey /eft2hift /eft shift 8ey &ight?ontrol &ight ?ontrol 8ey /eft?ontrol /eft ?ontrol 8ey &ightAlt &ight Alt 8ey /eftAlt /eft Alt 8ey /eftApple /eft Apple 8ey /eft_indo4s /eft _indo4s 8ey &ightApple &ight Apple 8ey &ight_indo4s &ight _indo4s 8ey AltFr Alt Fr 8ey

)elp )elp 8ey #rint #rint 8ey 2ys&eq 2ys &eq 8ey Brea8 Brea8 8ey *enu *enu 8ey *ouseE Mirst -primary. mouse !utton *ouse5 2econd -secondary. mouse !utton *ouse6 :hird mouse !utton *ouse7 Mourth mouse !utton *ouseX Mifth mouse !utton *ouseK 2i(th mouse !utton *ouseT 2eventh mouse !utton =oystic8ButtonE Button E on any joystic8 =oystic8Button5 Button 5 on any joystic8 =oystic8Button6 Button 6 on any joystic8 =oystic8Button7 Button 7 on any joystic8 =oystic8ButtonX Button X on any joystic8 =oystic8ButtonK Button K on any joystic8 =oystic8ButtonT Button T on any joystic8 =oystic8Button` Button ` on any joystic8 =oystic8ButtonY Button Y on any joystic8 =oystic8Button[ Button [ on any joystic8 =oystic8Button5E Button 5E on any joystic8 =oystic8Button55 Button 55 on any joystic8 =oystic8Button56 Button 56 on any joystic8 =oystic8Button57 Button 57 on any joystic8 =oystic8Button5X Button 5X on any joystic8 =oystic8Button5K Button 5K on any joystic8 =oystic8Button5T Button 5T on any joystic8 =oystic8Button5` Button 5` on any joystic8 =oystic8Button5Y Button 5Y on any joystic8 =oystic8Button5[ Button 5[ on any joystic8 =oystic85ButtonE Button E on first joystic8 =oystic85Button5 Button 5 on first joystic8 =oystic85Button6 Button 6 on first joystic8 =oystic85Button7 Button 7 on first joystic8 =oystic85ButtonX Button X on first joystic8 =oystic85ButtonK Button K on first joystic8 =oystic85ButtonT Button T on first joystic8 =oystic85Button` Button ` on first joystic8 =oystic85ButtonY Button Y on first joystic8 =oystic85Button[ Button [ on first joystic8 =oystic85Button5E Button 5E on first joystic8 =oystic85Button55 Button 55 on first joystic8 =oystic85Button56 Button 56 on first joystic8 =oystic85Button57 Button 57 on first joystic8 =oystic85Button5X Button 5X on first joystic8 =oystic85Button5K Button 5K on first joystic8 =oystic85Button5T Button 5T on first joystic8 =oystic85Button5` Button 5` on first joystic8 =oystic85Button5Y Button 5Y on first joystic8 =oystic85Button5[ Button 5[ on first joystic8 =oystic86ButtonE Button E on second joystic8 =oystic86Button5 Button 5 on second joystic8 =oystic86Button6 Button 6 on second joystic8 =oystic86Button7 Button 7 on second joystic8 =oystic86ButtonX Button X on second joystic8 =oystic86ButtonK Button K on second joystic8 =oystic86ButtonT Button T on second joystic8 =oystic86Button` Button ` on second joystic8

=oystic86ButtonY Button Y on second joystic8 =oystic86Button[ Button [ on second joystic8 =oystic86Button5E Button 5E on second joystic8 =oystic86Button55 Button 55 on second joystic8 =oystic86Button56 Button 56 on second joystic8 =oystic86Button57 Button 57 on second joystic8 =oystic86Button5X Button 5X on second joystic8 =oystic86Button5K Button 5K on second joystic8 =oystic86Button5T Button 5T on second joystic8 =oystic86Button5` Button 5` on second joystic8 =oystic86Button5Y Button 5Y on second joystic8 =oystic86Button5[ Button 5[ on second joystic8 =oystic87ButtonE Button E on third joystic8 =oystic87Button5 Button 5 on third joystic8 =oystic87Button6 Button 6 on third joystic8 =oystic87Button7 Button 7 on third joystic8 =oystic87ButtonX Button X on third joystic8 =oystic87ButtonK Button K on third joystic8 =oystic87ButtonT Button T on third joystic8 =oystic87Button` Button ` on third joystic8 =oystic87ButtonY Button Y on third joystic8 =oystic87Button[ Button [ on third joystic8 =oystic87Button5E Button 5E on third joystic8 =oystic87Button55 Button 55 on third joystic8 =oystic87Button56 Button 56 on third joystic8 =oystic87Button57 Button 57 on third joystic8 =oystic87Button5X Button 5X on third joystic8 =oystic87Button5K Button 5K on third joystic8 =oystic87Button5T Button 5T on third joystic8 =oystic87Button5` Button 5` on third joystic8 =oystic87Button5Y Button 5Y on third joystic8 =oystic87Button5[ Button 5[ on third joystic8

102. CLASE INPUT ( IV)

Get6e%Do.n: static function Get<e%Do)n (name : String) : boolean

evuelve true durante el frame en que el usuario empie'a a presionar la tecla identificada como name. &ecordemos llamarla dentro de la funci"n %pdata, ya que resetea su estado cada frame. 9o devuelve true hasta que el usuario suelta y luego aprieta la tecla de nuevo -tal como hace por ejemplo FetButton o4n con respecto a FetButton..

static function Get<e%Do)n (9e% : <e%8ode) : boolean

evuelve true durante el frame en que el jugador empie'a a presionar la tecla identificada por la 8ey de tipo enumeraci"n aey?ode, que vimos en el captulo anterior.

Get6e%U!: static function Get<e%:! (name : String) : boolean static function Get<e%:! (9e% : <e%8ode) : boolean evuelve true durante el frame en que el jugador li!era la tecla identificada por name.

Get7o%stic5Names: static function Get>o%stic94ames () : string+,

evuelve un array de strings descri!iendo los joystic8s conectados. 1sto puede ser 3til en una configuranci"n de entradas de pantalla de usuario. As, en lugar de ensear etiquetas como ]joystic8 5^, puedes mostrasr ttulos ms personali'ados.

Get-o+seB+tton: static function Get3ouse=utton (button : int) : boolean

evuelve true si el !ot"n indicado del rat"n es apretado. /a varia!le !utton es un int que representa E para el !ot"n i'quierdo, 5 para el derecho y 6 para el central. #or poner un ejemplo muy simple+ function %pdate-. O if-0nput.Fet*ouseButton-E.. e!ug./og-<presionado !ot"n i'quierdo.<.C if-0nput.Fet*ouseButton-5.. e!ug./og-<presionado !ot"n derecho.<.C if-0nput.Fet*ouseButton-6.. e!ug./og-<presionado !ot"n central.<.C P

Get-o+seB+ttonDo.n: static function Get3ouse=uttonDo)n (button : int) : boolean

evuelve true durante el frame en que el usuario aprieta el !ot"n del rat"n indicado. e!es llamar esta funci"n dentro de update, ya que el estado se resetea cada frame. 9o devolver true hasta que el !ot"n sea li!erado y vuelto a pulsar -recordemos de nuevo la diferencia de FetButton o4n con respecto a FetButton, para aplicarla tam!in aqu..

Get-o+seB+ttonU!: static function Get3ouse=utton:! (button : int) : boolean

evuelve true durante el frame en que el usuario li!era el !ot"n del rat"n indicado.

ResetIn!+tA)es: static function 7esetIn!ut*/es () : void

&esetea todos los inputs, con lo que todos los a(es y !otones retornan a E. 1sto puede ser util cuando se regenera al jugador y no te interesa conservar ning3n imput que proceda de alguna tecla que pudiera continuar presionando.

GetAccelerationE2ent: static function Get*cceleration6vent (inde/ : int) : *cceleration6vent

evuelve mediciones de aceleraci"n que ocurrieron durante el 3ltimo frame.

103. ESTRUCTURA BOUNDS

?omo es fcil apreciar, Bounds no es una clase, sino una estructura. /a diferencia, aunque a efectos prcticos una clase es lo mismo que una estructura, es ms de tipo semntico. 1sto es, cuando nos topamos con una estructura, se nos quiere informar de que la misma tiene un componente de complemento a una o varias clases que no suelen tener las clases en s. /a estructura !ounds representa una caja de !ordes con los ejes alineados. :am!in denominada AABB -para a!reviar a(is$aligned !ounding !o(., es una caja alineada con los ejes de coordenadas glo!ales que envuelve alg3n o!jeto. ?omo la caja nunca rota respecto de los ejes, puede ser definida por su centro y e(tensiones, o alternativamente por mnimo y m(imo. -center, e(tents, min y ma(, en ingls. /a estructura Bounds se usa en ?ollider.!ounds, *esh.!ounds y &enderer.!ounds.

VARIABLES: center: var center : "ector# 1l centro de la caja.

si*e: var si0e : "ector#

1l tamao total de la caja. 1s siempre dos veces ms grande que las e(tensiones -e(tents.

e)tents: var e/tents : "ector#

/as e(tensiones de la caja. 1s siempre la mitad del tamao -si'e.

min: var min : "ector#

1l punto mnimo de la caja. 1s siempre igual a center f e(tents.

ma): var ma/ : "ector#

1l punto m(imo de la caja. 2iempre es igual a centerBe(tents.

FUNCIONES: static function =ounds (center : "ector# si0e : "ector#) : =ounds

?rea una nueva caja de !ordes con un centro dado y un tamao total. /as e(tensiones de!en ser la mitad del tamao dado.

Set-in-a): function Set3in3a/ (min : "ector# ma/ : "ector#) : void

1sta!lece los !ordes en los valores mnimos y m(imos de la caja. %sar esta funci"n es ms rpido que asignar min y ma( de manera separada.

Enca!s+late: function 6nca!sulate (!oint : "ector#) : void function 6nca!sulate (bounds : =ounds) : void

0ncrementa la caja para incluir el punto que se pasa como parmetro -5er prototipo. o para incluir la nueva caja -6\ prototipo.

E)!and: function 6/!and (amount : float) : void function 6/!and (amount : "ector#) : void

1(pande la caja para incrementar su tamao en una cantidad a lo largo de cada cara.

Intersects: function Intersects (bounds : =ounds) : boolean

R)ay alguna otra caja intersectando nuestra cajaS

Contains: function 8ontains (!oint : "ector#) : boolean

R1st el punto point contenido en la cajaS

s,rDistance: function S2rDistance (!oint : "ector#) : float 1l cuadrado de la distancia entre el punto point y la caja.

intersectRa%: function Intersect7a% (ra% : 7a%) : boolean

R1l rayo ray intersecta esta cajaS #ongamos un ejemplo. #reviamente u!icamos la esfera -que es el gameo!ject al que tenemos vinculado nuestro script. en la posicion -6,E,6., y le aadimos de nuevo un componente &igid!ody. Ahora reeditamos *i#rimer2cript as+ var rayo + &ay D ne4 &ay ->ector7.'ero, >ector7.for4ard.CC function %pdate -. O e!ug. ra4&ay ->ector7.'ero, >ector7.for4ard Z [[[, ?olor.green.C var !ordes + Bounds D transform.collider.!oundsC if -!ordes.0ntersect&ay -rayo.. e!ug./og-</a caja toc" el rayo<.C P function Mi(ed%pdate-. O rigid!ody.AddMorce-$>ector7.rightZTZ:ime.delta:ime.C P

?reamos primero un rayo que surge en el centro glo!al de la escena y se prolonga a lo largo del eje ' positivo -vulgarmente, hacia delante.. ,a dentro de la funci"n update di!ujamos ese mismo rayo que ya tenemos descrito, para que visualmente podamos seguir lo que est pasando. Acto seguido creamos una instancia de la estructura Bounds que en un alarde de originalidad llamaremos !ordes, y la iniciali'aremos con la caja de !ordes del collider de nuestro gameo!ject -la caja que envuelve el collider, ojo, no confundir con el collider mismo. 1n este caso el collider tiene forma de escena y el Bounds de la esfera sigue teniendo forma de caja.. ejamos esta!lecido que si la caja toca el rayo se mostrar un mensaje en pantalla, as que s"lo nos queda darle movimiento a la esfera para que cuando intersecte el rayo -que aqu hemos di!ujado a travs de ra4&ay, pero que podramos ha!er dejado invisi!le. se muestre dicho mensaje.

104. CLASE COLLISION

?lase que o!tiene diferente informaci"n de una colisi"n. /a informaci"n de la collision es pasada a los eventos ?ollider.@n?ollision1nter, ?ollider.@n?ollision2tay y ?ollider.@n?ollision1(it.

VARIABLES: relati2eVelocit%:

>aria!le de s"lo lectura que devuelve la velocidad lineal relativa de los dos o!jetos que colisionan. #ara reali'ar un ejemplo, recoloquemos antes la esfera en -6,E,E.. /uego escri!amos nuestro script+ function @n?ollision1nter-colision + ?ollision. O var vel?ol+ >ector7 D colision.relative>elocityC e!ug./og-vel?ol.magnitude.C

P function Mi(ed%pdate-.O rigid!ody.AddMorce->ector7-$X,E,E..C P

1(pliquemos el script de a!ajo arri!a. 1n la funci"n Mi(ed%pdate lo 3nico que hacemos es aplicar una fuer'a de cuatro unidades hacia la i'quierda a la esfera, for'ndola a colisionar con el cu!o. 1n el momento en que la esfera topa con el cu!o, los datos de la colisi"n son almacenados en el parmetro colision. %no de dichos datos es, como estamos estudiando, la velocidad relativa a la que aqulla se produce, velocidad que almacenamos en la varia!le vel?ol, de tipo >ector7. ,a s"lo nos queda imprimir la fuer'a o longitud de dicho vector, que como recordaremos se hace a travs de la varia!le magnitude. #ulsamos play y o!servamos que la magnitud de la colisi"n es de algo menos de X -fruto de descontar el ro'amiento y la resistencia respecto de la fuer'a aplicada.

rigid"od%: var rigidbod% : 7igidbod%

>aria!le de s"lo lectura que hace referencia al rigid!ody que golpeamos. 1s nulo si el o!jeto que golpeamos es un collider sin rigid!ody vinculado. 1s fcil de ilustrar con un ejemplo+ function @n?ollision1nter-colision + ?ollision. O if-colision.rigid!ody.O e!ug./og-<)e topado con el rigid!ody del o!jeto < B colision.rigid!ody.name.C P P function Mi(ed%pdate-.O rigid!ody.AddMorce->ector7-$X,E,E..C P

9o hay mucho que e(plicar. 2i el collider con el que topa nuestra esfera tiene un rigid!ody, se nos imprime un te(to que adems incluye el nom!re del o!jeto al que dicho rigid!ody pertenece.

collider: var collider : 8ollider

1l collider que golpeamos -s"lo lectura.. #ara determinar la parte concreta que golpeamos de cada collider de!eremos iterar a travs de los puntos de contacto con la propiedad contacts.

trans(orm: var transform : Transform

1l transform del o!jeto que golpeamos -read only.. 2i chocamos contra un collider con un rigid!ody, el transform ser el vinculado al rigid!ody. 2i colisionamos contra un collider sin rigid!ody, el transform ser el vinculado al collider.

gameO"'ect: var gameObject : GameObject

>aria!le de s"lo lectura que devuelve el o!jeto con el que chocamos.

contacts: var contacts : 8ontact5oint+,

1l punto de contacto generado por el engine de fsicas. ?ada contacto implica un punto de contacto, un normal y dos colliders que colisionan -ver ?ontact#oint.. A travs de @n?ollision2tay o @n?ollision1nter puedes siempre estar seguro de que el contacto tiene al menos un elemento. ?ontact#oint es una estructura que tiene estas varia!les+

5. point+ el punto de contacto. #or ejemplo+ function @n?ollision1nter-colision + ?ollision. O if-colision.relative>elocity.magnitude L 6.O print-<#untos de colision+ < B colision.contacts./ength.C print-<#rimer punto de colision+ < B colision.contactsUEV.point.C P P function Mi(ed%pdate-.O rigid!ody.AddMorce->ector7-$Y,E,E..C P

%na !reve e(plicaci"n del script+ ?omo en el anterior aplicamos una fuer'a a la esfera que la o!liga a colisionar con el cu!o. 2i dicha colisi"n tiene una fuer'a superior a 6 unidades se imprimen dos mensajes+ uno que indica el n3mero de colisiones que se ha producido y otro el punto e(acto de la primera colisi"n. 2i no hu!iramos esta!lecido una fuer'a mnima del contacto para que aparecieran los mensajes, el propio contacto de la esfera con el suelo ha!ra disparado dichos mensajes. #ulsamos play y veremos uno de los mensajes, y si hacemos clic8 so!re dicho mensaje para que nos apare'ca el popup de la consola, encontraremos el segundo, tal como muestro en esta captura+

6. normal+ 1l normal del punto de contacto. 7. this?ollider+ 1l primer collider en contacto, o sea, el vinculado al script. function @n?ollision1nter-colision + ?ollision. O if -colision.relative>elocity.magnitude L 6.O print-<:his collider is named+ < B colision.contactsUEV.this?ollider.name.C P P function Mi(ed%pdate-.O rigid!ody.AddMorce->ector7-$Y,E,E..C P

1n este sencillo script o!servamos que this?ollider se corresponde a la esfera. X. other?ollider+ 1l otro collider en contacto. #ara compro!ar que hace referencia al cu!o, meramente sustituir en el script anterior this?ollider por other?ollider.

105. CLASE CONTROLLERCOLLIDER&IT

?ontroller?ollider)it es usado por ?haracter?ontroller.@n?ontroller?ollider)it para dar informaci"n detallada so!re la colisi"n y como tra!ajar con ella.

VARIABLES: controller: var controller : 8haracter8ontroller

1l controller que golpea el collider. un simple ejemplo, para el cual con la esfera seleccionada vamos a men3DL?omponentDL#hysicsDL?haracter ?ontroller, y reempla'amos la 2phere ?ollider. /uego escri!imos el siguiente script+ function @n?ontroller?ollider)it-colision + ?ontroller?ollider)it. O e!ug./og-colision.controller.name.C P function Mi(ed%pdate-.O collider.*ove->ector7-$Y,E,E..C P

#oco que e(plicar. *ovemos la esfera hacia el cu!o -notad que sustituimos la funci"n AddMorce por *ove, ya que ahora nuestra esfera tiene un character controller. %na ve' impacta con el cu!o, se imprime el nom!re del controller -la esfera.

collider: var collider : 8ollider

1l collider que fue golpeado por el controller. #ara verlo en un ejemplo sustituyamos <colision.controller.name< por <colision.collider.name<.

rigid"od%: var rigidbod% : 7igidbod%

1l rigid!ody que fue golpeado por el controller. 1s null si no se toca un rigid!ody sino un collider esttico.

gameO"'ect: var gameObject : GameObject

1l game o!ject que fue golpeado por el controller.

trans(orm: var transform : Transform

1l transform que fue golpeado por el controller.

!oint: var !oint : "ector#

1l punto de impacto en coordenadas glo!ales.

normal: var normal : "ector#

1l normal de la superficie con la que colisionamos en coordenadas glo!ales.

mo2eDirection: var moveDirection : "ector#

Apro(imadamente la direcci"n desde el centro de la cpsula al punto que tocamos. 1sto puede ser 3til para encontrar una direcci"n ra'ona!le para aplicar fuer'as a rigid!odies golpeados.

#or poner un ejemplo muy !sico+ function @n?ontroller?ollider)it-colision + ?ontroller?ollider)it. O colision.rigid!ody.AddMorce-colision.move irection Z 5K.C e!ug./og-colision.move irection.C P function Mi(ed%pdate-.O collider.*ove->ector7-$6,E,E..C P

?uando el cu!o reci!e el impacto de la esfera, a su ve' al rigid!ody vinculado al cu!o le aplicamos una fuer'a en la misma direcci"n del impacto, multiplicada por quince. #aralelamente imprimimos la direcci"n desde el centro de la cpsula de nuestro controller al punto de contacto.

mo2eLenght: var move-ength : float

0ndica lo lejos que el character controller ha viajado hasta golpear al collider. 9ote que esto puede ser diferente de lo que pasas a ?haracter?ontroller.*ove, porque todos los movimientos estn constreidos por colisiones.

10!. CLASE DEBUG

?lase que contiene mtodos para des!ugear con facilidad mientras se desarrolla un juego+

VARIABLES DE CLASE: isDe"+gB+ild: static var isDebug=uild : boolean

1n el dilogo Build 2ettings, que podemos encontrar en el men3DLMile, hay un chec8 !o( llamado ] evelopment Build^. 2i dicho chec8 !o( est marcado, entonces is e!ugBuild ser true.

FUNCIONES DE CLASE: Dra.Line: static function Dra)-ine (start : "ector# end : "ector# color : 8olor & 8olor()hite duration : float & '('f) : void

i!uja una lidea desde el punto que le pasemos como parmetro start hasta el esta!lecido como end con el color que le esta!le'camos como tercer parmetro y durante un tiempo fijado en duration. 2i la duraci"n es E entonces la linea es di!ujada un frame. /a linea ser di!ujada en la vista de escena del editor. 2i en la ventana Fame est ha!ilitada la opcion Fi'mos, tam!in se mostrar ah la lnea. %n pequeo ejemplo+ function %pdate -. O e!ug. ra4/ine ->ector7.'ero, transform.position, ?olor.red.C P

1stamos di!ujando una lnea que empe'ara en el centro de la escena y que ira hasta el centro del o!jeto que tiene vinculado el script, esto es, la esfera. /a lnea sera de color rojo y se di!uja cada frame, coincidiendo con las veces que es llamada la funci"n %pdate. 2i queremos ver tam!in la lnea en la vista Fame, recordemos activar el !ot"n Fi'mos.

Dra.Ra%: static function Dra)7a% (start : "ector# dir : "ector# color : 8olor & 8olor()hite duration : float & '('f) : void

i!uja una lnea desde start a startBdir con el color que especifiquemos por una duraci"n de tiempo tam!in esta!lecida. 2i duraci"n es E entonces la lnea es di!ujada un frame. #ara ver las diferencias con la funci"n anterior, lo mejor ser reali'ar el mismo ejemplo con la nueva funci"n. As+ function %pdate -. O e!ug. ra4&ay ->ector7.'ero, transform.positionZ5E, ?olor.red.C P

>emos que aqu el segundo parmetro no es el destino final del rayo, sino la direcci"n y distancia de ste. 1n este caso veremos una lnea;rayo de 5E metros saliendo desde el centro de la escena.

Brea5: static function =rea9 () : void

#ausa el editor. 1sto es 3til cuando queremos compro!ar ciertos valores en el inspector y no somos capaces de pausarlo manualmente.

Log: static function -og (message : object) : void Anota mensajes en la consola de %nity+ e!ug./og-<)ola, mundo<.C

static function -og (message : object conte/t : Object) : void ?uando seleccionas en mensaje en la consola se di!uja una cone(i"n con el o!jeto conte(tual. 1sto es muy 3til si queremos sa!er qu errores ocurren en un o!jeto. *e e(plico. 1scri!imos esto en *i#rimer2cript -que recordemos que tenemos vinculado a la esfera.+

e!ug./og -<)ola, mundo<, game@!ject.C

Al darle al play, tal como podemos suponer, aparece el mensaje impreso en la consola. #ero en este caso, si hacemos clic8 so!re ese mensaje, o!servaremos que en la jerarquia automticamente se nos selecciona la esfera durante unos segundos.

LogError: static function -og6rror (message : object) : void

%na varia!le de e!ug./og que anota un mensaje de error en la consola -en color rojo. e!ug./og1rror-<1sto es un error<.C

static function -og6rror (message : object conte/t : Object) : void >ariante similar a la que trat!amos antes para /og.

Log;arning: static function -og?arning (message : object) : void %na variante de e!ug./og que muestra un mensaje de aviso en la pantalla -en color amarillo. static function -og?arning (message : object conte/t : Object) : void *ensaje vinculado a un determinado o!jeto, como en los dos casos anteriores.

10". CLASE EVENT (I)

:ipos de teclas modificadores que pueden estar activos durante un proceso de pulsaci"n de tecla. /os eventos pueden corresponder a entradas de usuario -teclas presionadas, acci"n de rat"n. o !ien ser distri!uciones -layers. de unityF%0 o eventos de renderi'ado. Asi como @nF%0 es potencialmente llamado multiples veces por frame. 1vent.current corresponde al actual evento dentro de la llamada a @nF%0.

VARIABLES: t%!e: var t%!e : 6ventT%!e

>aria!le que indica el tipo de evento. 1s de tipo 1vent:ype, que es una enumeraci"n que permite los siguientes valores+

*ouse o4n %n !ot"n del rat"n ha sido presionado. *ouse%p %n !ot"n del rat"n ha sido li!erado. *ouse*ove 1l rat"n se ha movido -s"lo en vista de edici"n.. *ouse rag 1l rat"n fue arrastrado. aey o4n %na tecla del teclado fue presionada. aey%p %na tecla del teclado fue li!erada. 2croll_heel /a rueda del rat"n se movi". &epaint %n evento de repintado. 2e enva uno cada frame. /ayout %n evento de distri!uci"n. rag%pdated 2olo en editor+ operaci"n de drag e drop actuali'ada. rag#erform 2"lo en editor+ operaci"n de drag e drop reali'ada. rag1(ited 2"lo en editor+ operacion de drag e drop finali'ada. 0gnore el evento de!e ser ignorado. %sed 1vento ya procesado. >alidate?ommand >alida un comando especial -p.ej. copy e paste. 1(ecute?ommand 1jecuta un comando especial -p.ej. copy e paste. ?onte(t?lic8 1l usuario ha hecho clic8 con el !ot"n derecho.

#ongamos un !reve ejemplo+ function @nF%0 -. O e!ug./og-<?urrent event detected+ < B 1vent.current.type.C P

1ste script meramente imprime el evento que est teniendo lugar cada frame. #rue!a, tras pulsar play, a hacer clic8 con diferentes !otones del rat"n, pulsa distintas teclas, mueve el rat"n, etc. /uego detn el reproductor y ha' clic8 so!re el 3ltimo mensaje de la consola para que te apare'ca el pop up. >ers una lista enorme de eventos que han tenido lugar, la mayora de repintado y distri!uci"n, pero entre ellos estarn los que hayas provocado durante ese tiempo.

mo+se/osition: var mouse5osition : "ector1

/a posici"n del rat"n. >aria!le usada en los eventos 1vent:ype.*ouse*ove y 1vent:ype.*ouse rag.

delta: var delta : "ector1

1l movimiento relativo del rat"n comparado con el 3ltimo evento.

"+tton: var button : int

Gu !ot"n del rat"n ha sido presionado. Apliquemos un ejemplo+ function @nF%0-. O var mi1vento + 1vent D 1vent.currentC if-mi1vento.!utton DD E ee mi1vento.is*ouse.O e!ug./og-<Bot"n i'quierdo<.C

P else if-mi1vento.!utton DD 5. O e!ug./og-<Bot"n derecho<.C P else if -mi1vento.!utton DD 6. O e!ug./og-<Bot"n del centro<.C P P

?reamos primero una instancia de la clase 1vent, que contendr el evento actual. 2i dicho evento es un evento de rat"n -is*ouse, que estudiaremos de aqu a un momento. y !utton vale cero -esto es, !utton vale cero pese a ha!er un evento de rat"n, ya que si no hay evento de rat"n !utton tam!in vale cero, no s si me estoy e(plicando. se imprime un mensaje, y as sucesivamente -con valores de !utton en uno y dos no hace falta descartar la posi!ilidad de que no se est produciendo un evento de rat"n por lo anteriormente e(plicado.

modi(iers: var modifiers : 6vent3odifiers Gu tecla modificadora est siendo pulsada- ahift, ctrl, alt.... function @nF%0-. O var mi1vento + 1vent D 1vent.currentC e!ug./og-mi1vento.modifiers.C P

#ro!ad a pulsar las teclas modificadoras y las veris impresas, a diferencia de las que no tienen esa condici"n.

104. CLASE EVENT (II)

clic5Co+nt: var clic98ount : int

?untos clic8s de rat"n consecutivos hemos reci!ido. 1s usado en el evento 1vent:ype.*ouse o4n. %sadlo para diferenciar entre un clic8 3nico y un do!le clic8. %n ejemplo+ private var numero?lic8s + int D EC function @nF%0-. O var mi1vento + 1vent D 1vent.currentC

if -mi1vento.is*ouse. O numero?lic8s BDmi1vento.clic8?ountC e!ug./og-<*ouse clic8s+ < B numero?lic8s.C P P

2i lo pro!amos, vemos que tenemos un contador de clic8s que conta!ili'a cada actividad -do4n y up. del !ot"n del rat"n desde el inicio del juego. 1s una adaptaci"n del script que est en el manual de referencia. 2i os fijis, declaramos la varia!le numero?lic8s fuera de la funci"n onF%0, para que no nos conta!ilice -como hace en el manual de referencia. los clic8s de cada frame, sino los totales. #or lo dems, el script no tiene mucho misterio+ iniciali'amos una varia!le de tipo 1vent con el evento actual, nos aseguramos de que el evento tenga que ver con el rat"n y pasamos a contar clic8s.

character: var character : char

1l tipo de caracter. function @nF%0-. O var mi1vento + 1vent D 1vent.currentC if -mi1vento.isaey. O e!ug./og-<#ulsado caracter+ < B mi1vento.character.C P P commandName var command4ame : String

1l nom!re de un evento de tipo 1(ecute?ommand o >alidate ?ommand -<?opy<, <?ut<, <#aste<, < elete<, <Mrame2elected<, < uplicate<, <2electAll<, etc.

5e%Code: var 9e%8ode : <e%8ode

1l 8ey code para eventos de teclado. %sado en los eventos 1vent:ype.aey o4n y 1vent:ype.aey%pC devuelve el valor del aey?ode, por lo que se usa para manejar, por ejemplo, teclas de cursor, de funciones, etc. :eclead este c"digo y tras salvar y darle al play pulsad por ejemplo una de las flechas de despla'amiento del teclado+ function @nF%0-. O var mi1vento + 1vent D 1vent.currentC if -mi1vento.isaey. O e!ug./og-<1l 8ey code es+ < B mi1vento.8ey?ode.C P P

shi(t: var shift : boolean

R1st shift pulsadoS -s"lo lectura.

control: var control : boolean

R1st control pulsadoS -s"lo lectura.

alt: var alt : boolean

R1st alt pulsadoS -2"lo lectura.

ca!sLoc5: var ca!s-oc9 : boolean

R1st el !loqueo de may3sculas pulsadoS -s"lo lectura.

n+meric: var numeric : boolean

R2e est presionando alguna tecla del teclado numrico. -s"lo lectura.

(+nction6e%: var function<e% : boolean

R1s la tecla presionada una tecla de funci"n -alt, ctrl, shift, etc.S -2"lo lectura.

is6e%: var is<e% : boolean

R1s este evento un evento de tecladoS -s"lo lectura.

is-o+se:

var is3ouse : boolean

R1s este evento un evento de rat"nS -s"lo lectura.

105. CLASE EVENT ( III)

FUNCIONES: GetT%!eFromControl: function GetT%!eFor8ontrol (controlID : int) : 6ventT%!e

1sta funci"n devuelve un tipo de evento que es filtrado para un determinado control cuya id pasamos como parmetro. 1sta funci"n es usada para implementar !loqueos de rat"n y de focos de teclado. 1l id del control para el que requerimos el tipo de evento se o!tiene de F%0%tilty.Fet?ontrol0 podemos ver una lista de sus posi!les valores. -., y en 1vent:ype

Use: function :se () : void

1vento ya utili'ado. de!eramos llamar a este mtodo cuando ya hemos usado un evento. 1l tipo de evento ser colocado en 1vent:ype.%sed, causando que otros elementos F%0 lo ignoren.

VARIABLES DE CLASE: c+rrent: static var current : 6vent

1l evento actual;corriente que est siendo procesado en este mismo momento. %n ejemplo+ function @nF%0-. O var mi1vento + 1vent D 1vent.currentC if-mi1vento.type QD 1vent:ype.repaint ee mi1vento.type QD 1vent:ype.layout.O e!ug./og-<?urrent detected event+ < B 1vent.current.C P P

2alvamos y tras pulsar al play disparamos los eventos que deseemos. etenemos el reproductor y accedemos a la consola donde se muestran los mensajes haciendo clic8 so!re el 3ltimo y ah tendremos toda la informaci"n so!re teclas pulsadas, movimientos y clics del rat"n, etc. @!servaris que descart la impresi"n de eventos de tipo repaint y

layout, que son los que se producen de manera automtica y en un n3mero mayor.

10!. CLASE GI(MOS

/os Fi'mos son usados para permitir un de!ug visual o !ien para colocar ayudas en la vista de escena. :odos los gi'mos de!en ser di!ujados o con la funci"n @n ra4Fi'mos o con la funci"n. @n ra4Fi'mos2elected. /a diferencia de am!as es que+ @n ra4Fi'mos es llamada cada frame. @n ra4Fi'mos2elected es llamada s"lo si el o!jeto al cual est vinculado el script es seleccionado.

VARIABLES DE CLASE: color: static var color : 8olor

1sta!lece el color para los gi'mos que sern di!ujados a continuaci"n. >amos a hacer un pequeo ejemplo. Aseguros de que *i#rimer2cript sigue estando vinculado a la esfera, y acto seguido deseleccionar cualquier gameo!ject haciendo clic8 en un espacio vaco de la =erarqua. ?ompro!amos que en la vista game tengamos marcada la pestaa Fi'mos. 1scri!imos+ function @n ra4Fi'mos2elected -. O Fi'mos.color D ?olor.!lueC var direction + >ector7 D transform.:ransform irection ->ector7.for4ard. Z KC Fi'mos. ra4&ay -transform.position, direction.C P

/e damos al play y no parece ocurrir nada. 1sto es porque estamos llamando a la funci"n @n ra4Fi'mos2elected, que s"lo muestra el di!ujo cuando seleccionamos el o!jeto al cual va vinculado el script, as que en la jerarqua seleccionamos la esfera y automticamente nos de!era aparecer una lnea de color a'ul que va desde la posici"n del transform de la esfera cinco metros en adelante.

FUNCIONES DE CLASE: Dra.Ra%: static function Dra)7a% (r : 7a%) : void static function Dra)7a% (from : "ector# direction : "ector#) : void i!uja un rayo que empie'a desde from hasta from B direction. /o hemos visto en funcionamiento en el ejemplo anterior.

Dra.;ireS!here:

static function Dra)?ireS!here (center : "ector# radius : float) : void

i!uja una esfera de alam!re con centro y radio. var radio D 6.EC function @n ra4Fi'mos-. O Fi'mos.color D ?olor.cyanC Fi'mos. ra4_ire2phere -transform.position, radio.C P

*eramente como apunte, aqu la esfera de alam!re se ve tengamos o no seleccionado el game o!ject esfera, porque la hemos di!ujado con la funci"n @n ra4Fi'mos.

Dra.S!here: static function Dra)S!here (center : "ector# radius : float) : void

i!uja una esfera s"lida con centro y radio.

Dra.;ireC+"e: static function Dra)?ire8ube (center : "ector# si0e : "ector#) : void

i!uja una caja de alam!re con centro y tamao.

Dra.C+"e: static function Dra)8ube (center : "ector# si0e : "ector#) : void

i!uja una caja s"lida con centro y tamao.

Dra.Icon: static function Dra)Icon (center : "ector# name : String) : void i!uja un icono en posici"n glo!al en la vista de escena. 1l icono de!er tener el mismo nom!re que le asignamos al parmetro name y estar u!icado en las coordenadas que le pasemos al parmetro center. 1l path del icono puede encontrarse en la carpeta Assets;Fi'mos. >amos por partes+ Antes que nada necesitamos una imagen tipo icono. ,o para el ejemplo he usado sta. &enom!ramos a la imagen como <nave<. #or otro lado, en el archivo donde estamos guardando estos ejemplos, dentro de la carpeta assets, hemos de crear una carpeta llamada Fi'mos, que es el path que %nity !uscar para dar con los iconos de este tipo. /uego arrastramos nuestra nave a la recin creada carpeta. , ahora editamos el script+ function @n ra4Fi'mos -. O Fi'mos. ra40con -transform.position B >ector7-E,6,E., <nave.png<.C P

#ulsamos el play, y dos metros por encima de nuestra esfera de!era aparecernos la nave, tal que as+

Dra.GUITe)t+re: static function Dra)G:ITe/ture (screen7ect : 7ect te/ture : Te/ture mat : 3aterial & null) : void static function Dra)G:ITe/ture (screen7ect : 7ect te/ture : Te/ture left=order : int right=order : int to!=order : int bottom=order : int mat : 3aterial & null) : void

i!uja una te(tura en coordenadas de pantalla. 1s 3til para !ac8grounds de F%0.

10". CLASE LIG&TMAPSETTINGS

Almacena los mapas de luces -lightmaps. de la escena. %na escena puede tener varios lightmaps almacenados en ella, y suss componentes &enderer pueden usar esos lightmaps. 1sto hace posi!le usar el mismo material en m3ltiples o!jetos, mientras cada o!jeto puede referirse a diferentes lightmaps o diferentes porciones del mismo lightmap.

VARIABLES DE CLASE: lightma!s: static var lightma!s : -ightma!Data+,

1s un array de tipo /ightmap ata que puede almacenar diferentes lightmaps. /ightmap ata es una clase con dos

varia!les+ lightmapMar+ lightmap9ear+

/ightmap que almacena la totalidad de la lu' entrante. /ightmap que almacena s"lo la lu' indirecta entrante.

lightsma!-ode: static var lightma!s3ode : -ightma!s3ode

*odo de renderi'ado de lightmaps. /ightmaps*ode es una enumeraci"n con los siguientes dos valores+ 2ingle+ *odo de renderi'ado de lightmap tradicional. ual+ *odo de renderi'ado de lightmap dual.

10#. ESTRUCTURA MAT&% (I)

1structura que contiene una colecci"n de funciones matemticas que podemos usar para nuestros scripts.

VARIABLES DE CLASE: /I: static var 5I : float 1l famoso 7.5X5K[6. -s"lo lectura. ?omo pequea anotaci"n, o!servad que las varia!les de clase de *athf comien'an por may3scula, al contrario de las varia!les de clase del resto de clases y funciones en %nity. :enedlo presente, ya que es una fuente importante de errores.

In(init%: static var Infinit% : float &epresentaci"n del infinito positivo -s"lo lectura.

Negati2eIn(init%: static var 4egativeInfinit% : float

%na representaci"n del infinito negativo -s"lo lectura.

Deg9Rad: static var Deg17ad : float

?onversi"n constante de grados a radianes -s"lo lectura.

Rad9Deg: static var 7ad1Deg : float

?onversi"n constante de radianes a grados -s"lo lectura.

E!silon: static var 6!silon : float

1l valor ms pequeo que un float puede tener diferente de cero -s"lo lectura.

FUNCIONES DE CLASE: Sin:

static function Sin (f : float) : float

evuelve el seno del ngulo f en radianes.

Cos: static function 8os (f : float) : float evuelve el coseno del ngulo f en radianes.

Tan: static function Tan(f : float) : float

evuelve la tangente del ngulo f en radianes.

Asin: static function *sin (f : float) : float

evuelve el arco seno de f menos el ngulo en radianes cuyo seno es f.

Acos: static function *cos (f : float) : float

evuelve el arco coseno de f menos el ngulo en radianes cuyo coseno es f.

Atan: static function *tan (f : float) : float

evuelve el arco tangente de f menos el ngulo en radianes cuya tangente es f.

Atan9: static function *tan1 (% : float / : float) : float

evuelve el ngulo en radianes cuya tangente es y;(. 1l valor retornado es el ngulo entre el eje I y un vector 6 que empie'a en cero y aca!a en -(,y.

S2rt: static function S2rt (f : float) : float

evuelve la ra' cuadrada de f.

A"s: static function *bs (value : float) : float static function *bs (value : int) : int evuelve el valor a!soluto de value.

-in: static function 3in (a : float b : float) : float static function 3in (!arams values : float+,) : float static function 3in (a : int b : int) : int static function 3in (!arams values : int+,) : int evuelve el valor mnimo de dos o ms valores dados.

-a):

static function 3a/ (a : float b : float) : float static function 3a/ (!arams values : float+,) : float static function 3a/ (a : int b : int) : int static function 3a/ (!arams values : int+,) : int evuelve el valor m(imo de dos o ms valores.

/o.: static function 5o) (f : float ! : float) : float evuelve f elevado a la potencia p.

E)!: static function 6/! (!o)er : float) : float

evuelve la potencia natural de un determinado n3mero.

Log: static function -og (f : float ! : float) : float static function -og (f : float) : float

evuelve el logaritmo de un determinado n3mero en una !ase especificada.

Log8<: static function -og.' (f : float) : float

evuelve el logaritmo en !ase die' de un determinado n3mero.

10$. ESTRUCTURA MAT&% (II)

Ceil: static function 8eil (f : float) : float

evuelve el integer ms pequeo igual o mayor que f.

Floor: static function Floor (f : float) : float

evuelve el mayor integer igual o ms pequeo que f.

Ro+nd: static function 7ound (f : float) : float

evuelve f redondeado al integer ms cercano. 2i el n3mero aca!a en .K y queda entre dos integers, uno de los cuales es par y el otro impar, se devolver el numero par.

CeilToInt: static function 8eilToInt (f : float) : int

evuelve el integer ms pequeo igual o mayor que f.

FloorToInt: static function FloorToInt (f : float) : int

evuelve el mayor integer menor o igual que f.

Ro+ndToInt: static function 7oundToInt (f : float) : int

evuelve f rendondeada al integer ms cercano. 2i e n3mero aca!a en .K y por lo tanto est a medio camino entre dos integers, uno impar y el otro par, se devuelve el n3mero par.

Sign: static function Sign (f : float) : float

evuelve el signo de f. evuelve 5 si es positivo o cero, y $5 si f es negativo.

Clam!:

static function 8lam! (value : float min : float ma/ : float) : float static function 8lam! (value : int min : int ma/ : int) : int &estringe un valor entre un mnimo y un m(imo, sean floats o ints. >amos a verlo con un ejemplo+ for-var ( + int D EC ( WD 5EC (BB. O var numeroMijado + int D *athf.?lamp-(, 5, K.C e!ug./og-numeroMijado.C P

*ediante un !ucle for le pasamos como primer parmetro a la funci"n ?lamp n3meros del 5E al die'. 2i desplegamos la consola tras pro!ar este ejemplo veremos que cuando ( vale E, clamp devuelve el valor mnimo fijado -en este caso 5.. /o mismo pasa cuando ( vale ms de K.

Clam!<8: static function 8lam!'. (value : float) : float Mija un valor entre E y 5 y lo devuelve.

Ler!: static function -er! (from : float to : float t : float) : float

0nterpola a hacia ! pasando por t. t queda fijada entre E y 5. ?uando t D E devuelve from. ?uando t D 5 devuelve to. ?uando t D E.K devuelve la media de a y !.

Ler!Angle: static function -er!*ngle (a : float b : float t : float) : float

/o mismo que lerp, pero asegurndonos de interpolar valores correctamente cuando d un giro de 7TE grados. /as varia!les a y ! representan grados. #ara ilustrar esta funci"n y la anterior vamos a apaar un pequeo ejemplo. 2era interesante que eliminrais el script vinculado a la esfera. 1ditamos+ var origen D $6.EC var destino D 5.EC var angulo0nicialD E.EC var anguloMinalD [E.EC function %pdate -. O transform.position D >ector7-*athf./erp-origen, destino, :ime.time Z E.5., E, E.C var angle + float D *athf./erpAngle-angulo0nicial, anguloMinal, :ime.time Z E.5.C transform.eulerAngles D >ector7-E, angle, E.C P

2alvamos y vinculamos el script al cu!o. A la funci"n /erp le pasamos el parmetro de situaci"n inicial $6, que coincide con su posici"n actual en el eje (, y le indicamos un destino en 5. :radicionalmente como tercer parmetro se coloca :ime.time, que pasa de E a 5 en un segundo, pero como queremos que el trayecto sea ms lento, multiplicamos :ime.time por E.5, de tal manera que el trayecto total dure 5E segundos. @tro tanto hacemos con el angulo inicial y final. ?omo resultado, el cu!o se mover tres metros en el eje I y girar [E

grados so!re el eje , en die' segundos.

-o2eTo.ards: static function 3oveTo)ards (current : float target : float ma/Delta : float) : float

*ueve el valor que indicamos en el parmetro current hacia el que indicamos en target. )asta aqu la funci"n sera parecida a *athf./erp, pero aqu nos aseguramos de la que velocidad no e(ceda de ma( elta. >alores negativos para ma( elta empuja el valor lejos del o!jetivo.

-o2eTo.ardsAngle: static function 3oveTo)ards*ngle (current : float target : float ma/Delta : float) : float

/o mismo que *ove:o4ards pero estando seguros de que los valores se interpolarn correctamente cuando gire 7TE grados. /a diferencia de *ove:o4ards y *ove:o4ardsAngle con respecto de /erp y /erpAngle la veremos ms fcilmente rehaciendo el script anterior+ var origen D $6.EC var destino D 5.EC var minAngle D E.EC var ma(Angle D [E.EC function %pdate -. O transform.position D >ector7-*athf.*ove:o4ards-origen, destino, :ime.time Z 5., E,E.C var angle + float D *athf.*ove:o4ardsAngle-minAngle, ma(Angle, :ime.time Z 7E.C transform.eulerAngles D >ector7-E, angle, E.C P

/a diferencia la tenemos que hallar en el tercer parmetro. 1n el caso de *ove:o4ards lo que le estamos pidiendo aqu al cu!o es que se mueva en el eje ( de la posici"n $6 a la 5 -7 metros, o sea. a ra'"n de un metro por segundo. , #ara *ove:o4ardsAngle estamos indicndole al cu!o que gire [E grados a ra'"n de 7E grados por segundo. e esta manera, en 7 segundos el cu!o de!era ha!er completado am!os movimientos. #ro!adlo.

SmoothSte!: static function SmoothSte! (from : float to : float t : float) : float 0nterpola entre mnimo y m(imo y facilita entrada y salida de los lmites. 2era como /erp, pero con un impulso inicial. 2i meramente sustitus em el 3ltimo script *ove:o4ards por 2mooth2tep veris a qu me refiero.

A!!ro)imatel%: static function *!!ro/imatel% (a : float b : float) : boolean ?ompara si dos valores en punto flotante son similares. e!ido a que los numeros en punto flotante son imprecisos no es recomenda!le compararlos usando el operador DD -podra no devolver true., y es mejor utili'ar esta funci"n.

110. ESTRUCTURA MAT&% ( III)

SmoothDam!: static function SmoothDam! (current : float target : float ref current"elocit% : float smoothTime : float ma/S!eed : float & 3athf(Infinit% deltaTime : float & Time(deltaTime) : float

Fradualmente cam!ia un valor hacia un o!jetivo en un determinado tiempo. /a funci"n se puede usar para suavi'ar la transici"n de valores, colores, posiciones, escalaresh. ?uenta con los siguientes parmetros+ current /a posici"n actual. target /a posici"n que estamos tratando de alcan'ar. current>elocity /a velocidad actual. 1ste valor es modificado por la funci"n cada ve' que la llamamos. smooth:ime Apro(imadamente el tiempo que tardaremos en alcan'ar el o!jetivo. %n valor pequeo har que allcancemos el o!jetivo ms rpido. ma(2peed @pcionalmente nos permite fijar la velocidad m(ima. delta:ime 1l tiempo desde la 3ltima llamada a esta funci"n. #or defecto :ime.delta:ime.

%n ejemplo+ var o!jetivo + :ransformC var tiempo1mpleado D 7C private var y>elocity DX.EC function %pdate -. O var ne4#osition + float D *athf.2mooth amp-transform.position.(, o!jetivo.position.(, y>elocity, tiempo1mpleado.C transform.position D >ector7-ne4#osition, transform.position.y, transform.position.'.C P

2alvamos y arrastramos el cu!o a la varia!le e(puesta <o!jetivo<. /o que aqu estamos haciendo es usar la funci"n 2mooth amp para ir marcando la nueva posici"n de nuestro cu!o. 1l punto de origen ser la posici"n actual del cu!o -en el eje (., el destino la posici"n actual en dicho eje del transform que marcamos como o!jetivo, le esta!lecemos un tiempo para que el origen alcance al o!jetivo de 7 segundos y le limitamos la velocidad m(ima que pueda alcan'ar nuestro cu!o a cuatro metros por segundo.

SmoothDam!Angle: static function SmoothDam!*ngle (current : float target : float ref current"elocit% : float smoothTime : float ma/S!eed : float & 3athf(Infinit% deltaTime : float & Time(deltaTime) : float

?am!ia gradualmente un ngulo dado en grados hacia el ngulo que constituye el o!jetivo en un tiempo determinado. 1l uso ms com3n de esta funci"n es para suavi'ar una cmara que est siguiendo alg3n personaje o escena.

Re!eat: static function 7e!eat (t : float length : float) : float

0ntroduce en un !ucle el valor t, de tal manera que nunca sea ms grande que length y nunca ms pequeo que E.

/ing/ong: static function 5ing5ong (t : float length : float) : float

)ace re!otar el valor t, de tal manera que nunca sea mayor que length y nunca mayor que E. 1l valor retornado se mover atrs y adelante entre E y length.

In2erseLer!: static function Inverse-er! (from : float to : float value : float) : float

?alcula el parmetro /erp entre dos valores.

Closest/o.erO(T.o: static function 8losest5o)erOfT)o (value : int) : int

&etorna la potencia de dos ms cercana.

Is/o.erO(T.o: static function Is5o)erOfT)o (value : int) : boolean

evuelve true si el valor es potencia de dos

Ne)t/o.erO(T.o: static function 4e/t5o)erOfT)o (value : int) : int evuelve el valor de la siguiente potencia de dos.

DeltaAngle: static function Delta*ngle (current : float target : float) : float

?alcula la diferencia ms corta entre dos ngulos dados.

111. CLASE P&YSICS (I)

?omponen esta clase, al igual que la estructura *athf anterior, propiedades glo!ales y mtodos de ayuda relacionados con las fsicas.

VARIABLES DE CLASE: gra2it%: static var gravit% : "ector#

/a gravedad aplicada a todos los rigid!odies en la escena. #uede ser desconectada para un rigid!ody individual usando su propiedad useFravity.

FUNCIONES DE CLASE: Ra%cast: static function 7a%cast (origin : "ector# direction : "ector# distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean /an'a un rayo contra todos los colliders en la escena. evuelve true cuando el rayo intersecta alg3n collider. :iene los siguientes parmetros+ origin 1l punto inicial del rayo en coordenadas glo!ales. direction /a direcci"n del rayo. distance /a longitud o fuer'a del rayo. layer*as8 %na mscara de distri!uci"n -/ayer mas8. que se usa para ignorar selectivamente colliders cuando se proyecta un rayo.

#or ejemplo+ function %pdate -. O var derecha + >ector7 D transform.:ransform irection ->ector7.right.C if -#hysics.&aycast -transform.position, derecha, 5E.. O print -<)ay algo a mi derecha<.C P P

/o que hacemos aqu es primero tomar la direcci"n local de nuestro cu!o y convertirla en direcci"n glo!al, a travs de la funci"n :ransform irection. icha direcci"n glo!al la almacenamos en la varia!le <derecha<. Acto seguido, imprimimos un mensaje si desde la posici"n de nuestro cu!o en una distancia no superior a die' metros hay a la derecha glo!al del mismo otro o!jeto. static function 7a%cast (origin : "ector# direction : "ector# out hitInfo : 7a%castHit distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean #royecta un rayo contra todos los colliders en la escena y devuelve informaci"n detallada so!re qu golpe". /os parmetros de este segundo prototipo de funci"n son+ origin 1l punto de inicio del rayo en coordenadas glo!ales. direction /a direcci"n del rayo. distance /a fuer'a o longitud del rayo. hit0nfo 2i se devuelve true, esta varia!le contendr ms informaci"n so!re donde colision" el collider. layer*as8 %n layer mas8 usado para ignorar colliders selectivamente cuando se proyecte un rayo.

static function 7a%cast (ra% : 7a% distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean static function 7a%cast (ra% : 7a% out hitInfo : 7a%castHit distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean 2on similares a las funciones anteriores, s"lo que usando ray.origin y ray.direction en ve' de origen y direcci"n como sendos >ector7.

Ra%castAll: static function 7a%cast*ll (ra% : 7a% distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : 7a%castHit+, static function 7a%cast*ll (origin : "ector# direction : "ector# distance : float & 3athf(Infinit% la%ermas9 : int & 9Default7a%cast-a%ers) : 7a%castHit+, /an'a un rayo a travs de la escena y devuelve todos los choques. >amos a adaptar un ejemplo del manual de referencia+ function %pdate -. O var choques + &aycast)itUVC choques D #hysics.&aycastAll -transform.position, transform.right, 5EE.E.C for -var i D ECi W choques./engthC iBB. O var mi?hoque + &aycast)it D choquesUiVC var renderer D mi?hoque.collider.rendererC if -renderer. O renderer.material.shader D 2hader.Mind-<:ransparent; iffuse<.C renderer.material.color.a D E.7C P P P

>amos paso a paso en la e(plicaci"n. #rimero declaramos una varia!le que contendr un array de tipo &aycast)it, que es precisamente lo que hemos visto que devuelve la funci"n &aycastAll. /a iniciali'amos con todas aquellas colisiones que sufra nuestro rayo, el cual proyectamos desde el cu!o 5EE metros a la derecha. ado que puede ha!er ms de una colisi"n, iteramos a travs del array y el collider con el que se ha producido cada colisi"n le es asignado temporalmente a la varia!le mi?hoque, a travs de la cual lo volvemos semitransparente. 2i pulsamos play vemos que nuestra esfera se torna semiinvisi!le.

LineCast: static function -inecast (start : "ector# end : "ector# la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

evuelve true si hay alg3n collider intersectando la lnea entre start y end.

static function -inecast (start : "ector# end : "ector# out hitInfo : 7a%castHit la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

1n este segundo prototipo, si se devuelve true, hitinfo contendr ms informaci"n so!re d"nde colision" el collider.

O2erla!S!here: static function Overla!S!here (!osition : "ector# radius : float la%er3as9 : int & 9*ll-a%ers) : 8ollider+,

evuelve un array con todos los colliders que toquen o estn dentro de la esfera cuya posici"n y radio pasamos como parmetros.

112. CLASE P&YSICS ( II)

Ca!s+leCast: static function 8a!sule8ast (!oint. : "ector# !oint1 : "ector# radius : float direction : "ector# distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean static function 8a!sule8ast (!oint. : "ector# !oint1 : "ector# radius : float direction : "ector# out hitInfo : 7a%castHit distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

/an'a una cpsula contra todos los colliders de la escena y devuelve informaci"n de contra qu ha chocado. true cuando el s4eep -!arrido. de la cpsula choca con alg3n collider. /os parmetros de esta funci"n son+ point5 1l inicio de la cpsula. point6 1l fin de la cpsula. radius 1l radio de la cpsula. direction /a direcci"n en la cual hace el !arrido la cpsula. hit0nfo 2i devuelve true, hit0nfo contendr ms informaci"n so!re d"nde golpe" el collider. distance /a longitud del !arrido. layer*as8 %n /ayer mas8 que se usa para ignorar selectivamente colliders cuando se proyecte la cpsula.

evuelve

/a cpsula viene conformada por las dos esferas con radios alrededor del point5 y point6, que forman los dos finales de la cpsula. 1sto es 3til cuando un &aycast no tiene suficiente precisi"n para lo que queremos hacer, como por ejemplo asegurarnos de que un personaje podr moverse a cualquier sitio sin colisionar con nada en el camino.

S!hereCast: static function S!here8ast (origin : "ector# radius : float direction : "ector# out hitInfo : 7a%castHit distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

#royecta una esfera contra todos los colliders de la escena y proporciona informaci"n so!re los que colisionan. evuelve true si topa con alguno en su !arrido. ?uenta con estos parmetros+ origin 1l centro de la esfera al principio del !arrido. radius 1l radio de la esfera. direction /a direcci"n en la cual hace el !arrido la esfera. hit0nfo 2i la funci"n devuelve true, esta varia!le contendr ms informaci"n acerca de d"nde el collider colision" -#ara ms informaci"n ver+ &aycast)it.. distance /a longitud del !arrido. layer*as8 %n /ayer mas8 que se usa para ignorar selectivamente colliders cuando se proyecta la cpsula.

1sta funci"n es 3til cuando un &aycast no nos da suficiente precisi"n, como por ejemplo en el caso en que queramos averiguar si un o!jeto de un determinado tamao, como un character, ser capa' de de moverse a alg3n lado sin colisionar con algo por el camino. 1n casos como estos es preferi!le usar la funci"n 2phere?ast. )emos de tener presente, eso s, que la 2phere?ast no funcionar contra aquellos colliders configurados como triggers. #ro!emos un ejemplo. #reviamente hay que aadirle un character controller al cu!o. Acto seguido tecleamos este script+ function %pdate -. O var hit + &aycast)itC var char?trl + ?haracter?ontroller D Fet?omponent-?haracter?ontroller.C var p5 + >ector7 D transform.position B char?trl.centerC if -#hysics.2phere?ast -p5, char?trl.height ;6, transform.right, hit, 5E.. O e!ug./og-<)ay un o!stculo a < B hit.distance B < metros<.C P P

/o que hemos hecho aqu es, a grandes rasgos, que nuestro cu!o efect3e un !arrido hacia la derecha en !usca de o!stculos para un character con un radio equivalente a la mitad de la altura de nuestro character. Al topar con uno, se muestra un mensaje en pantalla junto con informaci"n suplementaria, como en este caso la distancia a que se halla dicho o!stculo. 1l ejemplo es un poco rupestre, pero nos permite intuir la utilidad de esta funci"n para aplicrsela a un personaje. static function S!here8ast (ra% : 7a% radius : float distance : float 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean static function S!here8ast (ra% : 7a% radius : float out hitInfo : 7a%castHit distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

Ca!s+leCastAll: static function 8a!sule8ast*ll (!oint. : "ector# !oint1 : "ector# radius : float direction : "ector# distance : float & 3athf(Infinit% la%ermas9 : int & 9Default7a%cast-a%ers) : 7a%castHit+,

1s como #hysics.?apsule?ast, pero devolviendo todos los colliders que la cpsula intercepta en su !arrido e informaci"n so!re los mismos. evuelve un array con todos esos colliders. #armetros+ point5 1l principio de la cpsula. point6 1l final de la cpsula. radius 1l radio de la cpsula. direction /a direcci"n en la cual efect3a el !arrido la cpsula. distance /a longitud del !arrido. layer*as8 %n /ayer mas8 que se usa para ignorar selectivamente algunos colliders cuando se proyecta la cpsula

/a cpsula es definida por las dos esferas con su radio alrededor de point5 y point6, que forman los dos e(tremos de la cpsula. 2on devueltos datos de todos los colliders contra los que nuestra cpsula proyectada choque en esa direcci"n. &ecordemos que esta funci"n no funciona contra colliders configurados como triggers.

S!hereCastAll: static function S!here8ast*ll (origin : "ector# radius : float direction : "ector# distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : 7a%castHit+, static function S!here8ast*ll (ra% : 7a% radius : float distance : float & 3athf(Infinit% la%er3as9 : int & 9Default7a%cast-a%ers) : 7a%castHit+, ?omo physics.2phere?ast, pero devolviendo todos los colliders que colisionen.

Chec5S!here: static function 8hec9S!here (!osition : "ector# radius : float la%er3as9 : int & 9Default7a%cast-a%ers) : boolean

evuelve true si hay alg3n collider tocando la esfera definida por position y radius en coordenadas glo!ales.

Chec5Ca!s+le: static function 8hec98a!sule (start : "ector# end : "ector# radius : float la%ermas9 : int & 9Default7a%cast-a%ers) : boolean

evuelve true si hay alg3n collider tocando la cpsula definida por el eje que va de start a end y que tiene el radio radius, en coordenadas glo!ales.

IgnoreCollision: static function Ignore8ollision (collider. : 8ollider collider1 : 8ollider ignore : boolean & true) : void

)ace que el sistema de detecci"n de colisiones ignore todas las colisiones entre collider5 y collider6. 1sto es muy 3til por ejemplo para que los proyectiles no colisionen con el o!jeto que los dispara.

1sta funci"n tiene algunas limitaciones+ 5.$ 9o es persistente. 1sto significa que el estado de ignorar colisi"n no ser almacenado en el editor cuando se salve la escena. 6.$ 2"lo puedes aplicar esta funci"n a colliders en gameo!jects activos. ?uando se desactiva el collider o el rigid!ody vinculado se pierde el estado de 0gnore?ollision y tendrs que llamar a esta funci"n otra ve'.

IgnoreLa%erCollision: static function Ignore-a%er8ollision (la%er. : int la%er1 : int ignore : boolean & true) : void

)ace que el sistema de detecci"n de colisiones ignore todas las colisiones entre cualquier collider en layer5 y otros en

layer6.

GetIgnoreLa%erCollision: static function GetIgnore-a%er8ollision (la%er. : int la%er1 : int) : boolean

Booleano que indica si las colisiones entre layer5 y layer6 estn siendo ignoradas.

113. ESTRUCTURA )UATERNION

9uestros amigos los quaterniones son usados para representar rotaciones. %nity internamente usa Guaterniones para representar todas las rotaciones. 2in em!argo, los quaterniones estn !asados en n3meros complejos y no son fciles de entender intuitivamente, as que casi nunca accederemos o modificaremos los componentes individuales de un Guaterni"n -(,y,',4.. /o que ser ms ha!itual es que queramos meramente tomar rotaciones ya e(istentes -por ej desde un :ransform. y usarlas para construir nuevas rotaciones -por ej interpolando suavemente entre dos rotaciones.. /as funciones so!re Guaterniones que usaremos el [[d del tiempo -las otras funciones son para usos e("ticos. son Guaternion./oo8&otation, Guaternion.Angle, Guaternion.1uler, Guaternion.2lerp, Guaternion.Mrom:o&otation y Guaternion.identity.

VARIABLES: e+lerAngles: var euler*ngles : "ector#

evuelve la representacion en ngulos euler de la rotacion.

FUNCIONES: ToAngleA)is: function To*ngle*/is (out angle : float out a/is : "ector#): void ?onvierte una rotaci"n en una representaci"n de angle$a(is -ngulo de eje.

SetFromToRotation: function SetFromTo7otation (fromDirection : "ector# toDirection : "ector#) : void

?rea una rotaci"n que rota desde from irection hasta to irection.

ToString: function ToString () : String function ToString (format : String) : String

evuelve un string formateado del Guaternion.

VARIABLES DE CLASE: identit%: static var identit% : $uaternion

2era el equivalente a no rotation. 1l transform quedar perfectamente alineado con el mundo o con los ejes del padre.

FUNCIONES DE CLASE: AngleA)is: static function *ngle*/is (angle : float a/is : "ector#) : $uaternion

?rea una rotaci"n que rota los ngulos que le pasemos como primer parmetro con respecto al eje que le pasamos como segundo. @ sea, para girar nuestro cu!o -previamente eliminadle el character controller que le aadimos el captulo anterior., tecleamos+ transform.rotation D Guaternion.AngleA(is-7E, >ector7.up.C

e esta forma tan simple giramos el cu!o 7E grados so!re el eje ,.

FromToRotation: static function FromTo7otation (fromDirection : "ector# toDirection : "ector#) : $uaternion ?rea una rotaci"n que rota desde el primer parmetro al segundo. 9ormalmente usaremos esta funci"n para rotar un transform uno de cuyos ejes sigue un o!jetivo en una direcci"n en coordenadas glo!ales.

Sler!: static function Sler! (from : $uaternion to : $uaternion t : float) : $uaternion

0nterpola esfriamente del primer al segundo parmetro durante el tercero.

RotateTo.ards: static function 7otateTo)ards (from : $uaternion to : $uaternion ma/DegreesDelta : float) : $uaternion

1fect3a una rotaci"n entre el primer parmetro y el segundo. 1sto es esencialmente lo mismo que Guaternion.2lerp, pero aqu la funci"n se aregura de que la velocidad angular nunca e(ceda de la marcada en ma( egrees elta. 2i ma( egrees elta tiene un valor negativo la rotaci"n es empujada lejos del segundo parmetro -to..

Angle: static function *ngle (a : $uaternion b : $uaternion) : float

evuelve el ngulo en grados entre dos rotaciones dadas. >eamos eso+ var o!jetivo + :ransformC function %pdate -. O var angulo + float D Guaternion.Angle-transform.rotation, o!jetivo.rotation.C e!ug./og-angulo.C P

Arrastramos la esfera a la varia!le e(puesta o!jetivo. 2i pulsamos play, o!servaremos que nos aparece un cero en pantalla, ya que -si teneis am!as figuras colocadas como yo. am!as tienen sus respectivas rotaciones a E,E,E. #ro!ad ahora a cam!iar la rotaci"n de una $o las dos$ figuras.

E+ler: static function 6uler (/ : float % : float 0 : float) : $uaternion static function 6uler (euler : "ector#) : $uaternion evuelve en quaterniones una rotaci"n pasada como parmetro en grados euler.

114. CLASE RANDOM

?lase para generar n3meros aleatorios.

VARIABLES DE CLASE: seed: static var seed : int

?oloca la semilla para el generador de n3meros aleatorios.

2al+e: static var value : float

evuelve un n3mero aleatorio entre E.E -inclusive. y 5.E -inclusive.. for-var (+ int DEC (W5EC (BB.O print-&andom.value.C P

#odris compro!ar que los die' n3meros que nos aparecern en pantalla estn entre am!os valores.

insideUnitS!here: static var inside:nitS!here : "ector#

evuelve un punto aleatorio dentro de una esfera con radio 5. transform.position D &andom.inside%nit2phere Z 6C

1ste ejemplo situara nuestro cu!o en un punto aleatorio dentro de una esfera -7 dimensiones. con un radio de 6 unidades.

insideUnitCircle: static var inside:nit8ircle : "ector1

evuelve un punto aleatorio dentro de un crculo con radio 5. var ne4#osition + >ector6 D &andom.inside%nit?ircle Z KC transform.position.( D ne4#osition.(C transform.position.y D ne4#osition.yC

en este caso nuestro cu!o se movera dentro de un crculo -6 . con radio de K unidades.

onUnitS!here: static var on:nitS!here : "ector# evuelve un punto aleatorio so!re la superficie de una esfera con radio 5. function Mi(ed%pdate-.O rigid!ody.velocity D &andom.on%nit2phere Z 5EC P

1sta funci"n mueve al rigid!ody de nuestro cu!o a una velocidad de 5E en una direcci"n aleatoria, por lo que no esperis ver otra cosa al darle al play que un cu!o volvindose loco.

rotation: static var rotation : $uaternion

evuelve una rotaci"n aleatoria -read only. var prefa! + Fame@!jectC 0nstantiate-prefa!, >ector7.'ero, &andom.rotation.C

1ste ejemplo instanciara un nuevo gameo!ject en el centro de la escena y con una rotaci"n aleatoria.

FUNCIONES DE CLASE: Range: static function 7ange (min : float ma/ : float) : float

evuelve un float aleatorio entre un min -inclusive. y ma( -inclusive.. var prefa! + Fame@!jectC function 2tart -. O var position+ >ector7 D >ector7-&andom.&ange-$K.E, K.E., E, &andom.&ange-$K.E, K.E..C 0nstantiate-prefa!, position, Guaternion.identity.C P

2i arrastramos la esfera a la varia!le e(puesta prefa!, al darle al play o!servaremos que se clona una instancia de la misma y aparece en un lugar aleatorio en un margen de K metros en los ejes I y J. static function 7ange (min : int ma/ : int) : int /a misma funci"n, pero admite y devuelve integers.

115. ESTRUCTURA RAY

1structura que nos permite representar y modificar rayos. %n rayo es una linea infinita que empie'a en un punto dado y va en alguna direcci"n.

VARIABLES: origin: var origin : "ector#

1l punto de origen del rayo.

direction: var direction : "ector#

/a direcci"n del rayo. /a direcci"n es siempre un vector normali'ado-5,E,E o E,5,E o E,E,5. 2i asignamos un vector de longitud distinta de la unidad, ser normali'ado.

FUNCIONES: Ra%: static function 7a% (origin : "ector# direction : "ector#) : 7a%

?rea un rayo que empie'a en origin a lo largo de direction. var ray D ne4 &ay -transform.position, transform.for4ard.C

1n este ejemplo crearamos un rayo que parte de la posici"n del transform al que est vinculado el script y que parte hasta el infinito a travs del eje J.

Get/oint: function Get5oint (distance : float) : "ector# evuelve un punto tantas unidades como le pasemos en el parmetro a lo largo del rayo. var r + &ayC print- r.Fet#oint -5E. .C

1ste ejemplo imprime un punto situado 5E unidades a lo largo del rayo.

ToString: function ToString () : String function ToString (format : String) : String

evuelve un string formateado para este rayo.

11!. ESTRUCTURA RAYCAST&IT

1structura usada para o!tener informaci"n de vuelta de un raycast -rayo proyectado..

VARIABLES: !oint: var !oint : "ector#

1l punto de impacto en coordenadas glo!ales donde el rayo golpea el collider

normal: var normal : "ector#

1l normal de la superficie que golpea el rayo.

"ar%entricCoordinate: var bar%centric8oordinate : "ector#

/a coordenada !aricntrica del tringulo que golpeamos -!aricentro D es un punto de una figura geomtrica la recta que pasa por el cual divide la figura en dos partes iguales. . 1sto nos permite interpolar cualquiera de los datos de los vrtices a lo largo de los tres ejes.

distance: var distance : float

/a distancia desde el origen del rayo hasta el punto de impacto.

triangleInde): var triangleInde/ : int

el ndice del tringulo que ha sido golpeado. 1l ndice del tringulo es s"lo vlido si el colider que lo golpea es un *esh?ollider.

te)t+reCoord: var te/ture8oord : "ector1

/a coordenada de la te(tura %> en el punto de impacto. 1sto puede ser usado para pinturas de te(tura 7d o impactos de !ala di!ujados. 2i el collider no es una mesh collider, retorna un >ector6 a cero.

te)t+reCoord9: var te/ture8oord1 : "ector1

/as coordenadas de la te(tura uv secundaria.

lightma!Coord: var lightma!8oord : "ector1

/a coordinada del lightmap de uv en el punto de impacto.

colider: var collider : 8ollider

1l collider que fue golpeado. 1sta propiedad es nula si no se golpea nada y no$nula si golpeas algo.

rigid"od%: var rigidbod% : 7igidbod%

1l rigid!ody del collider que ha sido golpeado. 2i el collider no est vinculado a un rigid!ody es null.

trans(orm: var transform : Transform

1l :ransform del rigid!ody o collider que ha sido golpeado.

Você também pode gostar