fpseteeski_español_cotolonco_parte1

73
1

Upload: jose-manuel

Post on 18-Apr-2015

2.618 views

Category:

Documents


2 download

DESCRIPTION

Para Unity 3D (Version Free o Pro)En este tutorial en español verás la parte básica del FPS y como scriptearla por parte, inclusive la cámara. Gracias a los video tutoriales de ETeeski que resumo y explico.

TRANSCRIPT

Page 1: FpsETeeski_Español_Cotolonco_Parte1

1

Page 2: FpsETeeski_Español_Cotolonco_Parte1

2

Índice:

Introducción ………………………………………………………………………………………………………………………………………………………….Pág.3

Capitulo 1.1-1.2………………………………………………………………………………………………………………………………………………………Pág.4

Capitulo 1.3 ……………………………………………………………………………………………………………………………………………………………Pág.9

Capitulo 1.4 ……………………………………………………………………………………………………………………………………………………………Pág.12

Capitulo 1.5 ……………………………………………………………………………………………………………………………………………………………Pág.15

Capitulo 1.6 ……………………………………………………………………………………………………………………………………………………………Pág.19

Capitulo 1.7 ……………………………………………………………………………………………………………………………………………………………Pág.24

Capitulo 1.8 ……………………………………………………………………………………………………………………………………………………………Pág.27

Capitulo 1.9 ……………………………………………………………………………………………………………………………………………………………Pág.32

Capitulo 1.10 …………………………………………………………………………………………………………………………………………………………Pág.35

Capitulo 1.11 …………………………………………………………………………………………………………………………………………………………Pág.38

Capitulo 1.12 …………………………………………………………………………………………………………………………………………………………Pág.42

Capitulo 1.13 …………………………………………………………………………………………………………………………………………………………Pág.47

Capitulo 1.14 …………………………………………………………………………………………………………………………………………………………Pág.52

Capitulo 1.15 …………………………………………………………………………………………………………………………………………………………Pág.54

Capitulo 1.16 …………………………………………………………………………………………………………………………………………………………Pág.56

Capitulo 1.17…………………………………………………………………………………………………………………………………………………………Pág.58

Capitulo 1.18 …………………………………………………………………………………………………………………………………………………………Pág.62

Capitulo 1.19 …………………………………………………………………………………………………………………………………………………………Pág.66

Capitulo 1.20 …………………………………………………………………………………………………………………………………………………………Pág.69

Page 3: FpsETeeski_Español_Cotolonco_Parte1

3

Introducción

Bienvenidos, me presento. Soy cotolonco, usuario de Taringa. Un día (mediados de Julio/2012) estuve buscando

tutoriales Fps de Unity, ya que los que había eran ejemplos ya hechos o no explicaban casi nada, decidí buscar tutoriales

en Inglés, ya que en Español no hay mucho, y me encontré con ETeeskiTutorial, que enseña lo básico de Unity, ya sean

las transform, Quaternion, la interfaz, javascript básico, entre otras, y entre eso hay tutoriales de Fps, y explica

sencillamente bien, incluso no hay que saber inglés 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, estarán 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 rápido, solo para ejemplificar y disculpen lo lento del video, iba fluido cuando lo

grabé).

Cada video tutorial tendrá su capítulo, el cual estará compuesto por el video original en inglés de ETeeski, para verlo

online. Una pequeña intro de qué se verá en el capítulo, los pasos a seguir, los script por parte o completos dependiendo

el caso, y una explicación de este si lo requiere.

Resumen por mí en español, con lo más importante.

Requisitos Antes de Continuar:

- Conocer la interfaz de Unity.

- Saber como crear objetos vaciós, cubos, crear terrenos, lo que es un GameObject, entre otras.

- Diferenciar de un Padre, un hijo, en qué afecta, etc.

- Variables básicas acerca del transform, position, rotation, quaternion, definir variables, etc.

- Saber qué es un Tag, un Input, entre otras y como definirlo o modificarlo.

- Conocimientos básicos de JavaScript, (Mayor importancia a sentencia if-else) y su estructura.

Cualquier duda antes de continuar, pueden contactarme a: [email protected] [email protected]

O también a ETeeski, enviándole un MP por youtube: http://www.youtube.com/user/ETeeskiTutorials

Nota: Hay líneas de código que no se alcanzan a escribir en una línea del documento.Fíjense en eso.

Les Recomiendo lean con cuidado, y pregunten.

Page 4: FpsETeeski_Español_Cotolonco_Parte1

4

Capítulo 1.1 Visión General

Ver en Inglés: http://www.youtube.com/watch?v=MPN5kYkdYUY&feature=plcp

Empezamos con estos capítulos en español. Bueno básicamente 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 qúe se

hará y como se hará sin usar Unity aún. Y la segunda parte del video muestra el proceso en Unity.

Capítulo 1.2 Mouse Look Script (Mirar moviendo el ratón)

