Jump to content
Cerpion

ANSWERED Duda programación – como usar referencias

Recommended Posts

¡Hola a todos! no tengo mucha experiencia con la programación, pero tengo entendido que cada script debe trabajar de forma individual, el player tendrá un script, el enemigo tiene un script.

Mi duda es entonces esta mal hacer referencia a otros scrips, por ejemplo, si tengo un script de joysctick que controla el movimiento y hago referencia de este script en el player para que controle la dirección, ¿eso está mal? ¿Se debería crear un game manager que guarde una referencia estática al script de joystick y partiendo de eso, agregarlo en el código del player desde la referencia del game manager?

Otro ejemplo. tengo un script que controla el movimiento de la cámara que está en un Game Object vació padre de la cámara y otro que controla en que parte del mundo estoy presionando con el mouse (este script está en la main camera), este último lo utilizare como referencia para otros códigos, ¿estos también deberían estar juntos o están bien separado, cual es la manera más optima de hacerlo?

Espero haberme podido darme a entender, 

¡Saludos! 😁

Share this post


Link to post
Share on other sites

hola, no se si estoy entendiendo bien la pregunta....

si, puedes usar referencias de otros scripts, gameObjecs, o componentes sin problema.

de hecho el leguaje orientado a objetos funciona asi... esta pensado de ese modo.

pueden ser "public" y asignarlos tu mismo desde el inspector.

puedes "buscarlo" en el "void Start" y asignarlo a una variable "private"...

por ejemplo imagina que el script "Enemy" necesita tener acceso al script "Player", pues dentro de "Enemy" deberias tener una variable "private Player m_player;" (el nombre "m_player" es por poner un ejemplo)

y en el "void start" buscas ese "objeto" y lo asignas...

seria algo asi...

public class Enemy : monoBehaviour {
  
  private Player m_player;
  
  void Start() {
    //buscar por nombre el objeto 
    // y cojer una referencia del componente (script) Player
    m_player = GameObject.Find("player").GetComponent<Player>();
  }
  
  void Update() {
    //aqui irian las cosas que hace el enemy
  }
  
  
}

 

.......

pero seguramente si preguntas cosas tan "basicas" la gente te diga que primero te mires unos libros o tutoriales... que seguramente es lo que deberias hacer....   te aconsejo igual que te mires los conceptos basicos de Java porejemplo, que es muy "sencillo" y hay muchos tutoriales de iniciacion y muchos ejercicios muy sencillo de entender...y luego C# (que es el que se usa en Unity) es muy parecido...  te decia de empezar a aprender lo Basico en Java porque creo que hay mas ejemplos y ejercicios basicos.... mas simples...  y es muy parecido..... ya que C# es una copia de Java..... pero si quieres puedes ir direcamente a mirar ejercicios de C# 

...o igual no he entendido bien y ya sabes estas cosas.... porque vi que estabas haciendo un proyecto con mecanicas tipo "assasins creed".... y eso no es muy basico...

Edited by Igor

Share this post


Link to post
Share on other sites

Yo otra forma que hago para referenciar scripts que a lo mejor no es la adecuada, no lo se. Es que si ese script es unico y no se repite crear una variable static de ese script, por ejemplo:

public static Player player

Luego en el Awake() pongo:

player=this;

Despues para hacer referencia al script simplemente pongo:

Player.player.SetLives(5);

A mi me funciona pero a lo mejor no es la forma adecuada, la programacion no es mi fuerte, jeje

Share this post


Link to post
Share on other sites

Hola Cerpion,
Lo primero: No es terrible hacer referencia a otros scripts, pero en un mundo ideal, generalmente es preferible hacer referencias a abstracciones de tus scripts. Esto nos permite que sea más fácil reutilizar y cambiar nuestro código en un futuro. Ahorita me explico más:

Supón que tienes un script llamado Player, y un script llamado Joystick, que a su vez tiene un método llamado GetMovement. Algo así:

public class Player:MonoBehaviour
{
  //Esta es una manera de obtener la referencia, aquí aparecería un campo para asignar el Joystick en el inspector:
  public Joystick playerJoystick;
  //La otra manera sería:
  private void Start()
  {
    playerJoystick = GetComponent<Joystick>();
  }
}

public class Joystick:MonoBehaviour()
{
  public Vector2 GetMovement()
  {
    //Supón que aquí regresaramos un movimiento de verdad en lugar de ceros.
    return new Vector2(0,0);
  }
}

