Estoy tratando de hacer que un rectángulo se mueva entre dos posiciones a las que me refiero como _positionAy _positionB. Ambos son de tipo Vector3. El rectángulo se mueve bien. Sin embargo, cuando llega _positionBno se mueve en la dirección opuesta, como debería.
Regresé al código para echar un vistazo. Llegué a la conclusión de que a medida que el objeto se movía, las ifdeclaraciones en el código perdieron el marco en el que la posición de los rectificadores era igual _positionB. Decidí modificar el código para invertir la dirección si la posición de los rectificadores es mayor o igual que _positionB . Mi código no es demasiado largo, así que lo mostraré a continuación:
using UnityEngine;
using System.Collections;
public class Rectangle : MonoBehaviour
{
private Vector3 _positionA = new Vector3(-0.97f, -4.28f); //Start position
private Vector3 _positionB = new Vector3(11.87f, -4.28f); //End position
private Transform _rect_tfm;
private bool _atPosA = false, _atPosB = false;
public Vector2 speed = new Vector2(1f, 0f);
private void Start()
{
_rect_tfm = gameObject.GetComponent<Transform>();
_rect_tfm.position = _positionA;
_atPosA = true;
}
private void Update()
{
/*NOTE: Infinite loops can cause Unity to crash*/
Move();
}
private void Move()
{
if (_atPosA)
{
_rect_tfm.Translate(speed * Time.deltaTime);
if (_rect_tfm.position == _positionB)
{
_atPosA = false;
_atPosB = true;
}
}
if (_atPosB)
{
_rect_tfm.Translate(-speed * Time.deltaTime);
if (_rect_tfm.position == _positionA)
{
_atPosA = true;
_atPosB = false;
}
}
}
}
Cuando lo cambié, sin embargo, me advirtió del siguiente mensaje de error:
Operador> = no se puede aplicar a operandos de tipo Vector3 y Vector3.
Esto me confunde por dos razones; primero, ambos valores son del mismo tipo de datos. Segundo, usar el operador de comparación ( ==) en los dos valores funciona sin error. ¿Por qué no puedo usar el operador >=con Vector3s?
fuente