Ver en Inglés: http://www.youtube.com/watch?v=3JsuldsGuNw&feature=plcp

Esto es lo más 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 línea o código que

posiblemente estuvo mal redactada o el posicionamiento/rotación de algún GameObject.

Vamos a ver 2 cosas aquí, primero como manejar la cámara a través del mouse y lo segundo como suavizar su

movimiento. Empecemos:

Antes de comenzar creen un pequeño 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 además agreguen una luz direccional.

Renombren los Game Objects como les acomode.

Debe quedar más o menos como se muestra en la imagen:

Page 5: FpsETeeski_Español_Cotolonco_Parte1

5

Seguido de esto, creamos un objeto Vacío (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 Vacío. 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 además para

decir “Si nosotros pisamos al Padre (El Escenario), estamos pisando algún hijo de este. Entonces Ahora podremos saltar”

(Caso hipotético, 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 “Cámara” 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;

-------------------------------------------------------------------------------------------

Page 6: FpsETeeski_Español_Cotolonco_Parte1

6

Antes de seguir primero explicaré para que se utilizara cada una.

lookSensitivity será la sensibilidad del mouse. En defecto es 5, a mayor sea más rápido rotará la cámara. xRotation e

yRotation son las rotaciones en los ejes Y y X respectivamente. Pero, se preguntarán por qué xRotation representa la

rotación en el eje Y y yRotation la rotación en el eje X. Es Simple, si ustedes van a los GameObjects y seleccionan la

cámara, Verán que en la sección Transform está su componente la Rotación, y Si ustedes cambian el valor de X

(Representando xRotation), entonces la cámara 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 después. 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 cámara

xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cámara

//Rotación final de la cámara

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 más suavizadas y rápidas ya que se involucra con

números complejos.

Euler es una Función Clase o Class Function. Esta Función pide 3 parámetros o valores

(x: float,y : float,z: float). Devuelve una rotación 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 cámara verá hacia abajo y viceversa.

Page 7: FpsETeeski_Español_Cotolonco_Parte1

7

Pueden probar el juego y verán que funciona, pero notarán que los movimientos son un poco bruscos, por lo que las demás variables ayudarán a suavizar el movimiento. Nota: Si agregan arriba de la function Update() este código: -------------------------------------------------------------------------------------------

function Awake()

{

Screen.showCursor=false;

}

-------------------------------------------------------------------------------------------

Podrán 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 cámara

xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cámara

//Mirar con el Mouse más suavizado:

currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp);

currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp);

//Rotación final de la cámara

Page 8: FpsETeeski_Español_Cotolonco_Parte1

8

transform.rotation=Quaternion.Euler(currentXRotation, currentYRotation, 0);

}

-------------------------------------------------------------------------------------------

Veamos qué es eso de Mathf.SmoothDamp Es una Class Function (así como colocar Mathf.Cos, que sería el coseno de un número) que pide máximo 6 parámetros. 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 parámetro es la posición actual. El segundo parámetro es la posición a la que queremos buscar, el Tercer parámetro es la velocidad actual. Y el Cuarto parámetro es el tiempo que tardará en llegar del primer parámetro al tercer parámetro. Pueden ver el Script Reference aquí: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.SmoothDamp.html Por lo tanto, queremos llegar de la rotación xRotation, yRotation a la rotación 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 cámara 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 ()

Page 9: FpsETeeski_Español_Cotolonco_Parte1

9

{

//Mirar con el Mouse:

yRotation+=Input.GetAxis("Mouse X") * lookSensitivity; //Movimiento horizontal de la cámara

xRotation-=Input.GetAxis("Mouse Y") * lookSensitivity;//Movimiento vertical de la cámara

xRotation=Mathf.Clamp(xRotation,-90,90);

//Mirar con el Mouse más suavizado:

currentXRotation=Mathf.SmoothDamp(currentXRotation,xRotation,xRotationV,lookSmoothDamp);

currentYRotation=Mathf.SmoothDamp(currentYRotation,yRotation,yRotationV,lookSmoothDamp);

//Rotación final de la cámara

transform.rotation=Quaternion.Euler(currentXRotation, currentYRotation, 0);

}

-------------------------------------------------------------------------------------------

Para finalizar, explicaré que es Mathf.Clamp Es una Class Function que pide 3 parámetros: el valor, el mínimo, el máximo. La función devuelve un valor que esté entre el mínimo y el máximo (Incluyéndolos). Pueden ver el Script Reference Aquí: http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Clamp.html Ahora prueben y verá que funciona perfectamente.

Capítulo 1.3 Caminar/Correr básicamente

Ver en Inglés: http://www.youtube.com/watch?v=5pkeRlpjFzQ&feature=plcp

Quiero aclarar antes de iniciar el capítulo que no es correr presionando shift, o caminar lentamente presionando shift, si

no que tu movimiento natural es una aceleración, por lo que si más rato mantienes mantenido WASD o las flechas del

teclado, cada vez aumentarás más la velocidad. Sabiendo esto comencemos:

Antes de comenzar con los Script. Agreguen a la Escena una cápsula y llámenla PlayerCapsule y arrastren la Cámara, de

tal manera que sea hijo de la cápsula.

Cuando hayan arrastrado la cámara. Ubiquen su posición (x,y,z) en (0,0.7,0).

Como se muestra en la imagen:

Page 10: FpsETeeski_Español_Cotolonco_Parte1

10

Ahora seleccionen al PlayerCapsule, vayan a Component -> Physics -> Rigidbody. Para añadirle un rigidbody al

PlayerCapsule.

Antes de seguir, como ahora a nuestro jugador le afectan las físicas. No queremos que se caiga como un Pin de los

juegos de Bolos. Por lo tanto agregamos esto:

Page 11: FpsETeeski_Español_Cotolonco_Parte1

11

Así estará siempre “de pie”.

Ahora si podremos continuar. Creen un nuevo JavaScript y llámenlo PlayerMovement (Arrástrenlo 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 cámara 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í:

Page 12: FpsETeeski_Español_Cotolonco_Parte1

12

Ahora explicaré qué significa ese parámetro que le dimos cameraObject.GetComponent(MouseLook).currentYRotation.

Primero ingresamos al cameraObject qué es un GameObject (En este caso la cámara que arrastramos), Ingresamos al

Script MouseLook y obtenemos el valor de currentYRotation. Así el Player mirará hacia donde mira la cámara. Así no

tendremos algún problema al caminar. (Si prueban el juego ahora no notarán mucha diferencia).

Ahora vamos al Script final:

-------------------------------------------------------------------------------------------

var walkAcceleration: float=5;

var cameraObject:GameObject;

function Update ()

{

//Rotar Hacia donde ve la cámara

transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0);

//Añade 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. Además es una función que recibió 3

parámetros. El primero, le añade una fuerza relativa a través del eje x. El segundo, a través del eje y. Y finalmente el

tercero a través del eje z.

Aquí el Script Reference:

http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody.AddRelativeForce.html

Si probamos el juego, y presionamos W o algún otro botón, notaremos que irá lento al principio y comenzará a

aumentar su velocidad. Si cambian walkAcceleration a 10 irá más rápido pero si sueltan el botón el Playercapsule se

deslizará. En el próximo capítulo veremos como arreglarlo.

Capítulo 1.4 Estableciendo una velocidad máxima

Ver en Inglés: 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:

Page 13: FpsETeeski_Español_Cotolonco_Parte1

13

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

Dentro de la carpeta creada Materiales, creen un Material (Renómbrenlo como TexturaPiedra).

Luego Arrastren la imagen a Unity, y colóquenla la imagen en el Material (TexturaPiedra). Y éste Material Arrástrenlo a

su GameObject Suelo.

Para que no sea una imagen super larga de la textura Pierda, cambien el Tiling del Material.

Page 14: FpsETeeski_Español_Cotolonco_Parte1

14

Obviamente luego de esto, tendrían 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 cámara

transform.rotation=Quaternion.Euler(0,cameraObject.GetComponent(MouseLook).currentYRotation,0);

//Añade 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 máxima del

PlayerCapsule. Además 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 sería 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 dirección.

Page 15: FpsETeeski_Español_Cotolonco_Parte1

15

Script Reference aquí:

http://docs.unity3d.com/Documentation/ScriptReference/Vector2-normalized.html

Segundo Le multiplicamos por maxWalkSpeed para entregarle el límite 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 podrán notar que en un momento no aumenta la velocidad. Pueden cambiar el valor de

maxWalkSpeed a 10 y notarán más el resultado.

Capítulo 1.5 Saltando de Manera Correcta

Ver en Inglés: http://www.youtube.com/watch?v=eSnzuRgrN_8&feature=plcp

Tal como dice el título, veremos como saltar de manera correcta. Además de que podrá saltar cuando el vector normal

que se genera entre el jugador y lo que pisas forma algún ángulo que sea menor al máximo (tampoco podrás saltar si

chocaste con la cabeza un objeto, también 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);

Page 16: FpsETeeski_Español_Cotolonco_Parte1

16

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 inclinación podremos subir.

Luego se agregó 2 líneas. La primera Input.GetButtonDown regresa verdadero si el botón fue presionado (solo con una

vez basta, no mantenido). Y “Jump” es el botón 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, auméntenlo

a 300 o 400 para fijarse mejor.

Claro que hasta ahora podremos saltar incluso en el aire.

Antes de seguir creen un cubo y transfórmenlo en rampa, y arrástrelo al GameObject Escenario (Opcional). Pueden

copiar los datos de esta imagen:

Page 17: FpsETeeski_Español_Cotolonco_Parte1

17

Si se fijan la rotación 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)

