Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Resetear posicion waypoint

Iniciado por brok, Enero 08, 2018, 12:12:43 AM

Tema anterior - Siguiente tema
Enero 08, 2018, 12:12:43 AM Ultima modificación: Enero 08, 2018, 12:13:30 AM por brok
Hola bunas, estoy intentando que un coche resetee la posición por waypoint, y no me sale nada no se que hago mal alguna ayuda por favor, este es parte del script:
 

private Transform[] WayPoints;
void Start
{
WayPoints = GameObject.Find("WaypointVuelco").GetComponentsInChildren<Transform>();
}
     
void OnTriggerEnter(Collider colision)
 {
     if (colision.gameObject.CompareTag("Terreno"))
     {
         for (int i = 0; i < WayPoints.Length; i++)
         {
             transform.position = WayPoints[i].transform.position;
         }
     }
 }                                            

 
No se la verdad que creo que es por hay el camino pero no hace nada.

A bote pronto si el collider no esta en la misma posicion exacta que el waypoint el codigo fallara. Y sobre todo revisa el tema tags por si te has dejado alguna sin asignar

Gracias Eskema, mi intención es que el coche cuando vuelque  se posicione en el waypoint mas cercano, ¿Cómo podría hacerlo?.
Lo he probado con un input en un if y no funciona. Tendre que investigar a ver pero que ya estoy que no encuentro nada.

Podrias hacer un arreglo con waypoints que recorran todo el circuito y luego lo agregar a un arreglo 
 
por otro lado cuando el coche se da vuelta buscas en el arreglo el waypoints con menor distancia al player.

Gracias francoe1 voy a ver si funciona.
 
Tengo echo esto :
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WayPointVuelco : MonoBehaviour {
    public Color rayColor = Color.blue;
    public List<Transform> listTransObj = new List<Transform>();
    private Transform[] TransArray;
    void OnDrawGizmos()
    {
        Gizmos.color = rayColor;
        TransArray = GetComponentsInChildren<Transform>();
        listTransObj.Clear();
        foreach(Transform transObj in TransArray)
        {
            if(transObj != transform)
            {
                listTransObj.Add(transObj);
            }
        }
        for(int i = 0; i < listTransObj.Count; i++)
        {
            Vector3 posicion = listTransObj[i].position;
            if (i > 0)
            {
                Vector3 previo = listTransObj[i - 1].position;
                Gizmos.DrawLine(previo, posicion);
                Gizmos.DrawWireSphere(posicion, 50f);
            }
        }
    }
}

 
son el array de waypoint y lo tengo por todo el circuito pero no se como puedo hacerlo.
 
Este script va vinculado a WaypointVuelco.
 
He echo esto pero se posiciona en el ultimo waypoint:
 

private Transform player;
private WayPointVuelco vuelcoWaypoint;
void Start()
{
player = GameObject.FindWithTag("Player").transform;
    vuelcoWaypoint = GameObject.Find("WaypointVuelco").GetComponent<WayPointVuelco>();
}
void Update()
{
if (Input.GetKey(KeyCode.R))
    {
       for (int i = 0; i < vuelcoWaypoint.listTransObj.Count; i++)
       {
          player.transform.position = vuelcoWaypoint.listTransObj[i].transform.position;
       }
    }
}

 
 

Cita de: brok date=1515371085He echo esto pero se posiciona en el ultimo waypoint:
   


Hola, lo que pasa es que en el for siempre salis al recorrer toda la lista, es decir al pasar por el último elemento:
 

for (int i = 0; i < vuelcoWaypoint.listTransObj.Count; i++)
       {
          player.transform.position = vuelcoWaypoint.listTransObj[i].transform.position;
       }

 
-> Si querés obtener el último lo que podés hacer es:
 


  1.    detectar que llegaste a un waypoint de la forma que quieras, trigger o distancia, me parece que depende de la pista que tengas, si querés ser más preciso o no, yo usaría un trigger por prolijidad.


  2.    almacenar la posición que ocupa en la lista el waypoint de 1. (en un int por ej)


  3.    cuando se de el reset (apretás la R) lo que hacés es llevar al coche a la posición del waypoint (o alguna posición linkeada a este)


