J'essaie d'obtenir un rectangle pour se déplacer entre deux positions que j'appelle _positionA
et _positionB
. Les deux sont de type Vector3
. Le rectangle se déplace très bien. Cependant, lorsqu'il atteint, _positionB
il ne se déplace pas dans la direction opposée, comme il se doit.
Je suis retourné dans le code pour y jeter un œil. J'en suis venu à la conclusion que lorsque l'objet se déplaçait, les if
instructions du code manquaient le cadre dans lequel la position des rects était égale à _positionB
. J'ai décidé de modifier le code pour inverser la direction si la position de rects est supérieure ou égale à _positionB
. Mon code n'est pas trop long, je vais donc l'afficher ci-dessous:
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;
}
}
}
}
Cependant, lorsque je l'ai modifié, il m'a averti du message d'erreur suivant:
L'opérateur> = ne peut pas être appliqué aux opérandes de type Vector3 et Vector3.
Cela m'embrouille pour deux raisons; tout d'abord, les deux valeurs sont du même type de données. Deuxièmement, l'utilisation de l'opérateur de comparaison ( ==
) sur les deux valeurs fonctionne sans erreur. Pourquoi ne puis-je pas utiliser l'opérateur >=
avec Vector3
s?
la source
Bools
comme_atPosA
et_atPosB
. Inévitablement, vous ferez une erreur en les synchronisant tous les deux, et cela entraînera des bugs. Il est préférable de créer unenum
contenant toutes les positions (A, B, peut-être d'autres à l'avenir), et d'utiliser cela>=
signifier pour unVector3
? Comparer au niveau des composants? Ce ne serait pas une commande totale. Pensez à utiliserVector3.MoveTowards
var vec1 = new Vector3(1, 0, 0)
etvar vec2 = new Vector3(0, 1 ,0)
. Est-cevec1 >= vec2
vrai ou faux?Réponses:
Pour simplifier la réponse,
Vector3
une coutume eststruct
fournie par l'UnityEngine
espace de noms. Lorsque nous créons des typesclass
ou desstruct
types personnalisés , nous devons également définir ses opérateurs . En tant que tel, il n'y a pas de logique par défaut pour l'>=
opérateur. Comme l' a souligné Evgeny Vassiliev ,_rect_tfm.position == _positionB
est logique, comme nous pouvons vérifier directement lesVector3.x
,Vector3.y
et lesVector3.z
valeurs._rect_tfm.position >= _positionB
n'a pas autant de sens, car aVector3
est représenté par trois valeurs distinctes.Nous pourrions surcharger la
Vector3
classe pour contenir les opérateurs appropriés en théorie , mais cela semble plutôt compliqué. Au lieu de cela, il serait plus facile d' étendre simplement laVector3
classe avec une méthode appropriée . Cela étant dit, il semble que vous ayez l'intention d'utiliser cette logique pour le mouvement. En tant que tel, vous pourriez trouver beaucoup plus facile d'utiliser laVector3.Lerp
méthode; si oui, lisez plus loin ci-dessous.Ajout de méthodes d'extension à
Vector3
Comme mentionné précédemment, l'application
<=
ou>=
à unVector3
est souvent illogique. Pour le mouvement, vous voudrez probablement lire plus loin pour laVector3.Lerp
méthode. Cela dit, vous voudrez peut-être appliquer l'<=
=>
arithmétique pour d'autres raisons, je vais donc vous donner une alternative facile.Au lieu d'appliquer la logique de
Vector3 <= Vector3
ouVector3 >= Vector3
, je propose d'étendre laVector3
classe pour inclure les méthodes deisGreaterOrEqual(Vector3 other)
etisLesserOrEqual(Vector3)
. Nous pouvons ajouter des méthodes d'extension à astruct
ouclass
en les déclarant dans unestatic
classe qui n'hérite pas. Nous incluons également la cibleclass
oustruct
comme premier paramètre, en utilisant lethis
mot - clé. Notez que dans mon exemple, je suppose que vous voulez vous assurer que les trois valeurs principales (x
,y
etz
) sont toutes respectivement supérieures ou égales, ou inférieures ou égales. Vous pouvez fournir votre propre logique, ici, selon vos besoins.Lorsque nous tentons d'appeler ces méthodes à partir de la
Vector3
classe,local
représentera l'Vector3
instance à partir de laquelle nous appelons la méthode. Vous noterez que les méthodes sontstatic
; les méthodes d'extension doivent l' êtrestatic
, mais vous devez toujours les appeler à partir d'une instance. Compte tenu des méthodes d'extension ci-dessus, vous pouvez désormais les appliquer directement à vosVector3
types.Se déplacer
Vector3
avecVector3.Lerp
L'appel de la
Vector3.Lerp
méthode nous permet de déterminer la position exacte entre deuxVector3
valeurs à un instant donné. Un autre avantage de cette méthode est que laVector3
ne sera pas dépasser son objectif .Vector3.Lerp
prend trois paramètres; la position de départ, la position de fin et la position actuelle représentées comme une valeur comprise entre 0 et 1. Il affiche la position résultante sous la forme aVector3
, que nous pouvons définir directement comme position actuelle.Pour résoudre votre problème, je propose d'utiliser
Vector3.Lerp
pour passer à atargetPosition
. Après avoir appelé laMove
méthode dans chacunUpdate
, nous pouvons vérifier si nous avons atteint ladite cible;Lerp.Vector3
sera pas remise des gaz, donctransform.position == targetPosition
devient fiable. Nous pouvons maintenant vérifier la position et modifier letargetPosition
enleftPosition
ourightPosition
pour inverser le mouvement en conséquence.Vous pouvez le voir dans l'animation suivante. Je traduis le cube bleu avec
Vector3.LerpUnclamped
, ce qui nous donne un résultat similaire à une simple traduction non contrôlée. Je traduis le cube rouge en utilisantVector3.Lerp
. Sans coche, le cube bleu s'éloigne dans l'oubli; tandis que le cube rouge s'arrête exactement là où je le souhaite. Vous pouvez en savoir plus sur ce type de mouvement dans la documentation Stack Overflow .la source
La définition
>=
d'unVector3
type n'a aucun sens. Qu'est-ce qui détermine si un vecteur est supérieur à un autre? Leur ampleur ou leurs composantes individuelles x, y, z?Un vecteur est une grandeur et une direction. Alors, qu'est-ce qui détermine quelle direction est la plus grande?
Si vous devez comparer les grandeurs que vous pouvez utiliser
sqrMagnitude
.Dans ce cas
Vector3
overrides==
de comparer simplement les différents composants pour voir si elles sont les mêmes. (dans un seuil)C'est la même raison pour laquelle la multiplication de deux vecteurs à l'aide
*
n'est pas possible. Il n'y a tout simplement aucun moyen mathématique de le faire. Certaines personnes utilisent*
pour le produit scalaire, mais il s'agit d'une conception d'API peu claire.la source
Vector3
est unstruct
, donc le paragraphe sur la comparaison des références n'est pas tout à fait correct.C'est une vieille question mais pour mettre en termes moins techniques, un Vector3 est un "conteneur" pour 3 valeurs flottantes - x, y, z.
Vous pouvez comparer des valeurs individuelles, telles que la comparaison des valeurs x de deux Vector3, car ce ne sont que des nombres.
Cependant, un Vector3 entier ne peut pas être comparé à un autre Vector3 car il n'y a pas une seule valeur qui peut être utilisée pour comparer les deux.
la source
Il suffit d'ajouter à ce que Gnemlock a publié, concernant l'ajout de méthodes d'extension à la classe Vector3. Il y a un problème dans Unity (et je suis sûr que d'autres moteurs de jeu) lors de l'utilisation de certains opérateurs de comparaison (
==
,<=
et>=
) entre deux valeurs flottantes, en raison de la façon dont le calcul en virgule flottante est géré.Mathf.Approximately
doit être utilisé à la place, ainsi les méthodes d'extension suivantes peuvent être ajoutées pour vérifier si deux vecteurs sont> = ou <= l'un par rapport à l'autre:la source
Je voudrais proposer une manière différente d'interpréter cette question. Un modèle de code comme celui-ci:
essaie essentiellement d'utiliser les opérateurs
>=
/<=
car "le côté gauche a-t-il atteint ou dépassé le côté droit?" tests.Utiliser
>=
/<=
pour signifier "atteint ou dépassé" est logique dans un sens unidimensionnel, si ma position n'est qu'un flottant:Mais dans l'espace 3D, nous n'avons pas de ligne pour mesurer, pour décider quel côté est "haut / loin" et quel côté est "bas / proche". Par exemple, nous pourrions essayer de patrouiller entre les points
Alors maintenant, nous nous attendons
patrolStart <= myPosition <= patrolEnd
sur l'axe X, maispatrolEnd <= myPosition <= patrolStart
sur l'axe Z. Notre opérateur "atteint ou dépassé" est différent d'un axe à l'autre, il n'y a donc plus de correspondance claire entre notre concept de franchissement de seuil et un simple contrôle d'inégalité.Mais, il y a un moyen de choisir une seule ligne dans l'espace 3D et de faire en sorte que notre
>=
/<=
se comporte comme le flotteur unique le long de cette ligne que nous avons choisi:En prime, si vous normalisez le vecteur d'axe avant de l'utiliser, tous les produits scalaires représentent des distances, de sorte que vous pouvez mesurer exactement à quelle distance vous êtes de chaque extrémité, le long de l'axe de déplacement.
la source