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 ““In 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 “inGame”:

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 “Horizontal” y “vertical” 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(“jump”)

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 “Jump”, 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;