Entonces la parte del reset te quedaría:
 

if(reset)
player.transform.position = vuelcoWaypoint.listTransObj[lastWaypoint].transform.position;

 
en donde "lastWaypoint" lo vas a ir actualizando a medida que vas arribando a distintos puntos.
 
Saludos

Como te ha dicho lightbug te posicionas en el ultimo waypoint porque tu codigo hace eso, recorres la lista y te paras en el ultimo elemento, es logico que te pille solo el ultimo waypoint.
 
Tienes que hacer algun check para saber que waypoint quieres y una vez encontrado salir del loop,
 

if (player.position == lista.position) {
player.position = lista.position;
break;
}

 
Ten en cuenta que esto NO funciona porque las posiciones NUNCA son exactas, en vez de == deberas buscar el mas aproximado, pero te sirve para hacerte una idea de lo que necesitas

A ver, lo tenes que hacer es un arreglo de WayPoints este mismo puede ser de tipo transform, a cada WayPoints le agregas un TAG especial para identificarlos, luego desde una función awake asignas el arreglo.
 
 
 

public class WayPointManager : MonoBehaviour
{
    private GameObject[] _waypoints;
private void Awake()
    {
       _waypoints = GameObject.FindGameObjectsWithTag("WayPoint");
    }
      public Vector3 GetNear(Vector3 from)
      {
         int index = -1;
         float distance = 100000;
         for(int i = 0; i < _waypoints.Length; i++)
         {
            float tmpdistance = (_waypoints.transform - from).magnitude;
            if(tmpdistance < distance)
            {
               index = i;
               distance = tmpdistance;
            }
         }
         return _waypoints[index].transform.position;
      }
}

 
De esa manera podes hacerlo ...

Enero 08, 2018, 07:40:45 PM #8 Ultima modificación: Enero 08, 2018, 08:05:54 PM por brok
Gracias a los 3 pero tengo mis dudas todavía, os pongo lo que estoy haciendo:
 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VuelcoCoche : MonoBehaviour
{
        public Vector3 Posicion;
        public Quaternion Rotacion;
        private GameObject[] WayPoints;
        private Transform player;
       
        public Vector3 Resetear;
        void Start()
        {
            player = GameObject.FindGameObjectWithTag("Player").transform;
            WayPoints = GameObject.FindGameObjectsWithTag("WaypointVuelco");
           
            Posicion = transform.position;
            Rotacion = transform.rotation;
        }
        void Update()
        {
            if (Input.GetKey(KeyCode.R))
            {
                ResetarCoche();
               
            }
            Posicion = player.transform.position;
            Rotacion = player.transform.rotation;
           StartCoroutine(Guardar_Posicion());
           StartCoroutine(Guardar_Rotacion());
 
        }
       
        Vector3 ResetarCoche()
        {
            int index = -1;
            float distancia = 100000;
           
           
            for (int i = 0; i < WayPoints.Length; i++)
            {
                float tmpDistancia = (WayPoints[i].transform.position - Cargar_Posicion()).magnitude;
               
                if (tmpDistancia < distancia)
                {
                    index = i;
                    distancia = tmpDistancia;
                    player.transform.position = WayPoints[i].transform.position;
                    player.transform.rotation = Cargar_Rotacion();
                }
            }
            return WayPoints[index].transform.position;
           
        }
       
        void OnTriggerEnter(Collider colision)
        {
            if (colision.gameObject.CompareTag("Terreno"))
            {
                ResetarCoche();
               
            }
        }
         
         
       
        IEnumerator Guardar_Posicion()
        {
            yield return new WaitForSeconds(5f);
            PlayerPrefs.SetFloat("x", Posicion.x);
            PlayerPrefs.SetFloat("y", Posicion.y);
            PlayerPrefs.SetFloat("z", Posicion.z);
        }
       IEnumerator Guardar_Rotacion()
        {
            yield return new WaitForSeconds(5f);
            PlayerPrefs.SetFloat("x", Rotacion.x);
            PlayerPrefs.SetFloat("y", Rotacion.y);
            PlayerPrefs.SetFloat("z", Rotacion.z);
        }
        Vector3 Cargar_Posicion()
        {
            PlayerPrefs.GetFloat("x", Posicion.x);
            PlayerPrefs.GetFloat("y", Posicion.y);
            PlayerPrefs.GetFloat("z", Posicion.z);
            return Posicion;
        }
        Quaternion Cargar_Rotacion()
        {
            PlayerPrefs.GetFloat("x", Rotacion.x);
            PlayerPrefs.GetFloat("y", Rotacion.y);
            PlayerPrefs.GetFloat("z", Rotacion.z);
            return Rotacion;
        }
}

 
Y me decis en que fallo por favor quiero que carge la posición anterior y se que la estoy liando porque no me funciona.
 
