Está en la página 1de 73

1

ndice:
Introduccin .Pg.3 Capitulo 1.1-1.2Pg.4 Capitulo 1.3 Pg.9 Capitulo 1.4 Pg.12 Capitulo 1.5 Pg.15 Capitulo 1.6 Pg.19 Capitulo 1.7 Pg.24 Capitulo 1.8 Pg.27 Capitulo 1.9 Pg.32 Capitulo 1.10 Pg.35 Capitulo 1.11 Pg.38 Capitulo 1.12 Pg.42 Capitulo 1.13 Pg.47 Capitulo 1.14 Pg.52 Capitulo 1.15 Pg.54 Capitulo 1.16 Pg.56 Capitulo 1.17Pg.58 Capitulo 1.18 Pg.62 Capitulo 1.19 Pg.66 Capitulo 1.20 Pg.69

Introduccin
Bienvenidos, me presento. Soy cotolonco, usuario de Taringa. Un da (mediados de Julio/2012) estuve buscando tutoriales Fps de Unity, ya que los que haba eran ejemplos ya hechos o no explicaban casi nada, decid buscar tutoriales en Ingls, ya que en Espaol no hay mucho, y me encontr con ETeeskiTutorial, que ensea lo bsico de Unity, ya sean las transform, Quaternion, la interfaz, javascript bsico, entre otras, y entre eso hay tutoriales de Fps, y explica sencillamente bien, incluso no hay que saber ingls para darse cuenta de las cosas. Empece a ver los tutoriales, y decidi hacerlo pdf primero, para que no se me olvidara, y luego se me ocurrio compartirlo en una comunidad de Taringa en lla que estoy, donde hay bastante gente. Les dejo el canal de Eteeski: http://www.youtube.com/user/ETeeskiTutorials Este documento, en esta primera parte, estarn los videos tutorials FPS1.1 hasta el FPS1.20 Aqu les dejo un video de todo lo que conseguiremos con estos 20 primeros tutoriales: http://www.youtube.com/watch?v=Y4O3BRbEpG4 (Destaco que es una pistola de disparo rpido, solo para ejemplificar y disculpen lo lento del video, iba fluido cuando lo grab). Cada video tutorial tendr su captulo, el cual estar compuesto por el video original en ingls de ETeeski, para verlo online. Una pequea intro de qu se ver en el captulo, los pasos a seguir, los script por parte o completos dependiendo el caso, y una explicacin de este si lo requiere. Resumen por m en espaol, con lo ms importante. Requisitos Antes de Continuar: Conocer la interfaz de Unity. Saber como crear objetos vacis, cubos, crear terrenos, lo que es un GameObject, entre otras. Diferenciar de un Padre, un hijo, en qu afecta, etc. Variables bsicas acerca del transform, position, rotation, quaternion, definir variables, etc. Saber qu es un Tag, un Input, entre otras y como definirlo o modificarlo. Conocimientos bsicos de JavaScript, (Mayor importancia a sentencia if-else) y su estructura.

Cualquier duda antes de continuar, pueden contactarme a: cotolonco@outlook.com coto.kun@gmail.com O tambin a ETeeski, envindole un MP por youtube: http://www.youtube.com/user/ETeeskiTutorials Nota: Hay lneas de cdigo que no se alcanzan a escribir en una lnea del documento.Fjense en eso. Les Recomiendo lean con cuidado, y pregunten.

Captulo 1.1 Visin General


Ver en Ingls: http://www.youtube.com/watch?v=MPN5kYkdYUY&feature=plcp Empezamos con estos captulos en espaol. Bueno bsicamente aqu se habla de lo que se tratar en el Tema, del FPS. Les recomiendo que vean el video. Bueno, ETeeski en cada video dedica su primera parte del video a explicar qe se har y como se har sin usar Unity an. Y la segunda parte del video muestra el proceso en Unity.

Captulo 1.2 Mouse Look Script (Mirar moviendo el ratn)


Ver en Ingls: http://www.youtube.com/watch?v=3JsuldsGuNw&feature=plcp Esto es lo ms primordial en un FPS, destaco anteriormente que si alguna cosa no sale como uno quiso, pueden ser varias razones, pero yo les recuerdo que pueden ser, el valor que toma una variable o alguna lnea o cdigo que posiblemente estuvo mal redactada o el posicionamiento/rotacin de algn GameObject. Vamos a ver 2 cosas aqu, primero como manejar la cmara a travs del mouse y lo segundo como suavizar su movimiento. Empecemos: Antes de comenzar creen un pequeo terreno (A partir de un Plano, Cubo o del Terrain Editor). Agreguen a la Escena Unos 5 cubos, ya sea en el suelo o en el aire y adems agreguen una luz direccional. Renombren los Game Objects como les acomode. Debe quedar ms o menos como se muestra en la imagen:

Seguido de esto, creamos un objeto Vaco (GameObject -> Create Empty). Lo Renombramos como Escenario o Level Stuff(Como se menciona en el video). Luego arrastren todos los cubos que colocaron, incluyendo su terreno dentro de su GameObject Vaco. Esto significar que el GameObject Escenario (En mi caso) Ser Padre de Todos los GameObjects que se hayan arrastrado a este. Por qu se hace esto? Principalmente para ordenarse y adems para decir Si nosotros pisamos al Padre (El Escenario), estamos pisando algn hijo de este. Entonces Ahora podremos saltar (Caso hipottico, no se usa para estos tutoriales). Para saber que algo es padre de GameObject/s basta con que est as:

Ahora Vamos a Project, y creamos una Carpeta llamada Scripts (O como quieran). Pueden Crear dentro de esta carpeta otra carpeta que se llame Player Scripts (En mi caso lo hice as). Crean un Nuevo JavaScript y lo renombran como MouseLook. Antes de proceder a armar el Script, Arrastren el JavaScript al GameObject Cmara o Main Camera por defecto. Creando Script: Para Comenzar crearemos 8 variables: ------------------------------------------------------------------------------------------var lookSensitivity : float=5; var yRotation : float; var xRotation : float; var currentYRotation : float; var currentXRotation : float; var yRotationV:float; var xRotationV:float; var lookSmoothDamp:float=0.1; -------------------------------------------------------------------------------------------