Page 18: FpsETeeski_Español_Cotolonco_Parte1

18

{

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 colisión con un collider o rigidbody. Y

OnCollisionExit se ejecuta en el instante que dejemos de colisionar con el collider o rigidbody.

El parámetro collision que se le da a OnCollisionStay, recibe información del collider/rigidbody con el cual está

colisionando.

Luego llamamos esta extraña 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 línea 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 inclinación 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 podrán hacer sin problemas. Pero si colocan una pared y saltan al lado de esta, se

“estancarán”. Esto se resolverá en el Capítulo 1.7.

Page 19: FpsETeeski_Español_Cotolonco_Parte1

19

Capítulo 1.6 Añadiendo Fricción al Movimiento

Ver en Inglés: http://www.youtube.com/watch?v=SUKddKIgCUQ&feature=plcp

Si ustedes habrán notado. Nuestro jugador al soltar las teclas de movimiento sigue deslizándose hasta detenerse y toma

bastante tiempo. Por lo tanto lo que haremos en este capítulo 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;

}

Page 20: FpsETeeski_Español_Cotolonco_Parte1

20

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 líneas:

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

botón. 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 además está

tocando suelo.

Si ustedes prueban se darán cuenta que el jugador frena casi de golpe. Para suavizarlo un poco bajen el valor de

walkDeacceleration a 1.05 o 1.1.

Page 21: FpsETeeski_Español_Cotolonco_Parte1

21

¿Qué tal si suavizamos más el movimiento?

Antes de saber cómo, 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);

}

Page 22: FpsETeeski_Español_Cotolonco_Parte1

22

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 función Mathf.SmoothDamp? Si no recuerdan, fue usada en el Script MouseLook, para suavizar el

movimiento de la rotación de la cámara.

Por lo tanto se hizo lo mismo para suavizar la fricción del jugador al detenerse.

Se agregaron de la misma forma walkDeaccelerationVolx y walkDeaccelerationVolz.

Si no recuerdan la función. 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

Page 23: FpsETeeski_Español_Cotolonco_Parte1

23

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á más suavizado el caminar. Pero tendrán que aumentar walkAcceleration a 500 o 1000, o algo parecido.

Page 24: FpsETeeski_Español_Cotolonco_Parte1

24

Capítulo 1.7 Control del Aire y Pegarse a las Paredes

Limitado

Ver en Inglés: http://www.youtube.com/watch?v=1Ptl4V4Zwy0&feature=plcp

Control del Aire significa que al saltar, podremos movernos más lento que en el suelo, y al chocar con las paredes, nos

iremos “deslizando” hasta llegar al suelo, dependiendo de su inclinación.

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. Verás que costará subir. Ya que vas chocando con cada cubo.

Por lo tanto debes hacer este pequeño truco:

Haz click en cada escalón 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 llámalo RampaEscalera o como quieras. Y ubícalo de tal forma que te quede como si

subieras entre el primer escalón y el último, como se muestra en esta imagen:

Page 25: FpsETeeski_Español_Cotolonco_Parte1

25

Ahora intenta subir la escalera, y verás que es sin problemas. Claro que si bajas el valor del walkAcceleration. No podrás

poder subirla totalmente. Por lo tanto si sucede, debes aumentar el valor.

Volviendo al Script, para saber cómo controlarte en el aire y no pegarte a las paredes. Abre tu Script PlayerMovement. Y

edítalo 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;

Page 26: FpsETeeski_Español_Cotolonco_Parte1

26

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;

}

}

Page 27: FpsETeeski_Español_Cotolonco_Parte1

27

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 tamaño.

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

else), se moverá más lento, determinado por un valor pequeño de walkAccelAirRatio.

Capítulo 1.8 Arma básica con Peso

Ver en Inglés: http://www.youtube.com/watch?v=ay2SMb9-nEE&feature=plcp

En este capítulo veremos como añadir un arma, y rotarla dependiendo de donde esté la cámara.

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 rápida. (Si se fijan las texturas no están ordenadamente

diseñadas).

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.

Page 28: FpsETeeski_Español_Cotolonco_Parte1

28

Ahora nos vamos a Unity, y creamos una carpeta llamada Modelos.

Luego arrastran estos 3 archivos a la carpeta. Se les tendría que ver así:

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. Obtendrán esto como resultado:

Page 29: FpsETeeski_Español_Cotolonco_Parte1

29

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

pequeño.

Y ahora podemos comenzar.

Hagan click en el GameObject cámara, y luego vayan a GameObject-> Create Empty y nómbrenlo 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 cámara.

Page 30: FpsETeeski_Español_Cotolonco_Parte1

30

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 renómbrenlo 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 cámara.

Ahora crearemos 7 variables más. De las cuales ya más o menos sabrán, para que serán.

-------------------------------------------------------------------------------------------

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;

Page 31: FpsETeeski_Español_Cotolonco_Parte1

