Estoy tratando de hacer que un rectángulo se mueva entre dos posiciones a las que me refiero como _positionA
y _positionB
. Ambos son de tipo Vector3
. El rectángulo se mueve bien. Sin embargo, cuando llega _positionB
no 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 if
declaraciones 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 Vector3
s?
fuente
Bools
gusta_atPosA
y_atPosB
. Inevitablemente, cometerá un error manteniéndolos sincronizados a ambos, y dará lugar a errores. Es mejor hacer un queenum
contenga 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.MoveTowards
var vec1 = new Vector3(1, 0, 0)
yvar vec2 = new Vector3(0, 1 ,0)
. ¿Esvec1 >= vec2
verdadero o falso?Respuestas:
Para simplificar la respuesta,
Vector3
es una costumbrestruct
proporcionada por elUnityEngine
espacio de nombres. Cuando creamos tiposclass
ostruct
tipos 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 == _positionB
tiene sentido, como podemos comprobar directamente losVector3.x
,Vector3.y
yVector3.z
los valores._rect_tfm.position >= _positionB
no tiene tanto sentido, debido al hecho de que aVector3
está representado por tres valores separados.Podríamos sobrecargar la
Vector3
clase para contener los operadores adecuados en teoría , pero eso parece bastante complicado. En cambio, sería más fácil simplemente extender laVector3
clase 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.Lerp
método; Si es así, lea más abajo.Agregar métodos de extensión a
Vector3
Como se mencionó anteriormente, aplicar
<=
o>=
aVector3
menudo es ilógico. Para el movimiento, probablemente desee leer más sobre elVector3.Lerp
mé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 <= Vector3
oVector3 >= Vector3
, propongo extender laVector3
clase para incluir métodos paraisGreaterOrEqual(Vector3 other)
yisLesserOrEqual(Vector3)
. Podemos añadir los métodos de extensión a unastruct
oclass
declarándolos en unastatic
clase que no hereda. También incluimos el objetivoclass
ostruct
como primer parámetro, usando lathis
palabra clave. Tenga en cuenta que en mi ejemplo, supongo que quiere asegurarse de que los tres valores principales (x
,y
yz
) 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
Vector3
clase,local
representaremos laVector3
instancia 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 susVector3
tipos.Moviéndose
Vector3
conVector3.Lerp
Llamar al
Vector3.Lerp
método nos permite determinar la posición exacta entre dosVector3
valores en un momento dado. Un beneficio adicional de este método es que elVector3
no sobrepase su objetivo .Vector3.Lerp
toma 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.Lerp
para pasar a atargetPosition
. Después de llamar alMove
método en cada unoUpdate
, podemos verificar si hemos alcanzado dicho objetivo;Lerp.Vector3
lo hará sin exceso, por lo quetransform.position == targetPosition
se convierte en fiable. Ahora podemos comprobar la posición y cambiar eltargetPosition
aleftPosition
orightPosition
invertir 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
>=
unVector3
tipo 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
Vector3
reemplaza==
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
Vector3
es 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.Approximately
debe 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 <= patrolEnd
en el eje X, peropatrolEnd <= myPosition <= patrolStart
en 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