El personaje y el controlador

1

Introducci贸n: De la idea al desarrollo

2

Estructura de carpetas en Unity

3

Assets, Game Objects y Sprite Atlas

4

Animaciones desde un sprite map

5

Animation Controller y Transiciones

6

Plataformas y gravedad

7

F铆sica en Unity

8

El script de control

9

Programando funciones en C# y Unity: Jump

10

Detectar el suelo con Raycast

11

Herramientas de debugging visual

12

Cambiar las animaciones seg煤n los estados

13

Reto: Terminando nuestras animaciones

14

Soluci贸n del reto

15

Hacer que el personaje camine

El manager del videojuego

16

C贸mo funciona el Game Manager

17

El Singleton

18

El modo de juego

19

Input manager y juegos multiplataforma

20

Correcci贸n del Bug del salto

21

La zona de muerte

22

Reiniciar la partida

23

Corrigiendo los bugs al reiniciar nuestro juego

Dise帽o procedural de niveles 2D

24

El dise帽o de niveles a mano

25

Configurando nuestros assets para el dise帽o procedural

26

Generaci贸n procedural de niveles

27

Creando la zona que eliminar谩 bloques del nivel excedentes

28

A帽adir un nuevo bloque de forma aleatoria

29

La c谩mara que sigue al jugador

30

Destrucci贸n de bloques antiguos

31

Terminando de programar la destrucci贸n de bloques antiguos

32

Solucionando el salto de la c谩mara al reiniciar el juego

HUD, men煤s y gameplay

33

El canvas en Unity

34

Uso de botones para crear un men煤

35

La l贸gica de los men煤s

36

Ejercicio: Preparando el men煤 del juego

37

Programando el men煤 del juego

38

Los coleccionables del juego

39

Actualizar UI de coleccionables

40

Iniciando con pociones y man谩

41

Pociones de vida y man谩

42

Programando las barras de vida y man谩

43

Calculando los puntajes con la distancia y el tiempo de juego

44

La l贸gica del man谩

Enemigos y dificultad

45

Plataformas m贸viles

46

Iniciar movimiento de la plataforma con trigger

47

Enemigos m贸viles

48

Enemigos m贸viles: preparando nuestro enemigo para girar

49

Enemigos m贸viles: programando que gire al chocar

50

Arreglando el collider de nuestra roca

51

Programando la condici贸n de muerte del personaje

52

A帽adiendo m煤sica de fondo a nuestro videojuego

53

A帽adiendo efectos de sonido y cierre del curso

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Curso de C# para Videojuegos

Curso de C# para Videojuegos

Juan Gabriel Gomila

Juan Gabriel Gomila

Input manager y juegos multiplataforma

19/53
Recursos

El Input Manager es una herramienta que nos proporciona Unity para expandir la entrada de controles y soportar y reaccionar correctamente a todas las posibles acciones de los jugadores en las plataformas disponibles. Unity nos enviar谩 c贸digos especiales cuando el jugador oprima ciertos botones y nosotros devolveremos la acci贸n que queremos realizar.

En esta clase vamos a trabajar con nuestros scripts controladores para cambiar entre los estados del juego por medio de esta nueva entrada de controles en vez de reaccionar por una tecla en particular.

El desaf铆o de esta clase es evitar que nuestro personaje pueda saltar a menos que estemos en estado de 鈥溾淚n Game鈥濃, as铆 como hemos evitado que nuestro personaje pueda avanzar en el resto de estados.

Aportes 27

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Yo logre detener el movimiento del personaje llamado a un m茅todo de su RigidBody2D

rigid.Sleep ();

Mi c贸digo. Yo le tengo configurado para que no camine autom谩ticamente, sino cuando yo presiono las flechas.

void Update () {

		if(GameManager.sharedInstance.currentGameState == GameState.inGame){
			if(Input.GetButtonDown("Jump")){
				Jump();
			}
		}
	
		animator.SetBool(STATE_ON_THE_GROUND, isTouchingTheGround());

		Debug.DrawRay(this.transform.position, Vector2.down*1.4f, Color.red); // for debug purposes
	}

	void FixedUpdate() {
		// if(rigidBody.velocity.x < runningSpeed){
		// 	rigidBody.velocity = new Vector2(runningSpeed, rigidBody.velocity.y);
		// }
		if(GameManager.sharedInstance.currentGameState == GameState.inGame){
			playerMovement();
		}
	}

	void playerMovement(){
		
		float isWalking = Input.GetAxisRaw("Horizontal");
	
		if(isWalking != 0){ //is true

			animator.SetBool(STATE_IS_QUIET, false);
			animator.SetBool(STATE_IS_WALKING, true);
			rigidBody.velocity = new Vector2(isWalking * runningSpeed,rigidBody.velocity.y);
			spriteRenderer.flipX = (isWalking == -1) ? true : false; 
			//if the value returns -1 that means is walking to the left and we need to make a flip in X
		}else{
			animator.SetBool(STATE_IS_QUIET, true);
			animator.SetBool(STATE_IS_WALKING, false);
		}
		
	}