31

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 serán usadas con la función Mathf.SmoothDamp, para suavizar el movimiento.

Las otras 2 variables, es para ubicar el arma más a la derecha o izquierda (holdSide), o hacia arriba o abajo (holdHeight).

Para la posición 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);

}

-------------------------------------------------------------------------------------------

Page 32: FpsETeeski_Español_Cotolonco_Parte1

32

La primera línea estamos estableciendo que a cada frame del juego la posición del arma transform.position, esté en el

centro de la cámara, más como ya dijimos un poco a la derecha/izquierda o arriba/abajo establecido por lo que sigue del

signo positivo.

Las siguientes 2 líneas donde se define targetXRotation y targetYRotation, si lo notaron se usa un movimiento suavizado

desde su ultima rotación targetXRotation/ targetYRotation hasta la rotación obviamente de la cámara

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, notarás que el arma se desplazará. Además

si rotas la vista, te darás cuenta que el arma con el brazo giran junto con la cámara. Pero en ocasiones la el arma con el

brazo desaparecen de la cámara, porque tardan en llegar. Para arreglar esto, cambiaremos el valor de rotateSpeed por

0.1 y a probar! Ahora está quedando bien.

Capítulo 1.9 Apuntando (Aiming)

Ver en Inglés: http://www.youtube.com/watch?v=_YhahZPE9Mg&feature=plcp

En este capítulo realizaremos un cambio de posición del arma, de manera suavizada y rápida. En unas líneas más

adelante explico un pequeño 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 añadirle unas 3 variables. Volveremos a usar Mathf.SmoothDamp.

Pero Antes de continuar, vamos a modificar ciertas cosas del arma. Ya que hay un pequeño error que cometimos. (Al

explicar el script entenderán por qué).

Vamos a modificar esto del GameObject ArmaBrazo1 (hijo del GameObject Gun).

Page 33: FpsETeeski_Español_Cotolonco_Parte1

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 serán 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

Page 34: FpsETeeski_Español_Cotolonco_Parte1

34

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

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

función 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 ratón. 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 línea modificada:

Page 35: FpsETeeski_Español_Cotolonco_Parte1

35

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 línea, esta:

Vector3(holdSide*racioHipHold,holdHeight*racioHipHold,0)

Como ya dijimos racioHipHold solo toma valores entre 0 y 1. Cuando presionamos click derecho del ratón, 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 capítulo). 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 botón derecho del ratón y notarán que está quedando muy bien. Si no es

así, es que hay algún problema, con variables o alguna línea mal escrita.

Capítulo 1.10 Sensibilidad del arma al apuntar (Gun Aim

Sensitivity)

Ver en Inglés: http://www.youtube.com/watch?v=T8G3uXSAZ3g&feature=plcp

En este capítulo se verá como colocar cierta sensibilidad cuando nosotros estemos apuntando (manteniendo presionado

click derecho del ratón), es decir, cuando apuntemos irá más lenta lla cámara que cuando no.

Si pudieron deducirlo, se habrán 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

Page 36: FpsETeeski_Español_Cotolonco_Parte1

36

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 Más 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 líneas donde están yRotation y

xRotation nos daremos cuenta que mientras más grande el número, más rápido rotará la cámara. 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

Page 37: FpsETeeski_Español_Cotolonco_Parte1

37

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

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

}

-------------------------------------------------------------------------------------------

Page 38: FpsETeeski_Español_Cotolonco_Parte1

38

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 verán que si mueven el mouse la cámara rotará como siempre, pero al mantener presionado el bóton

derecho del ratón (apuntando), y al mover el mouse se moverá más lentamente la cámara.

Capítulo 1.11 Zoom de la Cámara

Ver en Inglés: http://www.youtube.com/watch?v=0DWC-1Qb_2Y&feature=plcp

Tal como dice el título de este Capítulo, veremos cómo hacer un zoom de la cámara, 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

Page 39: FpsETeeski_Español_Cotolonco_Parte1

39

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 Más 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);

}

-------------------------------------------------------------------------------------------

Page 40: FpsETeeski_Español_Cotolonco_Parte1

40

Creamos 5 nuevas variables. Las 3 últimas, racioZoom, racioZoomV y racioZoomSpeed serán usadas, para la función

Mathf.SmoothDamp. Las 2 primeras variables, currentTargetCameraAngle y defaultCameraAngle definirán el ángulo de

la cámara apuntando, y el ángulo por default de la cámara.

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 función, analicemos la variable camera.fieldOfView.

Esta variable es el campo de visión de la cámara en grados. A menor grado, más zoom obtendrás y viceversa.

Script Reference:

http://docs.unity3d.com/Documentation/ScriptReference/Camera-fieldOfView.html

Vamos a la nueva función Mathf.Lerp, para entender mejor la situación:

Esta es una función, que pide 3 valores (from:float, to:float, t:float). Al entregárselas, Mathf.Lerp Interpola entre el