Boolsgusta_atPosAy_atPosB. Inevitablemente, cometerá un error manteniéndolos sincronizados a ambos, y dará lugar a errores. Es mejor hacer un queenumcontenga todas las posiciones (A, B, quizás otras en el futuro), y usar eso>=significar para aVector3? ¿Comparar componentes sabios? Eso no sería un pedido total. Considere usarVector3.MoveTowardsvar vec1 = new Vector3(1, 0, 0)yvar vec2 = new Vector3(0, 1 ,0). ¿Esvec1 >= vec2verdadero o falso?Respuestas:
Para simplificar la respuesta,
Vector3es una costumbrestructproporcionada por elUnityEngineespacio de nombres. Cuando creamos tiposclassostructtipos personalizados , también debemos definir sus operadores . Como tal, no existe una lógica predeterminada para el>=operador. Como ha señalado Evgeny Vasilyev ,_rect_tfm.position == _positionBtiene sentido, como podemos comprobar directamente losVector3.x,Vector3.yyVector3.zlos valores._rect_tfm.position >= _positionBno tiene tanto sentido, debido al hecho de que aVector3está representado por tres valores separados.Podríamos sobrecargar la
Vector3clase para contener los operadores adecuados en teoría , pero eso parece bastante complicado. En cambio, sería más fácil simplemente extender laVector3clase con un método adecuado . Dicho esto, parece que tienes la intención de utilizar esta lógica para el movimiento. Como tal, puede resultarle mucho más fácil usar elVector3.Lerpmétodo; Si es así, lea más abajo.Agregar métodos de extensión a
Vector3Como se mencionó anteriormente, aplicar
<=o>=aVector3menudo es ilógico. Para el movimiento, probablemente desee leer más sobre elVector3.Lerpmétodo. Dicho esto, es posible que desee aplicar la<==>aritmética por otras razones, por lo que le daré una alternativa fácil.En lugar de aplicar la lógica de
Vector3 <= Vector3oVector3 >= Vector3, propongo extender laVector3clase para incluir métodos paraisGreaterOrEqual(Vector3 other)yisLesserOrEqual(Vector3). Podemos añadir los métodos de extensión a unastructoclassdeclarándolos en unastaticclase que no hereda. También incluimos el objetivoclassostructcomo primer parámetro, usando lathispalabra clave. Tenga en cuenta que en mi ejemplo, supongo que quiere asegurarse de que los tres valores principales (x,yyz) son todos mayores o iguales, o menores o iguales, respectivamente. Puede proporcionar su propia lógica, aquí, según lo requiera.Cuando intentemos llamar a estos métodos desde la
Vector3clase,localrepresentaremos laVector3instancia desde la que estamos llamando al método. Notarás que los métodos sonstatic; los métodos de extensión deben serstatic, pero aún debe llamarlos desde una instancia. Dado los métodos de extensión anteriores, ahora puede aplicarlos directamente a susVector3tipos.Moviéndose
Vector3conVector3.LerpLlamar al
Vector3.Lerpmétodo nos permite determinar la posición exacta entre dosVector3valores en un momento dado. Un beneficio adicional de este método es que elVector3no sobrepase su objetivo .Vector3.Lerptoma tres parámetros; la posición inicial, la posición final y la posición actual representada como un valor entre 0 y 1. Produce la posición resultante como aVector3, que podemos establecer directamente como la posición actual.Para resolver su problema, propongo usar
Vector3.Lerppara pasar a atargetPosition. Después de llamar alMovemétodo en cada unoUpdate, podemos verificar si hemos alcanzado dicho objetivo;Lerp.Vector3lo hará sin exceso, por lo quetransform.position == targetPositionse convierte en fiable. Ahora podemos comprobar la posición y cambiar eltargetPositionaleftPositionorightPositioninvertir el movimiento, en consecuencia.Puede ver esto demostrado en la siguiente animación. Traduzco el cubo azul con
Vector3.LerpUnclamped, lo que nos da un resultado similar a la traducción simple no verificada. Traduzco el cubo rojo usandoVector3.Lerp. Si no se controla, el cubo azul se va al olvido; mientras que el cubo rojo se detiene exactamente donde lo pretendo. Puede leer más sobre este tipo de movimiento en la documentación de Stack Overflow .fuente
Definir
>=unVector3tipo no tiene sentido. ¿Qué determina si un vector es mayor que otro? ¿Su magnitud o sus componentes individuales x, y, z?Un vector es una magnitud y una dirección. Entonces, ¿qué determina qué dirección es mayor?
Si necesita comparar las magnitudes que puede usar
sqrMagnitude.En este caso, se
Vector3reemplaza==simplemente comparar los diferentes componentes para ver si son iguales. (dentro de un umbral)Esta es la misma razón por la que
*no es posible multiplicar dos vectores usando . Simplemente no hay forma matemática de hacerlo. Algunas personas usan*productos de punto, pero ese es un diseño de API poco claro.fuente
Vector3es unstruct, así que el párrafo sobre comparación de referencias no es del todo correcto.Esta es una vieja pregunta, pero para ponerla en términos menos técnicos, un Vector3 es un "contenedor" para 3 valores flotantes: x, y, z.
Puede comparar valores individuales, como comparar los valores de x de dos Vector3, porque son solo números.
Sin embargo, un Vector3 completo no se puede comparar con otro Vector3 porque no hay un solo valor que se pueda usar para comparar los dos.
fuente
Simplemente agregue a lo que Gnemlock publicó, con respecto a agregar métodos de extensión a la clase Vector3. Hay un problema en la unidad (y estoy seguro que otros motores de juego) cuando se utilizan ciertos operadores de comparación (
==,<=y>=) entre dos valores de coma flotante, debido a cómo se maneja el cálculo de coma flotante.Mathf.Approximatelydebe usarse en su lugar, por lo tanto, se pueden agregar los siguientes métodos de extensión para verificar si dos vectores son> = o <= entre sí:fuente
Me gustaría proponer una forma diferente de interpretar esta pregunta. Un patrón de código como este:
básicamente está tratando de usar los operadores
>=/<=como "¿el lado izquierdo alcanzó o pasó el lado derecho?" pruebasUsar
>=/<=para significar "alcanzado o pasado" tiene sentido en un sentido unidimensional, si mi posición es solo un flotador:Pero en el espacio 3D no tenemos una sola línea para medir, para decidir qué lado es "alto / lejano" y qué lado es "bajo / cercano". Por ejemplo, podríamos estar intentando patrullar entre los puntos
Así que ahora esperamos
patrolStart <= myPosition <= patrolEnden el eje X, peropatrolEnd <= myPosition <= patrolStarten el eje Z. Nuestro operador "alcanzado o pasado" es diferente de un eje a otro, por lo que ya no hay un mapeo claro entre nuestro concepto de pasar un umbral y una simple verificación de desigualdad.Pero, hay una forma en que podemos elegir una sola línea en el espacio 3D y hacer que nuestro
>=/ se<=comporte como el caso de flotación única a lo largo de esta línea que elegimos:Como beneficio adicional, si normaliza el vector del eje antes de usarlo, todos los productos de puntos representan distancias, por lo que puede medir exactamente qué tan lejos está de cada extremo, a lo largo del eje de desplazamiento.
fuente