Antes de seguir primero explicar para que se utilizara cada una. lookSensitivity ser la sensibilidad del mouse. En defecto es 5, a mayor sea ms rpido rotar la cmara. xRotation e yRotation son las rotaciones en los ejes Y y X respectivamente. Pero, se preguntarn por qu xRotation representa la rotacin en el eje Y y yRotation la rotacin en el eje X. Es Simple, si ustedes van a los GameObjects y seleccionan la cmara, Vern que en la seccin Transform est su componente la Rotacin, y Si ustedes cambian el valor de X (Representando xRotation), entonces la cmara mirar verticalmente a otro lado. Y con el valor de Y (Representando a yRotation), la camar comenzara a mirar horizontalmente. Las 5 Variables Restantes las explicaremos despus. Ahora vamos a Crear El script: ------------------------------------------------------------------------------------------var lookSensitivity : float=5; var yRotation : float; var xRotation : float; var currentYRotation : float; var currentXRotation : float; var yRotationV:float; var xRotationV:float; var lookSmoothDamp:float=0.1; function Update () { //Mirar con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity; //Movimiento horizontal de la cmara xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cmara //Rotacin final de la cmara transform.rotation=Quaternion.Euler(xRotation, yRotation, 0); } ------------------------------------------------------------------------------------------Antes de seguir explicar lo que es Quaternion.Euler Quaternion es un constructor que representa las rotaciones mucho ms suavizadas y rpidas ya que se involucra con nmeros complejos. Euler es una Funcin Clase o Class Function. Esta Funcin pide 3 parmetros o valores
(x: float,y : float,z: float). Devuelve una rotacin que rota z grados alrededor del eje z, x grados

alrededor del eje x, e y grados alrededor del eje y.(En ese orden) Pueden ver el Script Reference de aqu: http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.Euler.html Lo otro que pueden notar es que xRotation se le va restando y no sumando como a yRotation. Bueno simplemente si modifican y lo dejan de -= a += cuando muevan el cursor hacia arriba la cmara ver hacia abajo y viceversa.

Pueden probar el juego y vern que funciona, pero notarn que los movimientos son un poco bruscos, por lo que las dems variables ayudarn a suavizar el movimiento. Nota: Si agregan arriba de la function Update() este cdigo: ------------------------------------------------------------------------------------------function Awake() { Screen.showCursor=false; } ------------------------------------------------------------------------------------------Podrn esconder el Cursor mientras juegan. Vamos a la segunda parte del script: ------------------------------------------------------------------------------------------var lookSensitivity : float=5; var yRotation : float; var xRotation : float; var currentYRotation : float; var currentXRotation : float; var yRotationV:float; var xRotationV:float; var lookSmoothDamp:float=0.1; function Awake() { Screen.showCursor=false; } function Update () { //Mirar con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity; //Movimiento horizontal de la cmara xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cmara //Mirar con el Mouse ms suavizado: currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp); currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp); //Rotacin final de la cmara

transform.rotation=Quaternion.Euler(currentXRotation, currentYRotation, 0); } ------------------------------------------------------------------------------------------Veamos qu es eso de Mathf.SmoothDamp Es una Class Function (as como colocar Mathf.Cos, que sera el coseno de un nmero) que pide mximo 6 parmetros. En este caso agregamos los 4 primeros. (current : float, target : float, ref currentVelocity : float, smoothTime: float,maxSpeed: float = Mathf.Infinity, deltaTime : float = Time.deltaTime) El Primer parmetro es la posicin actual. El segundo parmetro es la posicin a la que queremos buscar, el Tercer parmetro es la velocidad actual. Y el Cuarto parmetro es el tiempo que tardar en llegar del primer parmetro al tercer parmetro. Pueden ver el Script Reference aqu: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.SmoothDamp.html Por lo tanto, queremos llegar de la rotacin xRotation, yRotation a la rotacin currentXRotation, currentYRotation, en un tiempo determinado por lookSmoothDamp. Ahora surge un ltimo problema que si lo pueden notar si mueven el cursor del mouse hacia arriba a cada momento, la cmara comenzar a rotar sobre s mismo, como si fuera una rueda. Por si no se entiende pueden apreciarlo en este video de ETeeski en el minuto 25:00. http://www.youtube.com/watch?v=3JsuldsGuNw&feature=plcp Para Arreglar esto, terminaremos el Script quedando finalmente as: ------------------------------------------------------------------------------------------var lookSensitivity : float=5; var yRotation : float; var xRotation : float; var currentYRotation : float; var currentXRotation : float; var yRotationV:float; var xRotationV:float; var lookSmoothDamp:float=0.1; function Awake() { Screen.showCursor=false; } function Update ()

{ //Mirar con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity; //Movimiento horizontal de la cmara xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cmara xRotation=Mathf.Clamp(xRotation,-90,90); //Mirar con el Mouse ms suavizado: currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp); currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp); //Rotacin final de la cmara transform.rotation=Quaternion.Euler(currentXRotation, currentYRotation, 0); } ------------------------------------------------------------------------------------------Para finalizar, explicar que es Mathf.Clamp Es una Class Function que pide 3 parmetros: el valor, el mnimo, el mximo. La funcin devuelve un valor que est entre el mnimo y el mximo (Incluyndolos). Pueden ver el Script Reference Aqu: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Clamp.html Ahora prueben y ver que funciona perfectamente.

Captulo 1.3 Caminar/Correr bsicamente


Ver en Ingls: http://www.youtube.com/watch?v=5pkeRlpjFzQ&feature=plcp Quiero aclarar antes de iniciar el captulo que no es correr presionando shift, o caminar lentamente presionando shift, si no que tu movimiento natural es una aceleracin, por lo que si ms rato mantienes mantenido WASD o las flechas del teclado, cada vez aumentars ms la velocidad. Sabiendo esto comencemos: Antes de comenzar con los Script. Agreguen a la Escena una cpsula y llmenla PlayerCapsule y arrastren la Cmara, de tal manera que sea hijo de la cpsula. Cuando hayan arrastrado la cmara. Ubiquen su posicin (x,y,z) en (0,0.7,0). Como se muestra en la imagen:

10

Ahora seleccionen al PlayerCapsule, vayan a Component -> Physics -> Rigidbody. Para aadirle un rigidbody al PlayerCapsule. Antes de seguir, como ahora a nuestro jugador le afectan las fsicas. No queremos que se caiga como un Pin de los juegos de Bolos. Por lo tanto agregamos esto:

As estar siempre de pie. Ahora si podremos continuar. Creen un nuevo JavaScript y llmenlo PlayerMovement (Arrstrenlo al PlayerCapsule). Dentro del Script crearemos 2 variables. ------------------------------------------------------------------------------------------var walkAcceleration: float=5; var cameraObject:GameObject; function Update () { transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); } ------------------------------------------------------------------------------------------Ya sabemos que es Quaternion.Euler, Primero definiremos cual es el GameObject. Cuando guarden el Script, arrastren el GameObject cmara al cameraObject del script del PlayerCapsule, para que pueda funcionar, ya que la variable cameraObject es de tipo GameObject. De tal forma que quede as:

11

Ahora explicar qu significa ese parmetro que le dimos cameraObject.GetComponent(MouseLook).currentYRotation. Primero ingresamos al cameraObject qu es un GameObject (En este caso la cmara que arrastramos), Ingresamos al Script MouseLook y obtenemos el valor de currentYRotation. As el Player mirar hacia donde mira la cmara. As no tendremos algn problema al caminar. (Si prueban el juego ahora no notarn mucha diferencia). Ahora vamos al Script final: ------------------------------------------------------------------------------------------var walkAcceleration: float=5; var cameraObject:GameObject; function Update () { //Rotar Hacia donde ve la cmara transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); //Aade una Fuerza Relativa rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccelerati on); } ------------------------------------------------------------------------------------------Expliquemos qu es rigidbody.AddRelativeForce. Para empezar solo puede ser usado por un GameObject que posea un rigidbody. Adems es una funcin que recibi 3 parmetros. El primero, le aade una fuerza relativa a travs del eje x. El segundo, a travs del eje y. Y finalmente el tercero a travs del eje z. Aqu el Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody.AddRelativeForce.html Si probamos el juego, y presionamos W o algn otro botn, notaremos que ir lento al principio y comenzar a aumentar su velocidad. Si cambian walkAcceleration a 10 ir ms rpido pero si sueltan el botn el Playercapsule se deslizar. En el prximo captulo veremos como arreglarlo.

12

Captulo 1.4 Estableciendo una velocidad mxima


Ver en Ingls: http://www.youtube.com/watch?v=GddQmaFLZ00&feature=plcp En este tutorial, importaremos una textura para colocarla en nuestro terreno y aprenderemos a limitar la velocidad de nuestro jugador. Comencemos:

Agranden su terreno de suelo (En mi caso el Scale de mi suelo es 200, 1,200). Creen una carpeta que se llame Materiales (Opcional). Busquen una textura, para el suelo. Yo usar una de piedra como ETeeski, esta de aqu:

13

Dentro de la carpeta creada Materiales, creen un Material (Renmbrenlo como TexturaPiedra). Luego Arrastren la imagen a Unity, y colquenla la imagen en el Material (TexturaPiedra). Y ste Material Arrstrenlo a su GameObject Suelo. Para que no sea una imagen super larga de la textura Pierda, cambien el Tiling del Material.

Obviamente luego de esto, tendran que ver la textura en el suelo repetidamente. O donde lo hayan colocado, en la Escena y en el Juego. Abrimos nuestro script anterior PlayerMovement. Y lo Editamos por esto: ------------------------------------------------------------------------------------------var walkAcceleration: float=5; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; function Update () { horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z); if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; //Rotar Hacia donde ve la cmara transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); //Aade una Fuerza Relativa rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAcceleration); } ------------------------------------------------------------------------------------------Vamos explicando, primero agregamos una variable llamada maxWalkSpeed, que ser la velocidad mxima del PlayerCapsule. Adems agregamos una variable llamada horizontalMovement, que es un Vector2. Por lo tanto podr guardar 2 variables. Y podremos descomponerlo en horizontalMovement.x y horizontalMovement.y. @HideInInspector, como dice su nombre simplemente esconde la variable de abajo en el inspector. Sigamos analizando el Script: A horizontalMovement le entregaremos 2 variables. La rigidbody.velocity.x y rigidbody.velocity.z que son la velocidad en x y en z del rigidbody (la velocidad en y sera saltando). Recuerden que la velocidad es un vector. Por lo tanto, luego nos preguntamos si la magnitud del horizontalMovement (La magnitud es la rapidez resultante) es mayor a la maxWalkSpeed. Si eso es cierto ocurren 2 cosas: Primero con horizontalMovement.normalized cambiamos la magnitud del vector por 1, manteniendo su direccin.

14

Script Reference aqu: http://docs.unity3d.com/Documentation/ScriptReference/Vector2-normalized.html Segundo Le multiplicamos por maxWalkSpeed para entregarle el lmite de la velocidad. Pero con eso no se soluciona el problema. As que debemos entregarle un nuevo valor a las velocidades en x y z del rigidbody. rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; Si prueban el juego podrn notar que en un momento no aumenta la velocidad. Pueden cambiar el valor de maxWalkSpeed a 10 y notarn ms el resultado.

15

Captulo 1.5 Saltando de Manera Correcta


Ver en Ingls: http://www.youtube.com/watch?v=eSnzuRgrN_8&feature=plcp Tal como dice el ttulo, veremos como saltar de manera correcta. Adems de que podr saltar cuando el vector normal que se genera entre el jugador y lo que pisas forma algn ngulo que sea menor al mximo (tampoco podrs saltar si chocaste con la cabeza un objeto, tambin sirve). Reabrimos nuestro Script PlayerMovement y lo editamos de tal forma que quede as: ------------------------------------------------------------------------------------------//Variables Movimiento: var walkAcceleration: float=10; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; //Variables Salto: var jumpVelocity: float=20; @HideInInspector var grounded:boolean=false; var maxSlope:float=60; function Update () { //Movimiento: horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z);

if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccel eration); //Salto: if (Input.GetButtonDown("Jump")) rigidbody.AddForce(0,jumpVelocity,0); } ------------------------------------------------------------------------------------------Primero notemos las nuevas 3 variables jumpVelocity, grounded, maxSlope. jumpVelocity, representa la velocidad con la que salta (Velocidad del eje y), grounded indicar si est habilitado para saltar. Y finalmente maxSlope, indica el ngulo en grados para limitarnos el tipo de inclinacin podremos subir. Luego se agreg 2 lneas. La primera Input.GetButtonDown regresa verdadero si el botn fue presionado (solo con una vez basta, no mantenido). Y Jump es el botn space por defecto definido en el apartado (Edit->ProjectSetting->Input). Y si presionamos space entonces, le aplicamos una fuerza hacia arriba. Si presionan space, en el juego tal vez vean que no salta mucho. Eso es porque, jumpvelocity es muy bajo, aumntenlo a 300 o 400 para fijarse mejor. Claro que hasta ahora podremos saltar incluso en el aire. Antes de seguir creen un cubo y transfrmenlo en rampa, y arrstrelo al GameObject Escenario (Opcional). Pueden copiar los datos de esta imagen:

16

Si se fijan la rotacin en z es 315, es decir que se forma un ngulo de 45. Ahora modificamos el Script, para que finalmente quede as: ------------------------------------------------------------------------------------------//Variables Movimiento: var walkAcceleration: float=10; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; //Variables Salto: var jumpVelocity: float=20; @HideInInspector var grounded:boolean=false; var maxSlope:float=60; function Update () { //Movimiento: horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z); if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccel eration); //Salto: if (Input.GetButtonDown("Jump") && grounded) rigidbody.AddForce(0,jumpVelocity,0); } function OnCollisionStay(collision:Collision) { for (var contact:ContactPoint in collision.contacts)

17

{ if (Vector3.Angle(contact.normal, Vector3.up)<maxSlope) grounded=true; } } function OnCollisionExit() { grounded=false; } ------------------------------------------------------------------------------------------Ahora veamos, primero modificamos esta parte: if (Input.GetButtonDown("Jump") && grounded), porque ahora nos preguntamos si est grounded o no. Que significa si podr saltar. Luego de esto, agregamos 2 nuevas funciones OnCollisionStay y OnCollisionExit. OnCollisionStay se ejecuta cada frame cada vez que nosotros estemos en colisin con un collider o rigidbody. Y OnCollisionExit se ejecuta en el instante que dejemos de colisionar con el collider o rigidbody. El parmetro collision que se le da a OnCollisionStay, recibe informacin del collider/rigidbody con el cual est colisionando. Luego llamamos esta extraa parte: for (var contact : ContactPoint in collision.contacts) Que simplemente significa: para los puntos de contacto (var contact:ContactPoint) con el collider/rigidbody (collision.contacts), el cual almacena el punto de contacto, una normal, y los collider que colisionan. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Collision-contacts.html La lnea siguiente: if (Vector3.Angle(contact.normal, Vector3.up)<maxSlope) Nos preguntamos si el ngulo (Vector3.Angle) formado desde el vector normal que se forma entre ambos collider y el Vector (0,1,0) es menor al maxSlope. As sabremos si realmente podremos saltar dependiendo de la inclinacin de la rampa en grados. Por lo tanto si es cierto, grounded=true. Luego OnCollisionExit nos indicar que ya dej de colisionar y por lo tanto ya no podremos saltar, haciendo grounded=false. Ahora si intentan saltar, lo podrn hacer sin problemas. Pero si colocan una pared y saltan al lado de esta, se estancarn. Esto se resolver en el Captulo 1.7.