Y eso funciona en general. Pero en un futuro tal vez vayas a querer tener players controlados por la computadora, o diferentes scripts para diferentes tipos de control, o qué sé yo que te depare el futuro. Para estar preparado para el futuro, y que te sea más fácil agregar y cambiar cosas, es mejor que nuestras referencias sean más abstractas, que Player en lugar de referirse a un Joystick haga referencia a, por ponerle un nombre, un MovementProvider. Hay dos formas de hacerlo. Una es con clases abstractas:
 

public class Player:MonoBehaviour
{
  //En lugar del Joystick, hacemos referencia a un MovementProvider, que puede ser un Joystick, pero también otra cosa que se te ocurra.
  public MovementProvider playerMovement;
  
  private void Update()
  {
    //Aquí usarías el vector que regresa GetMovement de para mover tu jugador alguna manera
    playerMovement.GetMovement();
  }
}

//La palabra abstract aquí significa que el script no puede ser usado por sí solo, necesita que otro clase herede de ésta para usarlo.
public abstract class MovementProvider:MonoBehaviour
{
  //La palabra abstract aquí significa la funcionalidad de este método debe ser definida en las clases que hereden de ésta.
  public abstract Vector2 GetMovement();
}

//Nota como no heredamos de MonoBehaviour esta vez, sino de la clase abstracta MovementProvider.
//Cualquier otro script puede hacer lo mismo y definir su propia función para GetMovement
public class Joystick:MovementProvider
{
  //Override significa que estamos sobrescribiendo la funcionalidad definida en el padre, en este caso en MovementProvider.
  //Es cierto que, de hecho, MovementProvider no definió ninguna funcionalidad, lo dejó abstracto, pero igual hay que ponerlo.
  public override Vector2 GetMovement()
  {
    return new Vector2(0,0);
  }
}

Y dos es con algo llamado interfaces:

public class Player:MonoBehaviour
{
  public IMovementProvider playerMovement;
  
  private void Start()
  {
    //Como no podemos obtener la referencia a IMovementProvider desde el inspector, hay que obtenerla de otra manera. Puede ser así:
    playerMovement = GetComponent<IMovementProvider>();
    //Si el componente está en otro GameObject, podríamos poner un campo de tipo GameObject en el inspector y luego:
    playerMovement = otherGameObject.GetComponent<IMovementProvider>();
  }

  private void Update()
  {
    //Aquí usarías el vector que regresa GetMovement de para mover tu jugador alguna manera
    playerMovement.GetMovement();
  }
}

//Las interfaces definen un conjunto de métodos y propiedades que debe implementar una clase.
//La ventaja de las interfaces es que puede aplicarse más de una a la misma clase, la desventaja es que no salen en el inspector.
//Es común poner una I en el nombre para identificar que es una interfaz.
public interface IMovementProvider
{
  Vector2 GetMovement();
}

//Nota como avisamos que implementamos la interfaz. Si hay más interfaces, se pueden seguir agregando separadas por comas.
public class Joystick:MonoBehaviour, IMovementProvider
{
  //Con las interfaces no tenemos que usar override, basta que el método sea público.
  public Vector2 GetMovement()
  {
    return new Vector2(0,0);
  }
}


Respecto a tu segundo punto, generalmente, entre más puedas dividir tus scripts, mejor. La idea es que, entre menos cosas distintas haga un script, más probable es que los puedas reutilizar en varias partes diferentes. Y es menos probable que los tengas que modificar cuando otra cosa cambie en tu código.

Cualquier cosa que quede sin explicarse bien, o cualquier duda, tú dime con confianza. Ahm, espero no haber sido demasiado teórico o demasiado confuso; esto de lo que hablé viene de unos principios de programación llamados SOLID, que son muy útiles como guía para facilitarte la vida, pero que luego uno no sabe explicarlos bien porque ya se acostumbró tanto que ya ni piensa en ellos. Por último, estas recomendaciones que te di, no dejes que te atoren mucho; se aprende haciendo y además, en esto de hacer juegos, todo mundo acaba haciendo montón de excepciones a este tipo de reglas.

PD
Eso del game manager y las referencias estáticas yo realmente te recomendaría evitarlo siempre que puedas. Hay razones para hacerlo, como si nomás es un prototipo rápido, o un juego móvil simple, o ciertas cosas que es mucho más complejo hacer de otra forma. Pero, generalmente, ese patrón de organizar tu código que algunos llaman singleton, acaba dándote muchos más problemas de los que arregla. En el momento en el que decides, por ejemplo, que tu juego es multijugador, tienes que ponerte a rescribir código en todos los lados que usan esa referencia estática, en código que escribiste hace mucho tiempo y que vas a tener que releer completito para entender cómo cambiarlo.

Edited by OscarAbraham
Corrección
  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

×
×
  • Create New...