TRaFuGa 0 Report post Posted August 5, 2020 (edited) Hola, he estado buscando por el foro e internet pero no he visto nada parecido a lo que quiero hacer. Tengo un mapa de 4x5 pantallas (dentro de una misma scene) con un tamaño establecido y fijo para cada pantalla (todas el mismo), el caso es que quiero hacer un sistema de cambio de pantalla (al pasar a la izquierda, derecha, arriba o abajo) y que la cámara se mueva y se ajuste a dicha pantalla (el efecto no es de mover, sino de cambiar, porque se le asignan las nuevas coordenadas a la cámara). El problema que tengo es en el proceso de cambio de pantalla (traspaso de pantalla del jugador). Tengo un trigger (con un edge collider, vertical u horizontal) y he probado dos formas de hacer el movimiento (que esto lo hace bien, pero el problema lo tengo al controlar cuando se hace...): -Pongo un trigger en cada zona de salida, con el edge collider pegado casi al final del tile, para asegurarme de que cuando traspasa dicho collider haga el cambio de pantalla que le he establecido por parámetros (por ejemplo, hacia la derecha) y controlando la dirección del personaje, de esta forma si pasa al contrario (ej: hacia la izquierda) no hace nada. -Pongo un solo trigger en el medio de los 2 tiles que dividen las pantallas, y dependiendo de la dirección del personaje muevo la cámara a dicha dirección. (Esta es la opción que tengo ahora, me parece más limpia, al tener menos triggers en el mapa) ¿El problema? Si voy ajustando el personaje despacito (y a veces no hace falta que vaya muy despacio), dicho cambio de cámara no se hace, o se hace doble... vamos, que funciona bien cuando quiere... En la captura se ve la zona de cambio (en este caso es de izquierda-derecha) y el trigger en verde en el medio Y este es el código del script asociado: using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerOutCam : MonoBehaviour { public enum direc { UP, DOWN, LEFT, RIGHT } public Camera Cam; public GameObject Player; public float CamHeigh=368f; public float CamWidth = 208f; //public direc Direccion = direc.UP; private int percent = 100; private Vector3 direction; private void Awake() { if (Player == null) { Player = GameObject.FindWithTag("Player"); } if (Cam == null) { Cam = GameObject.FindWithTag("MainCamera").GetComponent<Camera>(); } } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnTriggerEnter2D(Collider2D collision) { } private void OnTriggerExit2D(Collider2D collision) { direction = Player.transform.position - transform.position; //Debug.Log(direction.y); if (collision.gameObject.tag=="Player") { //bug.Log("Player.x: " + Player.transform.position.x); //Debug.Log("Triger.x " + this.gameObject.name + ":" + transform.position.x); float horizontalInput = Input.GetAxisRaw("Horizontal"); float vertical = Input.GetAxisRaw("Vertical"); Debug.Log("Direction: " + direction.x + " H: " + horizontalInput); if (direction.x < 0f && horizontalInput < 0f) //IZQUIERDA { Cam.transform.position = new Vector3(Cam.transform.position.x - (CamHeigh / percent), Cam.transform.position.y, Cam.transform.position.z); } if (direction.x > 0f && horizontalInput > 0f) //DERECHA { Cam.transform.position = new Vector3(Cam.transform.position.x + (CamHeigh / percent), Cam.transform.position.y, Cam.transform.position.z); } if (direction.y < 0f && vertical < 0f)//ABAJO { Cam.transform.position = new Vector3(Cam.transform.position.x, Cam.transform.position.y - (CamWidth / percent), Cam.transform.position.z); } if (direction.y > 0f && vertical >0f)//ARRIBA { Cam.transform.position = new Vector3(Cam.transform.position.x, Cam.transform.position.y + (CamWidth / percent), Cam.transform.position.z); } //Recuperamos todos los SpawnPoint de la escena GameObject[] spawn = GameObject.FindGameObjectsWithTag("SpawnPoint"); //Comprobamos que haya al menos 1 en la escena if (spawn != null) { //Por cada SpawnPoint de la escena hacemos las siguientes comprobaciones foreach (GameObject goSpawn in spawn) { //Creamos un punto que va desde la cámara hasta la posición del SpawnPoint Vector3 screenPoint = Cam.WorldToViewportPoint(goSpawn.transform.position); //Controlamos que el punto esté dentro de la visión de la cámara que será un rectángulo //que va desde 0-1 en su eje X y de 0-1 en su eje Y if (screenPoint.x>0 && screenPoint.x <1 && screenPoint.y>0 && screenPoint.y<1) { //En el caso de que este punto esté dentro de la visión //Se lo asignamos al Player como punto de Spawn Player.GetComponent<PlayerController>().SpawnPoint = goSpawn; //Retornamos y dejamos de buscar. return; } } } } } } El movimiento de la cámara funciona bien, lo que no me funciona correctamente es el ajuste de cuando se hace acorde al trigger que tengo, tampoco se si es la mejor manera de hacer algo de esto... A mayores, gestiono el punto de respawn del jugador, esto me funciona correctamente, aunque como siempre, lo mismo no es la mejor forma de hacerlo. Edited August 7, 2020 by TRaFuGa Encontrada solución Share this post Link to post Share on other sites
francoe1 536 Report post Posted August 5, 2020 Podrías optar por crear un Rectángulo (imaginario) para el "Player" y otro para "Final" luego en cada rectángulo final pondrías un componente que haga una comprobación AABB con el rect del Player, de este modo evitas utilizar físicas y omitís muchos problemas que esto conlleva. Share this post Link to post Share on other sites
TRaFuGa 0 Report post Posted August 6, 2020 Te refieres a hacerle un cuadrado (un collider?) para el personaje y otro para la entrada/salida de la pantalla? y comprobar si está dentro y se ha salido por uno de los lados?? Share this post Link to post Share on other sites
francoe1 536 Report post Posted August 6, 2020 Nop, me refiero a que no es necesario usar colisiones, simplemente definiendo la posición y tamaño de dos rectángulos podes hacer una comprobación AABB para saber si están colisionando. Share this post Link to post Share on other sites
nomoregames 35 Report post Posted August 6, 2020 también puedes usar un Distance y según la distancia que hay entre el personaje y el centro de la cámara empezar a trabajar Share this post Link to post Share on other sites
TRaFuGa 0 Report post Posted August 7, 2020 (edited) 14 hours ago, nomoregames said: también puedes usar un Distance y según la distancia que hay entre el personaje y el centro de la cámara empezar a trabajar Pues me parece buena idea, sabiendo el tamaño de la pantalla se puede hacer perfectamente, y así se controla si se ha salido por alguna de los 4 lados. Voy a intentarlo y os cuento. EDIT: Con una primera versión del movimiento, he conseguido que funcione mucho mejor que antes aunque tengo que seguir con las pruebas. Lo que hice fue sacar los límites de la cámara y según la X/Y del jugador, ya puedo controlar si se ha pasado por alguno de los lados y mover la cámara acorde a por dónde se ha salido, luego recupera nuevos límites. Aún tengo que pulirlo, sobre todo para buscar una solución a no tener que estar controlando las posiciones x e y del jugador en cada update 🙂 Edited August 7, 2020 by TRaFuGa Share this post Link to post Share on other sites
TRaFuGa 0 Report post Posted August 7, 2020 Voy a dejar el código del script por si a alguno le viene bien. Conseguí un trozo de internet que he usado: using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerInCam : MonoBehaviour { public Camera Cam; //Cámara que vamos a usar para hacer el movimiento public float CamHeigh=368f; //Tamaño de la cámara public float CamWidth = 208f; enum Direction {Left, Right, Up, Down}; //Enum para controlar a que dirección mover public bool mov = false; //Bool para controlar si estamos haciendo el movimiento de la cámara para no hacerlo doble private int percent = 100;//Porcentaje para ajustar el movimiento de la cámara private Limits val; //Valores de los límites de la pantalla private Transform _GameObject; //GameObject del personaje // Start is called before the first frame update void Start() { GetLimits(); //Recojemos la primera vez los límites de la pantalla _GameObject = GetComponent<Transform>();//Asignamos el transform del gameobject del player if (Cam == null) //En el caso de no haber asignado cámara, buscamos la maincamera { Cam = GameObject.FindWithTag("MainCamera").GetComponent<Camera>(); } } // Update is called once per frame void Update() { checkOutCam();//Método que comprueba si el player se ha salido de los límites de la cámara //if (!mov) // Debug.Log("Player:" + _GameObject.position.x + ":" + _GameObject.position.y ); } void checkOutCam(){ //Comprobamos si se ha salido desde algun lado de los límites y la cámara no se está moviendo //En el caso de que entre en algunos de los controles //Marcamos a true el movimiento y movemos la cámara en la dirección que deseamos if (_GameObject.position.x < val.Left && !mov) { //Debug.Log("LEFT"); mov = true; MoveCam(Direction.Left); } if (_GameObject.position.x > val.Right && !mov) { //Debug.Log("RIGHT"); mov = true; MoveCam(Direction.Right); } if (_GameObject.position.y < val.Bottom) { //Debug.Log("DOWN: " + _GameObject.position.y); mov = true; MoveCam(Direction.Down); } if (_GameObject.position.y > val.Top) { //Debug.Log("UP: " + _GameObject.position.y); mov = true; MoveCam(Direction.Up); } } private Limits GetLimits() { val=new Limits();//Generamos unos nuevos límites Vector3 lowerLeft = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 0)); //Recogemos el punto AbajoIzquierda Vector3 upperRight = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 0)); //Recogemos el punto ArribaDerecha //Con estos dos puntos, ya tenemos marcados los límites de la pantalla, recogiendo dichos límites en la variable val.Left = lowerLeft.x; val.Right = upperRight.x; val.Top = upperRight.y; val.Bottom = lowerLeft.y; //Debug.Log("Limits: " + val.Left +"|||" + val.Right + "|||" + val.Top + "|||" + val.Bottom); return val; } private void MoveCam(Direction dir){ //Movemos la cámara hacia la posición indicada switch (dir) { case Direction.Left: Cam.transform.position = new Vector3(Cam.transform.position.x - (CamHeigh / percent), Cam.transform.position.y, Cam.transform.position.z); break; case Direction.Right: Cam.transform.position = new Vector3(Cam.transform.position.x + (CamHeigh / percent), Cam.transform.position.y, Cam.transform.position.z); break; case Direction.Down: Cam.transform.position = new Vector3(Cam.transform.position.x, Cam.transform.position.y - (CamWidth / percent), Cam.transform.position.z); break; case Direction.Up: Cam.transform.position = new Vector3(Cam.transform.position.x, Cam.transform.position.y + (CamWidth / percent), Cam.transform.position.z); break; } GetLimits();//Volvemos a recoger los límites de la pantalla, ya que habrán cambiado con respecto al WorldSpace GetSpawnPoint();//Recogemos el punto de Spawn que hay en la pantalla mov = false;//Volvemos a poner a false el booleano para que si volvemos a cambiar de pantalla, se puedan hacer las comprobaciones } void GetSpawnPoint(){ //Recuperamos todos los SpawnPoint de la escena GameObject[] spawn = GameObject.FindGameObjectsWithTag("SpawnPoint"); //Comprobamos que haya al menos 1 en la escena if (spawn != null) { //Por cada SpawnPoint de la escena hacemos las siguientes comprobaciones foreach (GameObject goSpawn in spawn) { //Creamos un punto que va desde la cámara hasta la posición del SpawnPoint Vector3 screenPoint = Cam.WorldToViewportPoint(goSpawn.transform.position); //Controlamos que el punto esté dentro de la visión de la cámara que será un rectángulo //que va desde 0-1 en su eje X y de 0-1 en su eje Y if (screenPoint.x>0 && screenPoint.x <1 && screenPoint.y>0 && screenPoint.y<1) { //En el caso de que este punto esté dentro de la visión //Se lo asignamos al Player como punto de Spawn this.GetComponent<PlayerController>().SpawnPoint = goSpawn; //Retornamos y dejamos de buscar. return; } } } } public class Limits { public float Left { get; set; } public float Right { get; set; } public float Top { get; set; } public float Bottom { get; set; } } } Seguramente no sea la mejor opción el controlar en cada Update las coordenadas del Player para ver si se ha salido de los límites, pero no encontré ningún método que se ejecutara cuando el Player queda fuera de la visión de la cámara. Share this post Link to post Share on other sites