18

19

Captulo 1.6 Aadiendo Friccin al Movimiento


Ver en Ingls: http://www.youtube.com/watch?v=SUKddKIgCUQ&feature=plcp Si ustedes habrn notado. Nuestro jugador al soltar las teclas de movimiento sigue deslizndose hasta detenerse y toma bastante tiempo. Por lo tanto lo que haremos en este captulo ser suavizar el movimiento hasta detener al jugador. Para hacer eso abrimos nuestro script PlayerMovement y lo modificamos: ------------------------------------------------------------------------------------------//Variables Movimiento: var walkAcceleration: float=10; var walkDeacceleration: float=5; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; //Variables Salto: var jumpVelocity: float=20; @HideInInspector var grounded:boolean=false; var maxSlope:float=60; function Update () { //Movimiento: horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z); if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; if (Input.GetAxis("Horizontal")==0 && Input.GetAxis("Vertical")==0 && grounded) { rigidbody.velocity.x /=walkDeacceleration; rigidbody.velocity.z /=walkDeacceleration; }

transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccel eration); //Salto: if (Input.GetButtonDown("Jump") && grounded) rigidbody.AddForce(0,jumpVelocity,0); } function OnCollisionStay(collision:Collision) { for (var contact:ContactPoint in collision.contacts) { if (Vector3.Angle(contact.normal, Vector3.up)<maxSlope) grounded=true; } } function OnCollisionExit() { grounded=false; } ------------------------------------------------------------------------------------------Ya ha quedado un poco largo el Script, pero si se fijan bien. Agregamos una nueva variable llamada walkDeacceleration (Por defecto 5) y se agreg 2 nuevas lneas: if (Input.GetAxis("Horizontal")==0 && Input.GetAxis("Vertical")==0 && grounded) { rigidbody.velocity.x /=walkDeacceleration; rigidbody.velocity.z /=walkDeacceleration; } Qu significa que el Input.GetAxis(Horizontal)==0? Eso es equivalente a preguntarse si no se est presionando el botn. Es decir si no se est apretando ni WASD, ni las flechas (Que vienen por defecto en el Axis Horizontal y Vertical). Entonces las velocidades x e y se iran reduciendo, en este caso dividiendo hasta llegar a 0, si es que adems est tocando suelo. Si ustedes prueban se darn cuenta que el jugador frena casi de golpe. Para suavizarlo un poco bajen el valor de walkDeacceleration a 1.05 o 1.1.

20

21 Qu tal si suavizamos ms el movimiento? Antes de saber cmo, as queda el Script. ------------------------------------------------------------------------------------------//Variables Movimiento: var walkAcceleration: float=10; var walkDeacceleration: float=5; @HideInInspector var walkDeaccelerationVolx:float; @HideInInspector var walkDeaccelerationVolz:float; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; //Variables Salto: var jumpVelocity: float=20; @HideInInspector var grounded:boolean=false; var maxSlope:float=60; function Update () { //Movimiento: horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z); if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; if (Input.GetAxis("Horizontal")==0 && Input.GetAxis("Vertical")==0 && grounded) { rigidbody.velocity.x = Mathf.SmoothDamp(rigidbody.velocity.x,0,walkDeaccelerationVolx, walkDeacceleration); rigidbody.velocity.z =Mathf.SmoothDamp(rigidbody.velocity.z,0,walkDeaccelerationVolz, walkDeacceleration); }

transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccel eration); //Salto: if (Input.GetButtonDown("Jump") && grounded) rigidbody.AddForce(0,jumpVelocity,0); } function OnCollisionStay(collision:Collision) { for (var contact:ContactPoint in collision.contacts) { if (Vector3.Angle(contact.normal, Vector3.up)<maxSlope) grounded=true; } } function OnCollisionExit() { grounded=false; } ------------------------------------------------------------------------------------------Recuerdan esta funcin Mathf.SmoothDamp? Si no recuerdan, fue usada en el Script MouseLook, para suavizar el movimiento de la rotacin de la cmara. Por lo tanto se hizo lo mismo para suavizar la friccin del jugador al detenerse. Se agregaron de la misma forma walkDeaccelerationVolx y walkDeaccelerationVolz. Si no recuerdan la funcin. Har esto: En el caso de rigidbody.velocity.x, modificar la velocidad de la rigidbody.velocity.x actual hasta la velocidad 0, con una velocidad actual de 0 (walkDeaccelerationVolx, Preferible no modificar) en un tiempo determinado por walkDeacceleration. As que ahora podemos modificar el valor de walkDeacceleration a 0.5 y veremos que queda bien suavizado. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.SmoothDamp.html

22

Nota: Pueden modificar esta parte del Script. rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration,0,Input.GetAxis("Vertical")*walkAccelerati on); Por esta: rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration *Time.deltaTime,0,Input.GetAxis("Vertical")*walkAcceleration*Time.deltaTime); Esto har ms suavizado el caminar. Pero tendrn que aumentar walkAcceleration a 500 o 1000, o algo parecido.

23

24

Captulo 1.7 Control del Aire y Pegarse a las Paredes Limitado


Ver en Ingls: http://www.youtube.com/watch?v=1Ptl4V4Zwy0&feature=plcp Control del Aire significa que al saltar, podremos movernos ms lento que en el suelo, y al chocar con las paredes, nos iremos deslizando hasta llegar al suelo, dependiendo de su inclinacin. Antes de comenzar vamos a cambiar nuestra Escena y le agregaremos una especie de escalera hecha con cubos, de esta forma:

Prueba subir con una walkAcceleration de 1000 o 1500. Vers que costar subir. Ya que vas chocando con cada cubo. Por lo tanto debes hacer este pequeo truco: Haz click en cada escaln colocado, excepto el ltimo (El grande), y donde dice Is Trigger, marca la casilla. De tal modo que puedas traspasar los cubos. Acto seguido crea otro cubo y llmalo RampaEscalera o como quieras. Y ubcalo de tal forma que te quede como si subieras entre el primer escaln y el ltimo, como se muestra en esta imagen:

25

Ahora intenta subir la escalera, y vers que es sin problemas. Claro que si bajas el valor del walkAcceleration. No podrs poder subirla totalmente. Por lo tanto si sucede, debes aumentar el valor. Volviendo al Script, para saber cmo controlarte en el aire y no pegarte a las paredes. Abre tu Script PlayerMovement. Y edtalo por esto: ------------------------------------------------------------------------------------------//Variables Movimiento: var walkAcceleration: float=10; var walkAccelAirRatio:float=0.1; var walkDeacceleration: float=5; @HideInInspector var walkDeaccelerationVolx:float; @HideInInspector var walkDeaccelerationVolz:float; var cameraObject:GameObject; var maxWalkSpeed: float=20; @HideInInspector var horizontalMovement:Vector2; //Variables Salto: var jumpVelocity: float=20; @HideInInspector var grounded:boolean=false; var maxSlope:float=60;

function Update () { //Movimiento: horizontalMovement=Vector2(rigidbody.velocity.x,rigidbody.velocity.z); if (horizontalMovement.magnitude>maxWalkSpeed) { horizontalMovement=horizontalMovement.normalized; horizontalMovement*=maxWalkSpeed; } rigidbody.velocity.x=horizontalMovement.x; rigidbody.velocity.z=horizontalMovement.y; if (grounded) { rigidbody.velocity.x = Mathf.SmoothDamp(rigidbody.velocity.x,0,walkDeaccelerationVolx, walkDeacceleration); rigidbody.velocity.z =Mathf.SmoothDamp(rigidbody.velocity.z,0,walkDeaccelerationVolz, walkDeacceleration); } transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0); if (grounded) rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration *Time.deltaTime,0,Input.GetAxis("Vertical")*walkAcceleration*Time.deltaTime); else rigidbody.AddRelativeForce(Input.GetAxis("Horizontal")*walkAcceleration*walkAccelAirRatio *Time.deltaTime,0,Input.GetAxis("Vertical")*walkAcceleration*walkAccelAirRatio*Time.deltaTime); //Salto: if (Input.GetButtonDown("Jump") && grounded) rigidbody.AddForce(0,jumpVelocity,0); } function OnCollisionStay(collision:Collision) { for (var contact:ContactPoint in collision.contacts) { if (Vector3.Angle(contact.normal, Vector3.up)<maxSlope) grounded=true; } }

26

function OnCollisionExit() { grounded=false; } ------------------------------------------------------------------------------------------Se hizo 3 pasos en este Script. El primer paso es declarar una variable llamada walkAccelAirRatio. Lo que har esta variable ser controlar el movimiento del aire del jugador, as no dar grandes saltos largos. Si no de menor tamao. En el segundo paso se edit esta parte: if (Input.GetAxis("Horizontal")==0 && Input.GetAxis("Vertical")==0 && grounded) Por esta: If (grounded) Ya que solo nos queremos preguntar si est en el suelo o no. El tercer paso, es editar la parte de movimiento. Si est en el suelo se mover normal, de caso contrario (sentencia ifelse), se mover ms lento, determinado por un valor pequeo de walkAccelAirRatio.

27

Captulo 1.8 Arma bsica con Peso


Ver en Ingls: http://www.youtube.com/watch?v=ay2SMb9-nEE&feature=plcp En este captulo veremos como aadir un arma, y rotarla dependiendo de donde est la cmara. Antes de empezar, pueden descargar este modelo de brazo y pistola que dejo en el link: http://www.mediafire.com/?ecj1616z0qazhh5 pass: cotolonco Pueden usar su propio modelo pero yo usar el que hice a la rpida. (Si se fijan las texturas no estn ordenadamente diseadas). Primero, descomprimimos el .rar, y obtendremos 3 archivos. Habr un archivo .fbx que trae el modelo. Y 2 texturas: de la pistola y del brazo.

Ahora nos vamos a Unity, y creamos una carpeta llamada Modelos. Luego arrastran estos 3 archivos a la carpeta. Se les tendra que ver as:

28

Vamos a arrastrar la textura Arma1 y Brazo1 a la carpeta Materials. Ahora coloquen la textura Arma1.png al material Arma1, (si es que no la posee) y coloquen la textura Brazo1.png en el material ArmaBrazo1-Material. Obtendrn esto como resultado:

Ahora para terminar vamos y hacemos un click en ArmaBrazo1 y cambiamos su Scale Factor por 0.5. O si no se ver muy pequeo.

29

Y ahora podemos comenzar. Hagan click en el GameObject cmara, y luego vayan a GameObject-> Create Empty y nmbrenlo como Gun (Esto se hace para que Gun est exactamente donde esta el GameObject camara). Arrastren el Armabrazo1 al GameObject Gun. Borren Lamp y Camera del GameObject ArmaBrazo1. Y coloquen estos datos al GameObject, para ubicarlo bien en la cmara.

Lo ideal es que se vea como en Game. Si no funcionan esos valores intenten modificarlos. Ahora si comenzamos con el script. Creen un nuevo JavaScript y renmbrenlo como GunScript. Abran el JavaScript y empezaremos definiendo una variable de tipo GameObject ------------------------------------------------------------------------------------------var cameraObject : GameObject; ------------------------------------------------------------------------------------------Arrastramos el script al GameObject Gun. Y donde diga Camera Object None(Game Object). Arrastraremos la cmara.

30

Ahora crearemos 7 variables ms. De las cuales ya ms o menos sabrn, para que sern. ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5;

var holdSide : float = 0.5; ------------------------------------------------------------------------------------------Como ya dijimos @HideInInspector esconde la variable de abajo, para que no aparezca en el Inspector. Las variables targetXRotation, targetYRotation, targetXRotationV, targetYRotationV y rotateSpeed, si pudieron notarlo estas variables sern usadas con la funcin Mathf.SmoothDamp, para suavizar el movimiento. Las otras 2 variables, es para ubicar el arma ms a la derecha o izquierda (holdSide), o hacia arriba o abajo (holdHeight). Para la posicin original, que en este caso ya definimos nosotros la dejaremos en 0. Ahora terminemos de armar el Script: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; function Update () { //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide,holdHeight,0); targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetX RotationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetY RotationV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } -------------------------------------------------------------------------------------------

31

La primera lnea estamos estableciendo que a cada frame del juego la posicin del arma transform.position, est en el 32 centro de la cmara, ms como ya dijimos un poco a la derecha/izquierda o arriba/abajo establecido por lo que sigue del signo positivo. Las siguientes 2 lneas donde se define targetXRotation y targetYRotation, si lo notaron se usa un movimiento suavizado desde su ultima rotacin targetXRotation/ targetYRotation hasta la rotacin obviamente de la cmara xRotation/yRotation, con una velocidad targetXRotationV/targetYRotationV en un tiempo determinado por rotateSpeed. Si pruebas el juego ahora, y le cambias las variables a holdHeight y holdSide, notars que el arma se desplazar. Adems si rotas la vista, te dars cuenta que el arma con el brazo giran junto con la cmara. Pero en ocasiones la el arma con el brazo desaparecen de la cmara, porque tardan en llegar. Para arreglar esto, cambiaremos el valor de rotateSpeed por 0.1 y a probar! Ahora est quedando bien.

Captulo 1.9 Apuntando (Aiming)


Ver en Ingls: http://www.youtube.com/watch?v=_YhahZPE9Mg&feature=plcp En este captulo realizaremos un cambio de posicin del arma, de manera suavizada y rpida. En unas lneas ms adelante explico un pequeo error, eso es porque cuando importen el arma y situen, debe estar como en el segundo cuadro de la imagen y no como el primero (como nosotros lo hicimos): Lo que queremos conseguir aqu es que al tener click derecho presionado pase esto:

A nuestro script anterior GunScript, hay que aadirle unas 3 variables. Volveremos a usar Mathf.SmoothDamp. Pero Antes de continuar, vamos a modificar ciertas cosas del arma. Ya que hay un pequeo error que cometimos. (Al explicar el script entendern por qu). Vamos a modificar esto del GameObject ArmaBrazo1 (hijo del GameObject Gun).

33

Si logran notarlo el arma qued en el medio del GameObject camara, como se muestra en el Segundo cuadro de la imagen anterior a esta. Ahora a holdHeight y holdSide ya no sern 0, ya que de ser as el script siguiente no tendr efecto.

Ahora vamos al script y me dispondr a explicar: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector

var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; function Update () { if (Input.GetButton("Fire2")) racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); if (Input.GetButton("Fire2")==false) racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed);

34

//Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0);

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } ------------------------------------------------------------------------------------------Como dijimos agregamos 3 variables racioHipHold, hiptoAimSpeed y racioHipHoldV. La ltima solo ser usada para la funcin Mathf.SmoothDamp, as que no hay que explicarla. Ahora, hay 2 if en cuanto al Input.GetButton(Fire2), recuerden que Fire2 es el click derecho del ratn. El primer if es cuando la sentencia si se cumple, es decir cuando estamos presionando click derecho, en ese caso racioHipHold tomar un valor de 0 en un tiempo definido por hiptoAimSpeed. De caso contrario, raciohipHold tomar un valor de 1, en el tiempo definido por hiptoAimSpeed. Vamos a la ltima lnea modificada:

transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0); Vamos a tomar en cuenta solo una parte de la lnea, esta: Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0) Como ya dijimos racioHipHold solo toma valores entre 0 y 1. Cuando presionamos click derecho del ratn, este valor es 0, qu implica esto. Que el Vector3 tendr coordenadas (0, 0, 0), de este modo el arma estar posicionado en el centro (con los valores que definimos en la primera imagen de este captulo). De caso contrario cuando se suelta, racioHipHold, tomara un valor de 1, en este caso el Vector3 tendr un valor de (holdSide, holdHeight, 0), esto significa que cuando no haces click, el arma estar desplazada a la derecha (por los valores que definimos). Prueben el juego y mantengan presionado el botn derecho del ratn y notarn que est quedando muy bien. Si no es as, es que hay algn problema, con variables o alguna lnea mal escrita.

35

Captulo 1.10 Sensibilidad del arma al apuntar (Gun Aim Sensitivity)


Ver en Ingls: http://www.youtube.com/watch?v=T8G3uXSAZ3g&feature=plcp En este captulo se ver como colocar cierta sensibilidad cuando nosotros estemos apuntando (manteniendo presionado click derecho del ratn), es decir, cuando apuntemos ir ms lenta lla cmara que cuando no. Si pudieron deducirlo, se habrn dado cuenta que hay que modificar 2 scripts, MouseLook y GunScript. Vamos a modificar el script MouseLook, branlo y coloquen lo siguiente: ------------------------------------------------------------------------------------------var lookSensitivity: float=5; @HideInInspector var yRotation: float; @HideInInspector var xRotation: float; @HideInInspector var currentYRotation:float; @HideInInspector var currentXRotation:float; @HideInInspector

var yRotationV:float; @HideInInspector var xRotationV:float; var lookSmoothDamp:float=0.1; var currentAimRacio : float=1; function Awake() { Screen.showCursor=false;// Esconder cursor } function Update () { //Mirar Con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity * currentAimRacio; xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity * currentAimRacio; xRotation=Mathf.Clamp(xRotation,-90,90); //Mirar Con el Mouse Ms suavizado: currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp); currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp); //hacia donde mira: transform.rotation=Quaternion.Euler(currentXRotation,currentYRotation,0); } ------------------------------------------------------------------------------------------Solamente se agreg una variable, currentAimRacio. Esta variable si analizamos las lneas donde estn yRotation y xRotation nos daremos cuenta que mientras ms grande el nmero, ms rpido rotar la cmara. Ya sabiendo esto, ahora abrimos nuestro script GunScript y lo modificamos. ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector

36

var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; function Update () { if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0);

37

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,tar getXRotationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,tar getYRotationV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } -------------------------------------------------------------------------------------------

Ahora notaremos otra variable aimRacio, la cual nos dir que al mantener presionado click derecho, la variable currentAimRacio del Script MouseLook ser igual a la variable aimRacio. En el caso que no se haga un click, volver a la normalidad, en donde currentAimRacio ser 1. Vamos a probar y vern que si mueven el mouse la cmara rotar como siempre, pero al mantener presionado el bton derecho del ratn (apuntando), y al mover el mouse se mover ms lentamente la cmara.

38

Captulo 1.11 Zoom de la Cmara


Ver en Ingls: http://www.youtube.com/watch?v=0DWC-1Qb_2Y&feature=plcp Tal como dice el ttulo de este Captulo, veremos cmo hacer un zoom de la cmara, cuando nuestra arma est apuntando (cuando mantenemos presionado click derecho). Tal como muestra esta imagen:

Como es de esperarse nuevamente tendremos que modificar el Script MouseLook y el Script GunScript. Empezamos abriendo el script MouseLook para editarlo: ------------------------------------------------------------------------------------------var defaultCameraAngle : float=60; var currentTargetCameraAngle : float=60; var racioZoom : float=1; var racioZoomV : float; var racioZoomSpeed : float=0.2; var lookSensitivity: float=5; @HideInInspector var yRotation: float; @HideInInspector var xRotation: float; @HideInInspector

var currentYRotation:float; @HideInInspector var currentXRotation:float; @HideInInspector var yRotationV:float; @HideInInspector var xRotationV:float; var lookSmoothDamp:float=0.1; var currentAimRacio : float=1; function Awake() { Screen.showCursor=false;// Esconder cursor } function Update () { if (currentAimRacio == 1) racioZoom=Mathf.SmoothDamp(racioZoom, 1, racioZoomV, racioZoomSpeed); else racioZoom=Mathf.SmoothDamp(racioZoom, 0, racioZoomV, racioZoomSpeed); camera.fieldOfView = Mathf.Lerp(currentTargetCameraAngle, defaultCameraAngle, racioZoom); //Mirar Con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity * currentAimRacio; xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity * currentAimRacio; xRotation=Mathf.Clamp(xRotation,-90,90); //Mirar Con el Mouse Ms suavizado: currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp); currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp); //hacia donde mira: transform.rotation=Quaternion.Euler(currentXRotation,currentYRotation,0); } -------------------------------------------------------------------------------------------

39

Creamos 5 nuevas variables. Las 3 ltimas, racioZoom, racioZoomV y racioZoomSpeed sern usadas, para la funcin 40 Mathf.SmoothDamp. Las 2 primeras variables, currentTargetCameraAngle y defaultCameraAngle definirn el ngulo de la cmara apuntando, y el ngulo por default de la cmara. La primera sentencia nos pregunta si currentAimRacio es 1, es decir, cuando NO estamos presionando click derecho. Entonces racioZoom ser 1 en un tiempo determinado por racioZoomSpeed. De caso contrario ser 0. Antes de ver la funcin, analicemos la variable camera.fieldOfView. Esta variable es el campo de visin de la cmara en grados. A menor grado, ms zoom obtendrs y viceversa. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Camera-fieldOfView.html Vamos a la nueva funcin Mathf.Lerp, para entender mejor la situacin: Esta es una funcin, que pide 3 valores (from:float, to:float, t:float). Al entregrselas, Mathf.Lerp Interpola entre el valor from y el valor to (Recuerden que interpolar, bsicamente es generar otros puntos, a partir de estos 2 puntos). Para terminar, el valor t, no es de tiempo. Es un valor que est entre 0 y 1, Por lo tanto si t es 0 corresponde al valor from y si t es 1 corresponder al valor to. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Lerp.html Volviendo a nuestro caso, entonces cuando NO presionamos click derecho, currentAimRacio ser igual a 1, por lo tanto el valor de racioZoom, luego de ser suavizado por la funcin Mathf.SmoothDamp ser 1, esto implica que en la funcin Mathf.Lerp elegir a la variable defaultCameraAngle dejando a camera.fieldOfView igual a 60, es decir con su ngulo original. De caso contrario si presionamos click derecho, como racioZoom ahora ser 0, camera.fieldOfView ser igual a currentTargetCameraAngle. Pero si se fijan este valor tambin es 60, entonces Cmo le decimos que sea 30 por ejemplo? La respuesta es simple, nosotros le diremos el ngulo a travs del Script GunScript. Abramos este Script y lo editaremos: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float;

@HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; function Update () { cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0); targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,tar getXRotationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,tar getYRotationV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } -------------------------------------------------------------------------------------------

41

Agregamos una nueva variable zoomAngle que nos dar el nuevo ngulo de la cmara. Y la siguiente lnea le decimos que el currentTargetCameraAngle sea igual al zoomAngle. Cabe notar que no es necesario, meter esta lnea dentro de un if, ya que Mathf.Lerp, se encarga de elegir si el ngulo es 30, 60, o algn valor entre esos 2. Probemos el juego y s! Efectivamente tiene un zoom.

42

Captulo 1.12 Estableciendo la Frecuencia de Disparo (Fire Rate)


Ver en Ingles: http://www.youtube.com/watch?v=VkNUDn7rdPY&feature=plcp Empezar definiendo Fire Rate. Fire Rate es la frecuencia en la cual el arma puede disparar. Esta frecuencia est determinada por Disparos/segundos, Disparos/Minutos, etc. Por ejemplo: Encuentro una pistola en el suelo y disparo, y cada 2 segundos puedo disparar, entonces la frecuencia sera 30 Disparos/Minuto. Antes de comenzar a crear el Script. Tenemos que crear una bala. As que ser una bala de prueba. Por lo tanto, creen un cubo, renmbrenlo como Test Bullet, y modifiquen estos datos determinados por la lnea roja:

