Estou tentando fazer com que um retângulo se mova entre duas posições às quais me refiro como _positionA
e _positionB
. Ambos são do tipo Vector3
. O retângulo se move muito bem. No entanto, quando chega _positionB
, não se move na direção oposta, como deveria.
Voltei ao código para dar uma olhada. Cheguei à conclusão de que, à medida que o objeto se movia, as if
instruções no código perdiam o quadro no qual a posição rects era igual _positionB
. Decidi modificar o código para inverter a direção se a posição rects for maior ou igual a _positionB
. Meu código não é muito longo, então eu o mostrarei abaixo:
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;
}
}
}
}
Quando eu mudei, no entanto, ele me avisou da seguinte mensagem de erro:
Operador> = não pode ser aplicado a operandos do tipo Vector3 e Vector3.
Isso me confunde por duas razões; primeiro, ambos os valores são do mesmo tipo de dados. Segundo, o uso do operador de comparação ( ==
) nos dois valores funciona sem erros. Por que não posso usar o operador >=
com Vector3
s?
fonte
Bools
como_atPosA
e_atPosB
. Inevitavelmente, você cometerá um erro ao manter os dois em sincronia, e isso causará bugs. É melhor criar umenum
contendo todas as posições (A, B, talvez outras no futuro), e usando isso>=
significar para umVector3
? Comparar componentes? Isso não seria um pedido total. Considere usarVector3.MoveTowards
var vec1 = new Vector3(1, 0, 0)
evar vec2 = new Vector3(0, 1 ,0)
. Évec1 >= vec2
verdadeira ou falsa?Respostas:
Para simplificar a resposta,
Vector3
é um costumestruct
fornecido peloUnityEngine
espaço para nome. Quando criamos tiposclass
ou personalizadosstruct
, também devemos definir seus operadores . Como tal, não há lógica padrão para o>=
operador. Como apontado por Evgeny Vasilyev ,_rect_tfm.position == _positionB
faz sentido, como podemos verificar diretamente asVector3.x
,Vector3.y
eVector3.z
valores._rect_tfm.position >= _positionB
não faz tanto sentido, devido ao fato de que aVector3
é representado por três valores separados.Poderíamos sobrecarregar a
Vector3
classe para conter os operadores adequados na teoria , mas isso parece bastante complicado. Em vez disso, seria mais fácil simplesmente estender aVector3
classe com um método adequado . Dito isto, parece que você pretende usar essa lógica para o movimento. Como tal, você pode achar muito mais fácil usar oVector3.Lerp
método; Nesse caso, leia mais abaixo.Adicionando métodos de extensão a
Vector3
Como mencionado anteriormente, aplicar
<=
ou>=
a umVector3
é frequentemente ilógico. Para movimento, você provavelmente deseja ler mais sobre oVector3.Lerp
método. Dito isto, você pode aplicar a<=
=>
aritmética por outros motivos, portanto, darei uma alternativa fácil.Em vez de aplicar a lógica de
Vector3 <= Vector3
ouVector3 >= Vector3
, proponho estender aVector3
classe para incluir métodos paraisGreaterOrEqual(Vector3 other)
eisLesserOrEqual(Vector3)
. Podemos adicionar métodos de extensão astruct
ouclass
declarando-os em umastatic
classe que não herda. Também incluímos o destinoclass
oustruct
como o primeiro parâmetro, usando athis
palavra - chave Observe que, no meu exemplo, suponho que você queira garantir que todos os três valores principais (x
,y
ez
) sejam todos maiores ou iguais, ou menores ou iguais, respectivamente. Você pode fornecer sua própria lógica, aqui, conforme necessário.Quando tentamos chamar esses métodos da
Vector3
classe,local
representamos aVector3
instância da qual estamos chamando o método. Você observará que os métodos sãostatic
; métodos de extensão devem serstatic
, mas você ainda precisa chamá-los de uma instância. Dado os métodos de extensão acima, agora você pode aplicá-los diretamente aos seusVector3
tipos.Movendo-se
Vector3
comVector3.Lerp
Chamar o
Vector3.Lerp
método nos permite determinar a posição exata entre doisVector3
valores em um determinado momento. Um benefício adicional desse método é que oVector3
não ultrapassará seu objetivo .Vector3.Lerp
leva três parâmetros; a posição inicial, a posição final e a posição atual representada como um valor entre 0 e 1. Ela gera a posição resultante como aVector3
, a qual podemos definir diretamente como a posição atual.Resolvendo o seu problema, proponho usar
Vector3.Lerp
a mudança para atargetPosition
. Depois de chamar oMove
método em cada umUpdate
, podemos verificar se atingimos o objetivo;Lerp.Vector3
vai não ultrapassagem, por issotransform.position == targetPosition
torna-se confiável. Agora podemos verificar a posição e alterartargetPosition
paraleftPosition
ourightPosition
para reverter o movimento, de acordo.Você pode ver isso demonstrado na animação a seguir. Traduzo o cubo azul com
Vector3.LerpUnclamped
, o que nos dá um resultado semelhante à tradução desmarcada simples. Eu traduzo o cubo vermelho usandoVector3.Lerp
. Deixado desmarcado, o cubo azul se move para o esquecimento; enquanto o cubo vermelho para exatamente onde eu pretendo. Você pode ler mais sobre esse tipo de movimento na documentação Estouro de pilha .fonte
Definir
>=
para umVector3
tipo não faz sentido. O que determina se um vetor é maior que outro? Sua magnitude ou seus componentes individuais x, y, z?Um vetor é uma magnitude e uma direção. Então, o que determina qual direção é maior?
Se você precisar comparar as magnitudes, poderá usar
sqrMagnitude
.Nesse caso,
Vector3
substitui-o==
para simplesmente comparar os diferentes componentes para ver se são iguais. (dentro de um limite)Esta é a mesma razão pela qual multiplicar dois vetores usando
*
não é possível. Simplesmente não existe uma maneira matemática de fazê-lo. Algumas pessoas usam*
para produtos pontuais, mas esse é um design de API pouco claro.fonte
Vector3
é umstruct
, então o parágrafo sobre comparação de referências não está certo.Essa é uma pergunta antiga, mas para termos menos técnicos, um Vector3 é um "contêiner" para três valores flutuantes - x, y, z.
Você pode comparar valores individuais, como comparar os valores x de dois Vector3s, porque são apenas números.
No entanto, um Vector3 inteiro não pode ser comparado a outro Vector3 porque não há um valor único que possa ser usado para comparar os dois.
fonte
Apenas adicionando ao que o Gnemlock postou, sobre a adição de métodos de extensão à classe Vector3. Há um problema no Unity (e eu tenho certeza que outros mecanismos de jogos) ao usar certos operadores de comparação (
==
,<=
e>=
) entre dois valores flutuantes, devido à maneira como o cálculo do ponto flutuante é tratado.Mathf.Approximately
deve ser usado, portanto, os seguintes métodos de extensão podem ser adicionados para verificar se dois vetores são> = ou <= um ao outro:fonte
Eu gostaria de propor uma maneira diferente de interpretar essa pergunta. Um padrão de código como este:
está basicamente tentando usar os operadores
>=
/<=
como "o lado esquerdo alcançou ou passou pelo lado direito?" testes.Usar
>=
/<=
para significar "alcançado ou ultrapassado" faz sentido no sentido unidimensional, se minha posição for apenas uma flutuação:Porém, no espaço 3D, não temos uma única linha para medir, para decidir qual lado é "alto / distante" e qual lado é "baixo / próximo". Por exemplo, poderíamos estar tentando patrulhar entre os pontos
Então agora esperamos
patrolStart <= myPosition <= patrolEnd
no eixo X, maspatrolEnd <= myPosition <= patrolStart
no eixo Z. Nosso operador "alcançado ou passado" é diferente de um eixo para outro, portanto, não há mais um mapeamento claro entre nosso conceito de passar um limite e uma simples verificação de desigualdade.Mas há uma maneira de escolher apenas uma linha no espaço 3D e fazer com que nosso
>=
/<=
se comporte como o caso de flutuação única ao longo dessa linha que escolhemos:Como bônus, se você normalizar o vetor do eixo antes de usá-lo, todos os produtos pontuais representam distâncias, para que você possa medir exatamente a que distância está de cada extremidade, ao longo do eixo da viagem.
fonte