Podemos encontrar la herramienta de Input Manager en Edit > Project Settings > Input.

Solo hay que hacer eso para declarar que el personaje solo salte en modo juego, sin embargo al probarlo les recomiendo cambiar un momento la tecla de salto o intenten saltar con el mouse, ya que como tenemos designado que se cambie el estado del juego a inGame con la tecla Enter, unity me reconoce el spacebar tambien como enter, por ende al orpimir la barra espaciadora el personaje salta y me cambia el estado del juego automaticamente.

<if 

(GameManager.sharedInstance.currentGameState == GameState.inGame) // solo puede saltar si esta en modo juego
        {
            if (Input.GetButtonDown("Jump")) //condicional para que se ejecute metodo jump al oprimir espacio o click derecho
            {
                Jump();
            }
        }>

Saludos. Activ茅 el brinco solo si el estado del Juego est谩 en 鈥渋nGame鈥:

void Update()
    {
        if (GameManager.sharedInstance.currentGameState == GameState.inGame) {
            if (Input.GetButtonDown("Jump")) { // Input manager action
                Jump();
            }
        }
        
        animator.SetBool(STATE_ON_THE_GROUND, IsTouchingTheGround());
    }

Para los que lo est谩n viendo en Diciembre 2021 la ruta es
Edit > Project Settings > Input Manager

por que me pasa que cuando presiono space mi game state cambia a ingame??

En el caso de que se quiera usar movimiento tanto horizontal como vertical controlado por el usuario. se debe usar la palabra 鈥淗orizontal鈥 y 鈥渧ertical鈥 y para saber si es movimiento positivo o negativo, se debe usar el metodo GetAxisRaw.

// movimiento a la derecha
if(Input.GetButton("Horizontal") && Input.GetAxisRaw("Horizontal") > 0)

// movimiento a la izquierda
if(Input.GetButton("Horizontal") && Input.GetAxisRaw("Horizontal") < 0)

// movimiento hacia arriba
if(Input.GetButton("Vertical") && Input.GetAxisRaw("Vertical") > 0)

// movimiento hacia abajo
if(Input.GetButton("Vertical") && Input.GetAxisRaw("Vertical") < 0)

Yo lo solucione de esta forma

//saltara solo si se presiona la tecla designada por unity para el salto y si estamos en modo juego
        if (Input.GetButtonDown("Jump") && Gamemanager.ShareInstance.currentGameState == GameState.inGame)
        {
            Jump();
        }```

arregle el bug apagando el rigidbody en vez de modificando su velocidad, de esta manera no se ve afectado por las fisicas

PlayerController:

void Update()
    {
	// Se gestionan las animaciones arriba para evitar bugs visuales in-game
        anim.SetBool(STATE_GROUNDED, IsGrounded());
        anim.SetBool(STATE_WALKING, rigidBody.velocity.x != 0);

	// Se invierte este if para mejorar la legibilidad y reducir la complejidad cognitiva
        if (GameManager.sharedInstanceGM.currentGameState != GameState.inGame) return;

        if (Input.GetButtonDown("Jump"))
        {
            Jump();
        }

        Debug.DrawRay(this.transform.position - new Vector3(0, playerCollider.size.y / 2, 0), Vector2.down * gndRaycastLenght, Color.red);
    }
void FixedUpdate()
    {
	// Se invierte este if para mejorar la legibilidad y reducir la complejidad cognitiva
        if (GameManager.sharedInstanceGM.currentGameState != GameState.inGame) return;

        float xAxis = Input.GetAxis("Horizontal");

        if (xAxis != 0)
        {
            Walk(xAxis);
        }
    }

Finalmente se edita el Input Submit para que no se ejecute al presionar la barra espaciadora.

A mi me sale un error al tratar de cambiar el GameState.
Me sale este error:
NullReferenceException: Object reference not set to an instance of an object
Player_controler.FixedUpdate () (at Assets/Scripts/Player_controler.cs:46)
驴Qu茅 debo de hacer?
copie lo mismo del profesor

 if (GameManager.sharedInstance.currentGameState == GameState.inGame)
        {
            if (Input.GetButtonDown("Jump"))
            {
                Jump();
            }
        }
        

De hecho, al ver el juego en la primera clase ya imagin茅 c贸mo hacer los botones de juego

Solo hay que a帽adirle este if:

if (GameManager.sharedInstance.currentGameState == GameState.inGame)

A la funci贸n de getButtonDown(鈥渏ump鈥)

esat es mi solucion para JUMP

void Jump()
    {
        if(GameManager.sharedInstance.currentGameState == GameState.inGame)
        {
            if (IsTouchingTheGround()) //dependiendo del valor regresado del metodo, si es true pasara al salto
            {
                playerRB.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);

            }
        }
        
    }```

El salto no deber铆a estar en el FixedUpdate?

Para congelar el personaje en el aire al poner pausa us茅 rigidBody.Sleep() dentro del PlayerController

private void FixedUpdate()
    {
        if(GameManager.sharedInstance.currentGameState == GameState.inGame)
        {
            if (rigidBody.velocity.x < runningSpeed)
            {
                rigidBody.velocity = new Vector2(runningSpeed, rigidBody.velocity.y);
            }
        } else
        {
            rigidBody.Sleep();
        }
    }
 if (Input.GetButtonDown("Jump") && GameManager.SharedInstance.currentGameState == GameState.inGame) 
        {
            Jump();
  
        }

En mi caso al teclear la barra espaciadora se iba a inGame porque en el input manager en el segundo submit lo tiene configurado con esa tecla

Lo mejor es de momento usar otra tecla para saltar y no el Space, porque esa tecla aparece como secundaria para el argumento 鈥淛ump鈥, as铆 que al presionarla siempre va a saltar e inmediatamente va a cambiar a estado inGame. Ya luego de cambiar la tecla de salto se puede poner la condici贸n if(GameManager.sharedInstance.currentGameState == GameState.inGame)

Ya sea en la propia funci贸n Jump() o en el Update.

Si alguien quiere implementar un men煤 de pausa este v铆deo esta muy bueno.
https://www.youtube.com/watch?v=JivuXdrIHK0

Activar el auto completado del MonoDevelop es muy util

Este es el codigo de este video:

void FixedUpdate()
{
if (GameManager.sharedInstance.currentGameState == GameState.inGame)
{
if (rigidBody.velocity.x < runningSpeed)
{
rigidBody.velocity = new Vector2 (runningSpeed, rigidBody.velocity.y);
}
} else {
rigidBody.velocity = new Vector2(0, rigidBody.velocity.y);
}
}
![](

Genial

Mi soluci贸n fue, primero como el profesor indica, los cambios a las fisicas los dejo en FixedUpdate, las entradas de datos como movimiento y jump los inclui en Update, asi que dejando fuera los estados de animaci贸n inserte una condicional para limitar el movimiento y el brinco a que solo sea en inGame, las animaciones iniciales las dejo fuera ya que al iniciar el juego en GameState.menu el player ca铆a sin animaci贸n y con eso lo solucione

 void Update()
    {
        animator.SetBool(STATE_ON_THE_GROUND, IsTouchingTheGround());
        animator.SetBool(STATE_FALLING, IsFalling());

        if (GameManager.sharedInstance.currentGameState == GameState.inGame) 
        {
            if(Input.GetButtonDown("Jump"))
            {
                jumpKey = true;
            }
            move = Input.GetAxis("Horizontal");
            if (move > 0)
            {
                spriteRenderer.flipX = false;
                animator.SetBool(STATE_RUNNING, true);
            }
            else if (move < 0)
            {
                spriteRenderer.flipX = true;
                animator.SetBool(STATE_RUNNING, true);
            }
            else
            {
                animator.SetBool(STATE_RUNNING, false);
            }
        }
        else
        {
            jumpKey = false;
            move = 0f;
        }

Aqui mi c贸digo en FixedUpdate

    void FixedUpdate()
    {
        if (jumpKey)
        {
            Jump();
            jumpKey = false;
        }
        rigidBody.velocity = new Vector2(move * runningSpeed, //x
                                        rigidBody.velocity.y); //y
    }

Yo le deshabilite el animator tambi茅n por que no me gustaba que terminar谩 la animaci贸n

            rigidBody.Sleep();
            animator.enabled = false;