Acto Seguido. Creen una carpeta llamada Prefabs. Ahora dentro de esta carpeta creen un prefab y renmbrenlo como bullet. Ahora arrastren el GameObject Test Bullet a este prefab (Para saber que si lo arrastraron, hagan click en el prefab y vern todos los datos del cubo).

43

Ahora borren el GameObject Test Bullet que tenemos en la Escena, ya que tenemos el prefab de este. Creen un Objeto Vaco, y renmbrenlo como bullet spawn. Arrstrenlo al GameObject Pistola (que es hijo de ArmaBrazo1). Luego coloquen su coordenada de Position en (0, 0, 0). Y ahora arrastren el GameObject bullet spawn, hasta que quede en la salida de disparo del arma.

Para asegurarse, prueben el juego, y vean la vista Escena y noten que efectivamente rota con el arma y que el vector azul, este siempre alineado con el arma y la salida del arma. Armemos el Script. Abramos nuestro Script GunScript. Y vamos a crear 4 variables ms (la bala, donde aprece la bala, el tiempo para volver a disparar y la rapidez con que el tiempo para volver a disparar disminuye). Antes de mostrar el Script, solamente voy a mostrar la seccin de variables, para que no anden tan confusos. ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; ------------------------------------------------------------------------------------------Como podrn haberlo deducido, la variable fireSpeed, es la velocidad que afectar a waitTilNextFire, waitTilNextFire es el tiempo que debemos esperar para nuestro prximo disparo. La variable bullet es el GameObject de la bala que dispararemos y bulletSpawn es de donde aparecer la bala (del GameObject bullet spawn como establecimos). Antes de continuar, arrastren el prefab bullet y el GameObject bullet spawn donde corresponda. Como se muestra en la imagen:

44

45

Terminemos este Script: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15;

@HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; function Update () { if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0); targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } -------------------------------------------------------------------------------------------

46

Esto es ms fcil de entender. Primero nos preguntamos si estamos presionando el botn izquierdo del ratn. Si es as, entonces nos preguntamos si el tiempo de espera para el prximo disparo ya acab waitTilNextFire y si existe un GameObject bullet (si no arrastraron el prefab, ser false, caso contrario true). Luego se llama a la funcin Instantiate. La funcin Instantiate, recibe 3 parmetros. El objeto a clonar, la posicin en la que se crear y la rotacin que tendr. Si ustedes se ponen a disparar vern que se crean bullet (Clone), ya que son clonaciones de la bala original. Despus le cambiamos el valor de waitTilNextFire a 1. Y sencillamente despus cada frame se le va descontando el valor a waitTilNextFire.

47

Captulo 1.13 Raycast y agujeros de Bala


Ver en Ingls: http://www.youtube.com/watch?v=cZsG4dfCUec&feature=plcp Antes de comenzar, bsicamente Raycast, es un rayo que se crea, en donde nos devuelve informacin del objeto golpeado (collider) e incluso cambiar algunos aspectos de este. Vayan a su GameObject Rampa y cambien su Transform.Rotation a (0, 0, 0). Si han seguido estos captulos antes debera haber estado en (0, 0, 315). Esto es para probar lo de los agujeros de bala.

Lo que haremos ahora, ser crear el Agujero de Bala, y un cubo de color azul, para saber que cuando se cree el Bullet Hole, de fondo aparezca de color azul. Vamos y crearemos un GameObject Vaco y dentro de este un Plano.

48

Acto Seguido, crearemos un cubo. Busquen en internet la imagen de un Bullet Hole. Yo usar esta:

Ahora dentro de la carpeta Materiales, crearemos 2 materiales. Llamen a uno texAzul, y al otro texBulletHole. Al material texAzul coloquen un Main Color azul.

Con la imagen que descargaron, arrstrenla a Unity, luego colquenla en texBulletHole y finalmente establezcan el Shader en Particles -> Multiply.

49

Arrastren el material texAzul al ltimo cubo creado y el material texBulletHole al Plano creado. Se me olvido mencionar, al prefab bullet marquen la casilla Is Trigger, y desmarquen la casilla Mesh Renderer o si no tendrn algunos errores (ya que la bala no se dispara, la bala crea el rayo que genera el disparo). Dentro de la carpeta Prefabs creen un nuevo prefab, renmbrenlo como bulletHole. Arrastren el GameObject Vaco (con el Plane) (El plano con el material del bullet hole) a este prefab y luego borren el GameObject Vaco.

Para terminar, vamos a Edit -> Project Settings -> Tags. Cambiamos el tamao del Tag a 2, y en Element 0 colocamos Level Parts.

50

Y ahora a cada GameObject hijo del GameObject Escenario y al cubo azul creado, colquenle el Tag Level Parts.

Ahora si podremos comenzar con el Script. Creen un nuevo Script y renmbrenlo como bulletScript y arrstrenlo al Prefab bullet. ------------------------------------------------------------------------------------------var maxDist : float = 1000000000; var decalHitWall : GameObject; var floatInFronOfWall:float=0.001; function Update () { var hit : RaycastHit; if (Physics.Raycast(transform.position,transform.forward,hit,maxDist)) { if (decalHitWall && (hit.transform.tag=="Level Parts")) { Instantiate(decalHitWall,hit.point+(hit.normal*floatInFronOfWall), Quaternion.LookRotation(hit.normal)); } } Destroy(gameObject); } -------------------------------------------------------------------------------------------

Primero vamos explicando: creamos 3 variables, maxDist que ser el tamao mximo del rayo (un nmero grande), 51 decalHitWall, que es el bulletHole que se crea en la pared y floatInFrontOfWall, que es para que el bullet hole cuando se cree aparezca en frente de la pared y no la traspase o est por detrs. Recuerden arrastrar el Prefab bullethole donde lo pida.

Aqu hay algo nuevo, estamos definiendo una variable de tipo RaycastHit. Es una estructura que devuelve informacin de vuelta a travs de un raycast. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/RaycastHit.html Ahora veremos la nueva funcin Physics.Raycast. Hay distintos tipos de est funcin, pero la que usamos nosotros pide 4 parmetros. El origen que es el transform.position de la bala, la direccin establecida por transform.forward (El eje z positivo), el hit, que es la informacin que obtendremos de vuelta de lo que golpeamos. Y el tamao mximo maxDist del rayo. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Physics.Raycast.html?from=RaycastHit

Es decir si del rayo que se crea choca con algn collider, te devuelve un valor true. Luego nos preguntamos si colocamos algn GameObject para decalHitWall (Si es que arrastraron el bulletHole ser true) y adems si el tag del collider al cual golpea es Level Parts, entonces crear un cln del bullet hole, en el punto de colisin y un poco ms al frente, con una rotacin determinado por la normal que se forma entre los 2. Al final de esto hay un Destroy, esta funcin destruye al GameObject bala que se cre. Si no lo colocan les ir lento el juego.

Prueben el juego y se darn cuenta que los bullet holes estn mal rotados. Para esto vamos al prefab bulletHole y cambiamos esto a su hijo Plane:

52

Ahora prueben, por ahora hay algunos errores que se crean varios bulletHoles encima de otros. Pero eso lo veremos en el prximo captulo.

Captulo 1.14 Tiempo de Destruccin Agujero Bala


Ver en Ingls: http://www.youtube.com/watch?v=ei635F6xeP8&feature=plcp Como notaron en el captulo anterior el bullet hole creado est ah por siempre. Y al haber muchos te alenta el juego, por lo tanto veremos la forma de destruirlos. Primero vayan al prefab bulletHole-> Plane y Remuevan el componente del Mesh Collider, ya que o sino provoca colisiones con nuestro Jugador. Ahora creen un Script y renmbrenlo DestroyAfterTimeScript y arrstrenlo al prefab bulletHole. Abramos el Script y a trabajar:

------------------------------------------------------------------------------------------var destroyAfterTime : float= 30; var destroyAfterTimeRandomization :float=0; @HideInInspector var countToTime : float; function Awake() { destroyAfterTime+= Random.value * destroyAfterTimeRandomization; } function Update () { countToTime+=Time.deltaTime; if (countToTime>=destroyAfterTime) Destroy(gameObject); } ------------------------------------------------------------------------------------------Bueno, primero definimos una variable destroyAfterTime, que es el tiempo que tiene que transcurrir para que se destruya el bullethole, destroyAfterTimeRandomization ser para generar un valor al azar para destroyAfterTime. Y finalmente countToTime, va a ser como un cronmetro. Apenas se crea el GameObject en la Escena, a destroyAfterTime se le sumra un valor al azar entre 0 y 1 multiplicado por destroyAfterTimeRandomization. Script Reference: http://docs.unity3d.com/Documentation/ScriptReference/Random-value.html Luego countToTime se va sumando el tiempo, que transcurre y si llega al tiempo requerido por destroyAterTime entonces destruir al gameObject. Luego de esto, vayan al inspector Y cambien las 2 variables a 5,o a 3, dependiendo del tiempo. Destaco que el tiempo est en segundos. Prueben el juego, disparen al cubo azul, a la rampa, al suelo, etc.

53

Captulo 1.15 Propagacin de Balas


Ver en Ingls: http://www.youtube.com/watch?v=wx8PcZipBUo&feature=plcp En este captulo veremos como crear un efecto de rotacin en el arma cuando las balas se propagan, para generar disparos con cierta inexactitud (algo as como un recoil, en el prximo captulo veremos una mejor recoil). Bueno esto ser muy corto. Abrimos nuestro Script GunScript y lo editamos: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; var shootAngleRandomizationAiming : float=5; var shootAngleRandomizationNotAiming : float=15; function Update ()

54

{ if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); targetXRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); targetYRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0);

55

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } -------------------------------------------------------------------------------------------

56 Primero declaramos 2 variables shootAngleRandomizationAiming y shootAngleRandomizationNotAiming, ests ayudarn en un valor al azar cuando estas manteniendo presionado click derecho y cuando no. Luego a la rotacin en X e Y del arma le sumamos un valor al azar entre 0 y 1, le restamos 0.5 y lo multiplicamos por un valor que ser o shootAngleRandomizationAiming o shootAngleRandomizationNotAiming en este caso. En el inspector pueden cambiarlo a 3 y 5, prueben el juego y vern que si resulta. Nota: Esta es una pistola de disparo rpido, pueden bajar la frecuencia, para que sea de disparo lento.

Captulo 1.16 Recoil del Arma


Ver en Ingls: http://www.youtube.com/watch?v=GwgYt3EzRV0&feature=plcp Como ya mencionamos, vamos a generar una recoil al arma. Abramos el Script GunScript y editemos: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30;

var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; var shootAngleRandomizationAiming : float=5; var shootAngleRandomizationNotAiming : float=15; var recoilAmount : float=0.5; var recoilRecoverTime : float=0.2; @HideInInspector var currentRecoilZPos:float; @HideInInspector var currentRecoilZPosV:float; function Update () { if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); targetXRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); targetYRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); currentRecoilZPos-=recoilAmount; waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; currentRecoilZPos=Mathf.SmoothDamp(currentRecoilZPos,0,currentRecoilZPosV,recoilRecoverTime); cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false)

57

{ cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0)+Quaternion.Euler(ta rgetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

58

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } ------------------------------------------------------------------------------------------Ahora si est quedando largo el Script, les recomiendo que lo lean y analicen, para ayudarlos las partes en Negrita son las nuevas lneas o modificaciones que se realizaron. Primero definimos 4 variables, recoilAmount ser la cantidad de recoil que te genera cada disparo, por eso se le resta a currentRecoilZPos, esta variable indica el recoil que te genera en la posicin z, recoilRecoverTime es para ir reduciendo tu recoil, hasta no tener, finalmente currentRecoilZPosV ser usada para Mathf.SmoothDamp (Para volver a no tener recoil). Y a la posicin que tendr el arma dentro de la cmara ser determinada por los nuevos valores agregados: Quaternion.Euler(targetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

Captulo 1.17 Sonido de Disparo


Ver en Ingls: http://www.youtube.com/watch?v=_Et8Y-pX6XA&feature=plcp Vamos a ver en este captulo como aadir un sonido a nuestro disparoo. Antes que nada descargaremos un efecto de sonido de un disparo. Yo usar este: http://www.mediafire.com/?zzpnnwfz14jb57j Creen una Carpeta que se llame Sonidos e importen el sonido descargado a esta carpeta.

Creen un objeto vaco y renmbrenlo gunsound, arrastren el sonido importado a este GameObject. Adems arrastren el Script DestroyAfterTime y reduzcan la variable destroyAfterTime a 2. Ahora creen un prefab dentro de la Carpeta Prefab, nmbrenlo Bullet Sound, y arrastren el GameObject gunsound al prefab. Despus borren el GameObject de la Hierarchy. Ahora abrimos el Script GunScript y lo editamos: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; var shootAngleRandomizationAiming : float=5; var shootAngleRandomizationNotAiming : float=15; var recoilAmount : float=0.5; var recoilRecoverTime : float=0.2;

59

@HideInInspector var currentRecoilZPos:float; @HideInInspector var currentRecoilZPosV:float; var bulletSound:GameObject; function Update () { var holdSound:GameObject; if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); if (bulletSound) holdSound=Instantiate(bulletSound,bulletSpawn.transform.position,bulletSpawn.transform.rotation); targetXRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); targetYRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); currentRecoilZPos-=recoilAmount; waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; if (holdSound) holdSound.transform.parent=transform; currentRecoilZPos=Mathf.SmoothDamp(currentRecoilZPos,0,currentRecoilZPosV,recoilRecoverTime); cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); }

60

//Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0)+Quaternion.Euler(ta rgetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

61

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0) } ------------------------------------------------------------------------------------------Bueno obviamente creamos una variable bulletSound, para el prefab que acabamos de crear. Arrastramos nuestro prefab Bullet Sound, donde pida el GameObject el Script (de nuestro GameObject ArmaBrazo1). La funcin Instantiate crear el sonido de la bala, al igual donde se crea la bala, y esta bala clonada es guardada en la variable de tipo GameObject holdSound. La siguiente lnea: if (holdSound) holdSound.transform.parent=transform; Es para decirle que el objeto holdSound creado se mantenga en la posicin del bulletspawn. En el caso que no estuvieran estas 2 lneas y prueban el juego, disparen y roten rpidamente la cmara, y notaran en la vista Scene que el objeto sonido est detrs de uno y no en la salida del arma. Estas 2 lneas sern muy tiles para el prximo captulo. Prueben el juego y divirtanse disparando, ahora est quedando mucho mejor. Antes de seguir les recuerdo que los Script se van alargando, as que les reitero que deben leer bien e intenten entender cada parte del Script. Vayamos al prximo captulo:

Captulo 1.18 Muzzle Flash


Ver en Ingls: http://www.youtube.com/watch?v=aKtow07MX40&feature=plcp En este captulo veremos 2 procesos, el primero crear el muzzleflash, a partir de partculas, y el segundo modificar el Script para generarlo. Como dato usaremos el mismo proceso que con el sonido, as no tendrn dificultades. Vamos a bajar una imagen de algn muzzle flash. Yo usar esta:

62

Arrstrenla a la carpeta Materiales. Creen un nuevo Material, llmenlo Muzzle Flash y coloquen la textura del MuzzleFlash y de Shader: Particle/Additive.

Ahora creen un objeto vaco, llmenlo muzzleFlash y agreguen una componente Particle -> Ellipsoid, Particle Animator y Particle Renderer. Primero arrastren el material del Muzzle Flash a este GameObject. Ahora editen los valores de las componentes segn esta imagen:

63

Ahora creen un prefab, renmbrenlo como muzzle_flash y arrastren el GameObject muzzleflash a este prefab. Luego borren el GameObject. Abrimos GunScript, y editamos el Script (Recuerden que ser el mismo proceso que con el captulo anterior): ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float; @HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3;

var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; var shootAngleRandomizationAiming : float=5; var shootAngleRandomizationNotAiming : float=15; var recoilAmount : float=0.5; var recoilRecoverTime : float=0.2; @HideInInspector var currentRecoilZPos:float; @HideInInspector var currentRecoilZPosV:float; var bulletSound:GameObject; var muzzleFlash:GameObject; function Update () { var holdMuzzleFlash:GameObject; var holdSound:GameObject; if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); if (bulletSound) holdSound=Instantiate(bulletSound,bulletSpawn.transform.position,bulletSpawn.transform.rotation);

64

if (muzzleFlash) holdMuzzleFlash=Instantiate(muzzleFlash,bulletSpawn.transform.position,bulletSpawn.transform.rotation); targetXRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); targetYRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); currentRecoilZPos-=recoilAmount; waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; if (holdSound) holdSound.transform.parent=transform; if (holdMuzzleFlash) holdMuzzleFlash.transform.parent=transform; currentRecoilZPos=Mathf.SmoothDamp(currentRecoilZPos,0,currentRecoilZPosV,recoilRecoverTime); cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed); } if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0)+Quaternion.Euler(ta rgetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

65

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRota tionV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0) } -------------------------------------------------------------------------------------------

Bueno no hay mucho que explicar aqu, es igual al captulo Anterior, an as lo explicar de nuevo por las dudas. Primero 66 creamos una variable llamada muzzleFlash, que guardar informacin del prefab muzzle_flash (deben arrastrarlo donde lo pida). La segunda variable holdMuzzleFlash ser usada, para mantener el muzzleFlash creado, en la salida del arma. Cabe destacar que si prueban el juego y disparan, el muzzle flash tendr el mismo ngulo (no rotar para hacerlo variado). Para cambiar el ngulo marquen la casilla Rnd Rotation del Particle Animator.

Pongan Play, para probar el juego y podrn ver que el muzzleflash creado si tiene rotaciones aleatorias. Nota: Dentro del prefab muzzle_flash, pueden agregar un objeto point light, de baja intensidad, para generar un efecto de iluminacin en cada disparo.

Captulo 1.19 HeadBobMovement


Ver en Ingls: http://www.youtube.com/watch?v=q4d-_CCNo6g&feature=plcp Bueno no se si han jugado algn video juego en el que si avanzas hacia al frente, la cmara como que va movindose izquierda-derecha, sin que muevas el mouse (La cmara como que va cabeceando). Adems podrn apreciarlo en el video de la introduccin que coloqu. Antes de crear el Script, le dar ciertos datos a usar: Debemos crear variables que contengan, la velocidad del Headbob, las cantidades en el eje X/Y que afecte al Headbob, y la ultima posicin guardada, para originar movimientos suavizados del Headbob. Ahora vamos con el Script MouseLook:

------------------------------------------------------------------------------------------var defaultCameraAngle : float=60; var currentTargetCameraAngle : float=60; var racioZoom : float=1; var racioZoomV : float; var racioZoomSpeed : float=0.2; var lookSensitivity: float=5; @HideInInspector var yRotation: float; @HideInInspector var xRotation: float; @HideInInspector var currentYRotation:float; @HideInInspector var currentXRotation:float; @HideInInspector var yRotationV:float; @HideInInspector var xRotationV:float; var lookSmoothDamp:float=0.1; var currentAimRacio : float=1; var headbobSpeed:float=1; var headbobStepCounter:float; var headbobAmountX:float=1; var headbobAmountY:float=1; var parentlastPos:Vector3; var eyeHeightRacio:float=0.9; function Awake() { Screen.showCursor=false;// Esconder cursor parentlastPos=transform.parent.position; } function Update () { if (transform.parent.GetComponent(PlayerMovement).grounded)

67

headbobStepCounter+=Vector3.Distance(parentlastPos, transform.parent.position)*headbobSpeed; transform.localPosition.x=Mathf.Sin(headbobStepCounter)*headbobAmountX*currentAimRacio; transform.localPosition.y=(Mathf.Cos(headbobStepCounter*2)*headbobAmountY*1*currentAimRacio)+(transform.parent.localScale.y*eyeHeightRacio)-(transform.parent.localScale.y/2); parentlastPos=transform.parent.position; if (currentAimRacio == 1) racioZoom=Mathf.SmoothDamp(racioZoom, 1, racioZoomV, racioZoomSpeed); else racioZoom=Mathf.SmoothDamp(racioZoom, 0, racioZoomV, racioZoomSpeed); camera.fieldOfView = Mathf.Lerp(currentTargetCameraAngle, defaultCameraAngle, racioZoom); //Mirar Con el Mouse: yRotation+=Input.GetAxis("Mouse X") * lookSensitivity * currentAimRacio; xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity * currentAimRacio; xRotation=Mathf.Clamp(xRotation,-90,90); //Mirar Con el Mouse Ms suavizado: currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp); currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp); //hacia donde mira: transform.rotation=Quaternion.Euler(currentXRotation,currentYRotation,0); } ------------------------------------------------------------------------------------------Vamos a explicar: primero definimos 6 variables, headbobSpeed es la velocidad del cabeceo, parentLastPos guarda la ltima posicin del padre, para luego suavizar el movimiento a la nueva posicin del cabeceo, headbobStepCounter guarda la distancia entre parentLastPost y la nueva posicin del padre (PlayerCapsule). En base a eso se genera 2 funciones Seno y Coseno, para establecer el cabeceo (No se maten pensando por qu es esa frmula, si no entindanla). Ahora, prueben el juego y tal vez noten que el jugador baila mucho el mambo con la Pistola. El baile de la pistola es originado porque la funcin Update del Script GunScript interfiere mucho con la funcin Update, del script MouseLook. Por lo tanto lo que haremos es simplemente hacer que la funcin Update del Script GunScript se ejecute al termino de cada funcin Update. A el Script GunScript y cambien function Update por function LateUpdate Esto se ejecuta al termino de cada frame.

68

69

Ahora cambiaremos ciertas variables del inspector como muestra la imagen:

Estas variables cambiadas, harn que el jugador no tiemble mucho al caminar, y haga cabeceos cortos. Acomoden las variables como les acomode.

Captulo 1.20 Gun-Bob Movement


Ver en Ingls: http://www.youtube.com/watch?v=SEk52vLPmWQ&feature=plcp Ya sabemos que es el cabeceo, ahora realizaremos el mismo cabeceo ahora para el arma Esta vez realizaremos el cabeceo, pero para el arma. Empezaremos abriendo el Script GunScript y lo editaremos rpidamente: ------------------------------------------------------------------------------------------var cameraObject : GameObject; @HideInInspector var targetXRotation : float; @HideInInspector var targetYRotation : float;

@HideInInspector var targetXRotationV : float; @HideInInspector var targetYRotationV : float; var rotateSpeed : float = 0.3; var holdHeight : float = -0.5; var holdSide : float = 0.5; var racioHipHold : float=1; var hiptoAimSpeed : float=0.1; @HideInInspector var racioHipHoldV : float; var aimRacio : float = 0.4; var zoomAngle:float=30; var fireSpeed:float=15; @HideInInspector var waitTilNextFire:float=0; var bullet:GameObject; var bulletSpawn:GameObject; var shootAngleRandomizationAiming : float=5; var shootAngleRandomizationNotAiming : float=15; var recoilAmount : float=0.5; var recoilRecoverTime : float=0.2; @HideInInspector var currentRecoilZPos:float; @HideInInspector var currentRecoilZPosV:float; var bulletSound:GameObject; var muzzleFlash:GameObject; var gunbobAmountX:float=0.5; var gunbobAmountY:float=0.5; var currentGunbobX:float; var currentGunbobY:float;

70

function LateUpdate () { currentGunbobX=Mathf.Sin(cameraObject.GetComponent(MouseLook).headbobStepCounter)*gunbobAmou ntX*racioHipHold; currentGunbobY=Mathf.Cos(cameraObject.GetComponent(MouseLook).headbobStepCounter*2)*gunbobAm ountY*1*racioHipHold; var holdMuzzleFlash:GameObject; var holdSound:GameObject; if (Input.GetButton("Fire1")) { if (waitTilNextFire<=0 && bullet) { Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation); if (bulletSound) holdSound=Instantiate(bulletSound,bulletSpawn.transform.position,bulletSpawn.transform.rotation); if (muzzleFlash) holdMuzzleFlash=Instantiate(muzzleFlash,bulletSpawn.transform.position,bulletSpawn.transform.rotation); targetXRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); targetYRotation+=(Random.value0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold); currentRecoilZPos-=recoilAmount; waitTilNextFire=1; } } waitTilNextFire-=Time.deltaTime*fireSpeed; if (holdSound) holdSound.transform.parent=transform; if (holdMuzzleFlash) holdMuzzleFlash.transform.parent=transform; currentRecoilZPos=Mathf.SmoothDamp(currentRecoilZPos,0,currentRecoilZPosV,recoilRecoverTime); cameraObject.GetComponent(MouseLook).currentTargetCameraAngle=zoomAngle; if (Input.GetButton("Fire2")) { cameraObject.GetComponent(MouseLook).currentAimRacio=aimRacio; racioHipHold=Mathf.SmoothDamp(racioHipHold,0,racioHipHoldV,hiptoAimSpeed);

71

} if (Input.GetButton("Fire2")==false) { cameraObject.GetComponent(MouseLook).currentAimRacio=1; racioHipHold=Mathf.SmoothDamp(racioHipHold,1,racioHipHoldV,hiptoAimSpeed); } //Mantener la posicion de la camara transform.position=cameraObject.transform.position + Quaternion.Euler(0,targetYRotation,0)*Vector3(holdSide*racioHipHold+currentGunbobX,holdHeight*racioHipHold+curr entGunbobY,0)+Quaternion.Euler(targetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

72

targetXRotation=Mathf.SmoothDamp(targetXRotation,cameraObject.GetComponent(MouseLook).xRotation,targetXRot ationV,rotateSpeed); targetYRotation=Mathf.SmoothDamp(targetYRotation,cameraObject.GetComponent(MouseLook).yRotation,targetYRot ationV,rotateSpeed); transform.rotation=Quaternion.Euler(targetXRotation, targetYRotation,0); } ------------------------------------------------------------------------------------------Bueno es el mismo proceso que en el captulo anterior, les pido que analicen las variables y las lneas, ahora mostrar las variables que dej yo en el Inspector:

Esta primera parte del tutorial les ayudar a entender mejor ciertas funciones que son muy importantes al proceso de crear el Script, estos tutoriales de ETeeski y traducidos por mi, espero que los ayuden a meterse ms en el mbito de la programacin, y que requiere demasiada creatividad, para realizar cada Script. Le agradezco a ETeeski por darme permiso de poder publicar esta versin resumida de los tutoriales en una versin al Espaol, an as yo les recomiendo que vean sus tutoriales, inclusive de la parte bsica antes de empezar con los tutoriales FPS. Les recuerdo que para contactarse, pueden enviar un MP en ingls a ETeeski: http://www.youtube.com/user/ETeeskiTutorials O pueden enviarme un mail a cotolonco@outlook.com O a este correo: coto.kun@gmail.com Tambin pueden mandarme un MP a mi perfil de Taringa http://www.taringa.net/cotolonco Les deseo suerte con sus proyectos, nos vemos en la segunda parte de estos Tutoriales.

73