Pongo un video de lo que hace:
 
20180108_195642.mp4
 
Mi intención es que cargue la posición de hace 5 segundos aproximándose al waypoint

Enero 08, 2018, 08:26:21 PM #9 Ultima modificación: Enero 08, 2018, 09:07:19 PM por francoe1
Si lo que quieres hacer es que el auto vuelva a un tiempo atras deberias guardar los datos relevantes en una lista, esto puede ser cada x segundos requiera la interpolación aplicada luego.
 

public class Snapshot
{
public Vector3 Position { get; private set; }
public Quaternion Rotation { get; private set; }
public Snapshot(Vector3 pos, Quaternion rot)
{
   Position = pos;
   Rotation = rot;
}
}
public class SnapshotControl
{
private Queue<Snapshot> _snapshots = new Queue<Snapshot>();
private int _maxSnapshots = 200;
public SnapshotControl(int max)
{
   _maxSnapshots = max;
}
public void Register(Transform t)
{
   _snapshots.Enqueue(new Snapshot(t.position, t.rotation));
   if(_snapshots.Count > _maxSnapshots)
      _snapshots.Dequeue();
}
public Snapshot Get()
{
   if(_snapshots.Count > 0)
      return _snapshots.Dequeue();
   return null;
}
 
public void Clear()
{
   _snapshots.Clear();
}
}

 
De esa manera podrias hacerlo ----

Gracias franco1 voy a probar pero no se muy bien como va todavía mil gracias.
Me falta un using y no se cual es no lo encuentro.

Cita de: brok date=1515440014Gracias franco1 voy a probar pero no se muy bien como va todavía mil gracias.
   


Por otro lado creo que no estas entendiendo el uso de la Corrutinas, estas no tendrian ninguna diferencia con llamar simplemente la función desde Update, es mas es inutil la implementación.
 
Una corrutina simplemente agrega la "Funcion" a una lista, y esta lista es iterada luego de la función update y otra vez luego de la llamada de MGUI para trabajar con la clase WaitEndFrame - Por esta razón lo que estás haciendo es meter la función para que sea evaluada y quitarla inmediatamente de la lista, esto hace que tu función update tengo un costo de ejecución mayor.
 
Otro error es guardar los datos en un player prefab, ¿Sabes como funciona esto? --- 

Cita de: francoe1 date=1515441672Por otro lado creo que no estas entendiendo el uso de la Corrutinas, estas no tendrian ninguna diferencia con llamar simplemente la función desde Update, es mas es inutil la implementación.
   
   
      Una corrutina simplemente agrega la "Funcion" a una lista, y esta lista es iterada luego de la función update y otra vez luego de la llamada de MGUI para trabajar con la clase WaitEndFrame - Por esta razón lo que estás haciendo es meter la función para que sea evaluada y quitarla inmediatamente de la lista, esto hace que tu función update tengo un costo de ejecución mayor.
   
   
      Otro error es guardar los datos en un player prefab, ¿Sabes como funciona esto? --- 
   


Pues la verdad esque no estoy muy liado

Cita de: brok date=1515440014Gracias franco1 voy a probar pero no se muy bien como va todavía mil gracias.
   
   
      Me falta un using y no se cual es no lo encuentro.
   
   
      
   


System.Collections


Etiquetas: