Jump to content
Ancoreig

ANSWERED Concepto básico que no entiendo (Adjuntar scripts a objetos)

Recommended Posts

Buenas a todos, hay un concepto que no entiendo y leyendo el título no os habréis enterado de nada, me explico.

Estoy empezando en Unity y estoy siguiendo tutoriales básicos. El primer tutorial que estoy siguiendo se trata de un juego básico que eres un cuadrado y que tienes que comerte a tus enemigos (círculos) con un contador de por medio; si llega a 0 sin haberte comido a todos los enemigos pierdes, y si te los comes a todos antes de llegar a 0 pues ganas.

Os dejo 2 de los scripts; el Jugador y el contador:

public class Player : MonoBehaviour
{

    //las variables que son public, aparecen en Unity y, por ejemplo, podríamos modificar la velocidad del jugador desde 
    //unity, no así enemiesKilled por ejemplo, ya que no es pública

    public float velocidadJugador;
    int enemiesKilled;
    public Text countDownText2;

    //nos creamos un objeto de nuestra clase EnemySpawner
    public EnemySpawner enemySp;

    // Start is called before the first frame update
    void Start(){
        
    }

    // Update is called once per frame
    void Update(){
        
        //comprobamos que el usuario está pulsando la tecla de Flecha arriba
        if(Input.GetKey(KeyCode.UpArrow)){
            //movemos la posición de Y hacia arriba 1 en un segundo, y dejamos la posición X igual
            transform.position = new Vector2(transform.position.x, transform.position.y + velocidadJugador * Time.deltaTime);
        }
        else if(Input.GetKey(KeyCode.DownArrow)){
            transform.position = new Vector2(transform.position.x, transform.position.y - velocidadJugador * Time.deltaTime);
        }
        else if(Input.GetKey(KeyCode.LeftArrow)){
            transform.position = new Vector2(transform.position.x - velocidadJugador * Time.deltaTime, transform.position.y);
        }
        else if(Input.GetKey(KeyCode.RightArrow)){
            transform.position = new Vector2(transform.position.x + velocidadJugador * Time.deltaTime, transform.position.y);
        }

    }

    void OnTriggerEnter2D(Collider2D other){
        
        //comprobamos el choque por el tag del objeto. El objeto tiene que tener seteado el tag
        if(other.CompareTag("Enemy")){
            Destroy(other.gameObject);
            enemiesKilled++;

            //comprobamos si los enemigos que hemos matado es igual al número de enemigos totales gracis a a nuestro método que nos creamos en nuestra clase EnemySpawner
            //(tenemos que poner la variable pública y en nuestro player asignársela en unity)
            if(enemiesKilled == enemySp.GetNumberOfEnemies()){

                countDownText2.text = "Ganaste";

                //paralizamos el tiempo para mostrar que hemos ganado -> establecido a 0 es tiempo congelado, fijado a 1 es
                //tiempo normal (supongo que 2 será el doble de rápido, etc)
                Time.timeScale = 0;
            }

        }

    }

    public void SetVelocidadJugador(float velocidadModificada){
        velocidadJugador = velocidadModificada;
    }


}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CountDown : MonoBehaviour{

    Text countDownText;
    float timer;
    int countDownNumber = 20;

    public Player jugador;

    // Start is called before the first frame update
    void Start()
    {
        //accedo al componente Text y lo asigno a mi variable    
        countDownText = GetComponent<Text>();
        //accedo a la propiedad texto de mi objeto Texto y se lo cambio a 20, que es el valor al que la he iniciado
        countDownText.text = countDownNumber.ToString();


        
    }

    // Update is called once per frame
    void Update()
    {

        //básicamente, Time.deltaTime es igual a 1 segundo.
        timer += Time.deltaTime;

        //Así pues, si ha pasado 1 segundo Y countDownNumber es mayor que cero, le restaré  uno al contador
        if(timer >=1 && countDownNumber > 0){
            countDownNumber--;
            countDownText.text = countDownNumber.ToString();
            timer = 0;

            //si el tiempo llega a 0, mostramos que hemos perdido y ralentizamos al jugador
            if(countDownNumber == 0){
                countDownText.text = "Perdiste";
                
                jugador.SetVelocidadJugador(1);
            }

        }
    }
}

 

No venía en el tutorial y se me ocurrió que, por ejemplo, cuando perdieses se modificase la velocidad del jugador  a 1 (está a 5 en el inspector). Así que en el script del jugador le hice un setter de la velocidad y en el script del contador me instancié un objeto del jugador y se lo seteé a 1 su velocidad. En este punto es donde no entiendo el concepto, es decir, creía que con el seteo ese iba a ser suficiente, pero después de probar el juego unas cuantas de veces no iba.

Así que después de darle un par de vueltas, en mi script del contador, hice público mi objeto Player y ya en el inspector, le asigné al objeto contador el script del jugador y ahí sí que ya funcionó, pero sigo sin entender el por qué no funciona solo con el seteo.

Captura.PNG

 

Un saludo!

 

Edited by Ancoreig

Share this post


Link to post
Share on other sites

Tal vez porque la variable que almacenaba a tu jugador en el script contador estaba vacía, dices que creaste un setter en el player y otro en el contador, pero nunca dices que hiciste referencia entre los dos para activar la función. Para que un objeto tenga influencia a otro, debe tener una referencia de él, puedes obtener el objeto, Transform, el script o crear un namespace para hacer referencia a la función del otro GameObject.

  • Like 1

Share this post


Link to post
Share on other sites

Es lo que dice Alex.

En programación orientada a objetos, el definir un objeto que pertenece a una clase no llega (tú defines un objeto de nombre 'jugador' que pertenece a la clase Player (que es el nombre del Script).

Después de definir un objeto de una clase tienes que instanciarlo (es decir, darle memoria) o modificar su referencia para que 'apunte' a otro objeto ya instanciado previamente (que es lo que haces gráficamente cuando arrastras a la ventana Inspector el GameObject Player. Lo que haces realmente es asociar al componente Player (que es un script) a la variable public que defines en tu script CountDown).

 

Normalmente (o por lo menos es lo que hago yo), al GameObject Player se le suele asociar el tag Player y después, dentro del script, se referencia al player de la siguiente forma:

public class CountDown : MonoBehaviour
{


    private Player player;

    private void Awake()
    {
        GameObject goPlayer = GameObject.FindGameObjectWithTag("Player");
        if (goPlayer == null)
        {
            Debug.Log("Tag Player no encontrado");
        }
        else
        {
            player = goPlayer.GetComponent<Player>();
        }


    }
}

Si no sabes como asociar un Tag a un GameObject puedes consultar este enlace

Edited by AngelFG
  • Like 1

Share this post


Link to post
Share on other sites

×
×
  • Create New...