valor from y el valor to (Recuerden que interpolar, básicamente 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 función Mathf.SmoothDamp será 1, esto implica que en la

función 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 también es 60, entonces ¿Cómo le decimos que sea 30 por

ejemplo? La respuesta es simple, nosotros le diremos el ángulo a través del Script GunScript. Abramos este Script y lo

editaremos:

-------------------------------------------------------------------------------------------

var cameraObject : GameObject;

@HideInInspector

var targetXRotation : float;

@HideInInspector

var targetYRotation : float;

@HideInInspector

var targetXRotationV : float;

Page 41: FpsETeeski_Español_Cotolonco_Parte1

41

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

}

-------------------------------------------------------------------------------------------

Page 42: FpsETeeski_Español_Cotolonco_Parte1

42

Agregamos una nueva variable zoomAngle que nos dará el nuevo ángulo de la cámara.

Y la siguiente línea le decimos que el currentTargetCameraAngle sea igual al zoomAngle. Cabe notar que no es

necesario, meter esta línea dentro de un if, ya que Mathf.Lerp, se encarga de elegir si el ángulo es 30, 60, o algún valor

entre esos 2.

Probemos el juego y sí! Efectivamente tiene un zoom.

Capítulo 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 sería 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, renómbrenlo como Test Bullet, y modifiquen estos datos determinados por la línea roja:

Acto Seguido. Creen una carpeta llamada Prefabs. Ahora dentro de esta carpeta creen un prefab y renómbrenlo como

bullet. Ahora arrastren el GameObject Test Bullet a este prefab (Para saber que si lo arrastraron, hagan click en el

prefab y verán todos los datos del cubo).

Page 43: FpsETeeski_Español_Cotolonco_Parte1

43

Ahora borren el GameObject Test Bullet que tenemos en la Escena, ya que tenemos el prefab de este.

Creen un Objeto Vacío, y renómbrenlo como bullet spawn. Arrástrenlo 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.

Page 44: FpsETeeski_Español_Cotolonco_Parte1

44

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 más (la bala, donde apárece 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 sección 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 podrán haberlo deducido, la variable fireSpeed, es la velocidad que afectará a waitTilNextFire, waitTilNextFire es

el tiempo que debemos esperar para nuestro próximo 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:

Page 45: FpsETeeski_Español_Cotolonco_Parte1

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;

Page 46: FpsETeeski_Español_Cotolonco_Parte1

46

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

}

-------------------------------------------------------------------------------------------

Page 47: FpsETeeski_Español_Cotolonco_Parte1

47

Esto es más fácil de entender. Primero nos preguntamos si estamos presionando el botón izquierdo del ratón. Si es así,

entonces nos preguntamos si el tiempo de espera para el próximo 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 función Instantiate.

La función Instantiate, recibe 3 parámetros. El objeto a clonar, la posición en la que se creará y la rotación que tendrá.

Si ustedes se ponen a disparar verán que se crean bullet (Clone), ya que son clonaciones de la bala original.

Después le cambiamos el valor de waitTilNextFire a 1. Y sencillamente después cada frame se le va descontando el valor

a waitTilNextFire.

Capítulo 1.13 Raycast y agujeros de Bala

Ver en Inglés: http://www.youtube.com/watch?v=cZsG4dfCUec&feature=plcp

Antes de comenzar, básicamente Raycast, es un rayo que se crea, en donde nos devuelve información 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 capítulos antes

debería 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 Vacío y dentro de este un Plano.

Page 48: FpsETeeski_Español_Cotolonco_Parte1

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.

Page 49: FpsETeeski_Español_Cotolonco_Parte1

49

Con la imagen que descargaron, arrástrenla a Unity, luego colóquenla en texBulletHole y finalmente establezcan el

Shader en Particles -> Multiply.

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

tendrán 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, renómbrenlo como bulletHole. Arrastren el GameObject Vacío

(con el Plane) (El plano con el material del bullet hole) a este prefab y luego borren el GameObject Vacío.

Page 50: FpsETeeski_Español_Cotolonco_Parte1

50

Para terminar, vamos a Edit -> Project Settings -> Tags.

Cambiamos el tamaño del Tag a 2, y en Element 0 colocamos Level Parts.

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

Ahora si podremos comenzar con el Script. Creen un nuevo Script y renómbrenlo como bulletScript y arrástrenlo 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);

}

-------------------------------------------------------------------------------------------

Page 51: FpsETeeski_Español_Cotolonco_Parte1

51

Primero vamos explicando: creamos 3 variables, maxDist que será el tamaño máximo del rayo (un número grande),

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 detrás. Recuerden arrastrar el Prefab bullethole donde

lo pida.

Aquí hay algo nuevo, estamos definiendo una variable de tipo RaycastHit. Es una estructura que devuelve información

de vuelta a través de un raycast.

Script Reference:

