El personaje y el controlador

1

Programación de Videojuegos en Unity con C#

2

Creación y organización de proyectos 2D en Unity

3

Uso de Sprite Atlas en Unity para Optimizar Recursos Visuales

4

Animación de Personajes en Unity: Creación y Control de Sprites

5

Transiciones de Animaciones en Unity para Videojuegos 2D

6

Creación de Prefabs y Física Básica en Unity 2D

7

Conceptos de Física en Videojuegos con Unity: Colliders y RigidBodies

8

Creación y Uso de Colliders y Scripts en Unity para Videojuegos

9

Métodos Awake y Start en Unity para Configuración Inicial

10

Detección de Colisión con Raycast en Unity para Saltos Precisos

11

Uso de Gizmos y Física en Unity para Desarrollo de Videojuegos

12

Cambio de Animaciones de Personaje con Animator en Unity

13

Animación de Salto en Videojuegos: Creación de Estados Dinámicos

14

Animaciones y Transiciones en Unity Mechanim

15

Movimiento automático y control del personaje en Unity

El manager del videojuego

16

Creación y Gestión de un Game Manager en Videojuegos

17

Implementación de Singletons en Programación de Videojuegos

18

Transición de Estados en Videojuegos con Unity: Menú a Juego

19

Configuración de Controles en Unity: Uso del Input Manager

20

Configuración de Input Manager en Unity para Juegos

21

Creación de Zonas de Muerte con Colliders y Triggers en Unity

22

Función de Reset en Videojuegos 2D: Reinicio y Corrección de Bugs

23

Corrección de Bugs en Reaparición y Reinicio en Unity

Diseño procedural de niveles 2D

24

Diseño de Niveles: Creación Manual y Procedural en Videojuegos

25

Diseño Procedural de Niveles en Videojuegos: Pixel Perfect en Unity

26

Gestión de Bloques de Nivel en Videojuegos con Unity

27

Implementación de ExitZone para Destrucción de Bloques en Videojuegos

28

Generación Procedural de Niveles en Unity: Object Pooling y Optimización

29

Implementación de Cámara Follow en Videojuegos 2D con Unity

30

Destrucción de Bloques y Generación Procedural en Videojuegos

31

Corrección de errores en el Game Manager de videojuegos

32

Sincronización de Cámara y Fondo en Videojuegos 2D

HUD, menús y gameplay

33

El canvas en Unity

34

Diseño de Menú de Inicio en Videojuegos con Canvas

35

Programación de Funcionalidades de Botones en Unity

36

Diseño de Canvas para Pantalla de Juego y Game Over

37

Programación de Script para Interfaz de Juego en Unity

38

Incorporación de Objetos Recolectables en Unity

39

Implementación de un sistema de recolección de monedas en Unity

40

Programación de Pociones de Vida y Maná en Videojuegos

41

Notificación de Recolección de Pociones en Unity

42

Diseño e Implementación de Barras de Vida y Maná en Unity

43

Cálculo de Puntuación y Persistencia en Videojuegos con Unity

44

Implementación de Super Salto en Unity con Uso de Maná

Enemigos y dificultad

45

Creación de Plataformas Móviles en Unity con Animaciones

46

Scripts y Triggers para Plataformas Móviles en Videojuegos 2D

47

Programación de Enemigos Móviles en Unity con C#

48

Implementación de Fixed Update para Movimiento de Enemigos en Unity

49

Programación de colisiones para enemigos en videojuegos

50

Corrección de Bugs en Colisiones y Vida de un Personaje en Videojuegos

51

Control de Vida y Muerte de Personaje en Videojuegos

52

Añadir Música de Fondo en Videojuegos con Unity

53

Implementación de Efectos de Sonido en Videojuegos con Unity

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

Configuración de Controles en Unity: Uso del Input Manager

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 29

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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

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

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

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

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

```js public class GameManager : MonoBehaviour { public GameState currentGameState = GameState.menu; //"Singleton" is a unique script that will be used for a specific set of functionalities or a particular group, and it cannot conflict with others of the same type, such as the current state of the game. public static GameManager sharedInstance; //se llama shared instance porque hace mas enfacis al singleton void Awake(){ if (sharedInstance == null){ sharedInstance = this; } } // Start is called before the first frame update void Start() { currentGameState = GameState.menu; } // Update is called once per frame void Update() { if (Input.GetButtonDown("Submit")){ if (currentGameState == GameState.menu){ StartGame(); }else{ BackToMenu(); } } } public void StartGame(){ SetGameState(GameState.inGame); } public void GameOver(){ SetGameState(GameState.gameOver); } public void BackToMenu(){ SetGameState(GameState.menu); } void SetGameState(GameState newGameState) { currentGameState = newGameState; switch (newGameState) { case GameState.menu: // TODO: Implementar la lógica para mostrar el menú Time.timeScale = 0; break; case GameState.inGame: // TODO: Implementar la lógica para iniciar el juego Time.timeScale = 1; break; case GameState.gameOver: // TODO: Implementar la lógica para mostrar la pantalla de Game Over y reiniciar el juego Time.timeScale = 0; break; default: break; } } ```yo preferi hacerlo directamente en el game manager, ya que es mucho mas sencillo encontrarlo, ademas modificando el timescale te ahorras codigo en el playercontroller.
yo creo que esto lo deberia de programar en el game manager, a pesar de que el profe lo haga en el player controller, ya que es mucho mas sencillo ademas encontrar estas cosas aqui. por sierto utilice otro metodo que es modificando la escala de tiempo, es decir, si estas en in game, la escala es 1 y el tiempo corre normal, sin embargo, estando en menu, o game over deberia ser 0 y el tiempo se ve parado. ```js public class GameManager : MonoBehaviour { public GameState currentGameState = GameState.menu; //"Singleton" is a unique script that will be used for a specific set of functionalities or a particular group, and it cannot conflict with others of the same type, such as the current state of the game. public static GameManager sharedInstance; //se llama shared instance porque hace mas enfacis al singleton void Awake(){ if (sharedInstance == null){ sharedInstance = this; } } // Start is called before the first frame update void Start() { currentGameState = GameState.menu; } // Update is called once per frame void Update() { if (Input.GetButtonDown("Submit")){ if (currentGameState == GameState.menu){ StartGame(); }else{ BackToMenu(); } } } public void StartGame(){ SetGameState(GameState.inGame); } public void GameOver(){ SetGameState(GameState.gameOver); } public void BackToMenu(){ SetGameState(GameState.menu); } void SetGameState(GameState newGameState) { currentGameState = newGameState; switch (newGameState) { case GameState.menu: // TODO: Implementar la lógica para mostrar el menú Time.timeScale = 0; break; case GameState.inGame: // TODO: Implementar la lógica para iniciar el juego Time.timeScale = 1; break; case GameState.gameOver: // TODO: Implementar la lógica para mostrar la pantalla de Game Over y reiniciar el juego Time.timeScale = 0; break; default: break; } } ```

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

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;