http://docs.unity3d.com/Documentation/ScriptReference/RaycastHit.html

Ahora veremos la nueva función Physics.Raycast.

Hay distintos tipos de está función, pero la que usamos nosotros pide 4 parámetros. El origen que es el

transform.position de la bala, la dirección establecida por transform.forward (El eje z positivo), el hit, que es la

información que obtendremos de vuelta de lo que golpeamos. Y el tamaño máximo 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 algún collider, te devuelve un valor true.

Luego nos preguntamos si colocamos algún GameObject para decalHitWall (Si es que arrastraron el bulletHole será true)

y además si el tag del collider al cual golpea es Level Parts, entonces creará un clón del bullet hole, en el punto de

colisión y un poco más al frente, con una rotación determinado por la normal que se forma entre los 2.

Al final de esto hay un Destroy, esta función destruye al GameObject bala que se creó. Si no lo colocan les irá lento el

juego.

Prueben el juego y se darán cuenta que los bullet holes están mal rotados. Para esto vamos al prefab bulletHole y

cambiamos esto a su hijo Plane:

Page 52: FpsETeeski_Español_Cotolonco_Parte1

52

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

el próximo capítulo.

Capítulo 1.14 Tiempo de Destrucción Agujero Bala

Ver en Inglés: http://www.youtube.com/watch?v=ei635F6xeP8&feature=plcp

Como notaron en el capítulo 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 renómbrenlo DestroyAfterTimeScript y arrástrenlo al prefab bulletHole.

Abramos el Script y a trabajar:

Page 53: FpsETeeski_Español_Cotolonco_Parte1

53

-------------------------------------------------------------------------------------------

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 cronómetro.

Apenas se crea el GameObject en la Escena, a destroyAfterTime se le sumára 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.

Page 54: FpsETeeski_Español_Cotolonco_Parte1

54

Capítulo 1.15 Propagación de Balas

Ver en Inglés: http://www.youtube.com/watch?v=wx8PcZipBUo&feature=plcp

En este capítulo veremos como crear un efecto de rotación en el arma cuando las balas se propagan, para generar

disparos con cierta inexactitud (algo así como un recoil, en el próximo capítulo 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 ()

Page 55: FpsETeeski_Español_Cotolonco_Parte1

55

{

if (Input.GetButton("Fire1"))

{

if (waitTilNextFire<=0 && bullet)

{

Instantiate(bullet,bulletSpawn.transform.position,bulletSpawn.transform.rotation);

targetXRotation+=(Random.value-

0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold);

targetYRotation+=(Random.value-

0.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);

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

}

-------------------------------------------------------------------------------------------

Page 56: FpsETeeski_Español_Cotolonco_Parte1

56

Primero declaramos 2 variables shootAngleRandomizationAiming y shootAngleRandomizationNotAiming, estás

ayudarán en un valor al azar cuando estas manteniendo presionado click derecho y cuando no.

Luego a la rotación 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 verán que si resulta.

Nota: Esta es una pistola de disparo rápido, pueden bajar la frecuencia, para que sea de disparo lento.

Capítulo 1.16 Recoil del Arma

Ver en Inglés: 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;

Page 57: FpsETeeski_Español_Cotolonco_Parte1

57

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

0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold);

targetYRotation+=(Random.value-

0.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)

Page 58: FpsETeeski_Español_Cotolonco_Parte1

58

{

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

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 líneas 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 posición 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 posición que tendrá el arma dentro de la cámara será determinada por los nuevos valores agregados:

Quaternion.Euler(targetXRotation,targetYRotation,0)*Vector3(0,0,currentRecoilZPos);

Capítulo 1.17 Sonido de Disparo

Ver en Inglés: http://www.youtube.com/watch?v=_Et8Y-pX6XA&feature=plcp

Vamos a ver en este capítulo como añadir 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.

Page 59: FpsETeeski_Español_Cotolonco_Parte1

59

Creen un objeto vacío y renómbrenlo gunsound, arrastren el sonido importado a este GameObject. Además arrastren

el Script DestroyAfterTime y reduzcan la variable destroyAfterTime a 2.

Ahora creen un prefab dentro de la Carpeta Prefab, nómbrenlo Bullet Sound, y arrastren el GameObject gunsound al

prefab. Después 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;

Page 60: FpsETeeski_Español_Cotolonco_Parte1

60

@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.value-

0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold);

targetYRotation+=(Random.value-

0.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);

}

Page 61: FpsETeeski_Español_Cotolonco_Parte1

61

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

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 función 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 línea:

if (holdSound)

holdSound.transform.parent=transform;

Es para decirle que el objeto holdSound creado se mantenga en la posición del bulletspawn. En el caso que no

estuvieran estas 2 líneas y prueban el juego, disparen y roten rápidamente la cámara, y notaran en la vista Scene que el

objeto sonido está detrás de uno y no en la salida del arma.

Estas 2 líneas serán muy útiles para el próximo capítulo.

Prueben el juego y diviértanse 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 próximo capítulo:

Page 62: FpsETeeski_Español_Cotolonco_Parte1

62

Capítulo 1.18 Muzzle Flash

Ver en Inglés: http://www.youtube.com/watch?v=aKtow07MX40&feature=plcp

En este capítulo veremos 2 procesos, el primero crear el muzzleflash, a partir de partículas, y el segundo modificar el

Script para generarlo. Como dato usaremos el mismo proceso que con el sonido, así no tendrán dificultades.

Vamos a bajar una imagen de algún muzzle flash. Yo usaré esta:

Arrástrenla a la carpeta Materiales.

Creen un nuevo Material, llámenlo Muzzle Flash y coloquen la textura del MuzzleFlash y de Shader: Particle/Additive.

Page 63: FpsETeeski_Español_Cotolonco_Parte1

63

Ahora creen un objeto vacío, llámenlo 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 según esta imagen:

Ahora creen un prefab, renómbrenlo 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 capítulo 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;

Page 64: FpsETeeski_Español_Cotolonco_Parte1

64

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

Page 65: FpsETeeski_Español_Cotolonco_Parte1

65

if (muzzleFlash)

holdMuzzleFlash=Instantiate(muzzleFlash,bulletSpawn.transform.position,bulletSpawn.transform.rotation);

targetXRotation+=(Random.value-

0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold);

targetYRotation+=(Random.value-

0.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);

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)

}

-------------------------------------------------------------------------------------------

Page 66: FpsETeeski_Español_Cotolonco_Parte1

66

Bueno no hay mucho que explicar aquí, es igual al capítulo Anterior, aún así lo explicaré de nuevo por las dudas. Primero

creamos una variable llamada muzzleFlash, que guardará información 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 podrán 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 iluminación en cada disparo.

Capítulo 1.19 HeadBobMovement

Ver en Inglés: http://www.youtube.com/watch?v=q4d-_CCNo6g&feature=plcp

Bueno no se si han jugado algún video juego en el que si avanzas hacia al frente, la cámara como que va moviéndose

izquierda-derecha, sin que muevas el mouse (La cámara como que va cabeceando). Además podrán apreciarlo en el

video de la introducción 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 posición guardada, para originar movimientos suavizados del Headbob.

Ahora vamos con el Script MouseLook:

Page 67: FpsETeeski_Español_Cotolonco_Parte1

67

-------------------------------------------------------------------------------------------

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)

Page 68: FpsETeeski_Español_Cotolonco_Parte1

68

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 Más 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 posición del padre, para luego suavizar el movimiento a la nueva posición del cabeceo, headbobStepCounter

guarda la distancia entre parentLastPost y la nueva posición 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

fórmula, si no entiéndanla).

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 función Update del Script GunScript interfiere mucho con la función Update,

del script MouseLook. Por lo tanto lo que haremos es simplemente hacer que la función Update del Script GunScript se

ejecute al termino de cada función Update.

A el Script GunScript y cambien function Update por function LateUpdate Esto se ejecuta al termino de cada frame.

Page 69: FpsETeeski_Español_Cotolonco_Parte1

69

Ahora cambiaremos ciertas variables del inspector como muestra la imagen:

Estas variables cambiadas, harán que el jugador no tiemble mucho al caminar, y haga cabeceos cortos. Acomoden las

variables como les acomode.

Capítulo 1.20 Gun-Bob Movement

Ver en Inglés: 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 rápidamente:

-------------------------------------------------------------------------------------------

var cameraObject : GameObject;

@HideInInspector

var targetXRotation : float;

@HideInInspector

var targetYRotation : float;

Page 70: FpsETeeski_Español_Cotolonco_Parte1

70

@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;

Page 71: FpsETeeski_Español_Cotolonco_Parte1

71

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

0.5)*Mathf.Lerp(shootAngleRandomizationAiming,shootAngleRandomizationNotAiming,racioHipHold);

targetYRotation+=(Random.value-

0.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);

Page 72: FpsETeeski_Español_Cotolonco_Parte1

72

}

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

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 capítulo anterior, les pido que analicen las variables y las líneas, ahora mostraré las

variables que dejé yo en el Inspector:

Page 73: FpsETeeski_Español_Cotolonco_Parte1

73

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 más en el ámbito de la

programación, y que requiere demasiada creatividad, para realizar cada Script.

Le agradezco a ETeeski por darme permiso de poder publicar esta versión resumida de los tutoriales en una versión al

Español, aún así yo les recomiendo que vean sus tutoriales, inclusive de la parte básica antes de empezar con los

tutoriales FPS.

Les recuerdo que para contactarse, pueden enviar un MP en inglés a ETeeski:

http://www.youtube.com/user/ETeeskiTutorials

O pueden enviarme un mail a [email protected]

O a este correo: [email protected]

También 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.