Ich versuche, ein Rechteck zwischen zwei Positionen zu bewegen, die ich als _positionA
und bezeichne _positionB
. Beide sind vom Typ Vector3
. Das Rechteck bewegt sich gut. Wenn es jedoch erreicht _positionB
wird, bewegt es sich nicht in die entgegengesetzte Richtung, wie es sollte.
Ich ging zurück in den Code, um einen Blick darauf zu werfen. Ich kam zu dem Schluss, dass die if
Anweisungen im Code beim Bewegen des Objekts den Rahmen verfehlten, in dem die Position der Rechte gleich war _positionB
. Ich habe beschlossen, den Code so zu ändern, dass die Richtung umgekehrt wird, wenn die Position der Rechtecke größer oder gleich ist _positionB
. Mein Code ist nicht zu lang, daher werde ich ihn unten anzeigen:
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;
}
}
}
}
Als ich es änderte, warnte es mich jedoch vor der folgenden Fehlermeldung:
Operator> = kann nicht auf Operanden vom Typ Vector3 und Vector3 angewendet werden.
Das verwirrt mich aus zwei Gründen; Erstens sind beide Werte vom gleichen Datentyp. Zweitens ==
funktioniert die Verwendung des Vergleichsoperators ( ) für die beiden Werte fehlerfrei. Warum kann ich den Operator nicht >=
mit Vector3
s verwenden?
quelle
Bools
wie_atPosA
und zu verwenden_atPosB
. Es ist unvermeidlich, dass Sie einen Fehler machen, wenn Sie beide synchron halten, und dies führt zu Fehlern. Es ist besserenum
, alle Positionen (A, B, vielleicht andere in der Zukunft) zu enthalten und diese zu verwenden>=
bedeutenVector3
? Komponentenbezogen vergleichen? Das wäre keine Gesamtbestellung.Vector3.MoveTowards
var vec1 = new Vector3(1, 0, 0)
undvar vec2 = new Vector3(0, 1 ,0)
. Istvec1 >= vec2
wahr oder falsch?Antworten:
Um die Antwort zu vereinfachen,
Vector3
wird eine benutzerdefinierte Funktionstruct
vomUnityEngine
Namespace bereitgestellt . Wenn wir benutzerdefinierteclass
oderstruct
Typen erstellen , müssen wir auch deren Operatoren definieren . Daher gibt es keine Standardlogik für den>=
Bediener. Wie durch wies darauf hin , Evgeny Vasilyev ,_rect_tfm.position == _positionB
macht Sinn, da wir direkt die überprüfen könnenVector3.x
,Vector3.y
undVector3.z
Werte._rect_tfm.position >= _positionB
macht nicht so viel Sinn, da aVector3
durch drei separate Werte dargestellt wird.Wir könnten die
Vector3
Klasse überladen , um theoretisch die geeigneten Operatoren zu enthalten , aber das scheint ziemlich kompliziert zu sein. Stattdessen wäre es einfacher , dieVector3
Klasse einfach mit einer geeigneten Methode zu erweitern . Davon abgesehen scheint es, dass Sie beabsichtigen, diese Logik für die Bewegung zu verwenden. Daher ist es möglicherweise viel einfacher, dieVector3.Lerp
Methode zu verwenden. Wenn ja, lesen Sie weiter unten.Hinzufügen von Erweiterungsmethoden zu
Vector3
Wie bereits erwähnt, die Anwendung
<=
oder>=
auf einVector3
oft unlogisch. Für die Bewegung möchten Sie wahrscheinlich weiter für dieVector3.Lerp
Methode lesen . Das heißt, Sie möchten die<=
=>
Arithmetik vielleicht aus anderen Gründen anwenden , also werde ich Ihnen eine einfache Alternative geben.Anstatt die Logik von
Vector3 <= Vector3
oder anzuwendenVector3 >= Vector3
, schlage ich vor, dieVector3
Klasse um Methoden fürisGreaterOrEqual(Vector3 other)
und zu erweiternisLesserOrEqual(Vector3)
. Wir können einem oder Erweiterungsmethoden hinzufügen, indem wir sie in einer Klasse deklarieren , die nicht erbt. Wir geben auch das Ziel oder als ersten Parameter mit dem Schlüsselwort an. Beachten Sie, dass ich in meinem Beispiel davon ausgehe, dass Sie sicherstellen möchten, dass alle drei Hauptwerte ( , und ) alle größer oder gleich oder kleiner oder gleich sind. Hier können Sie nach Bedarf Ihre eigene Logik bereitstellen.struct
class
static
class
struct
this
x
y
z
Wenn wir versuchen, diese Methoden aus der
Vector3
Klasse aufzurufen ,local
wird dieVector3
Instanz dargestellt, von der aus wir die Methode aufrufen. Sie werden feststellen, dass die Methoden sindstatic
; Erweiterungsmethoden müssen vorhanden seinstatic
, Sie müssen sie jedoch weiterhin von einer Instanz aus aufrufen. Mit den oben genannten Erweiterungsmethoden können Sie sie jetzt direkt auf IhreVector3
Typen anwenden .Umzug
Vector3
mitVector3.Lerp
Durch Aufrufen der
Vector3.Lerp
Methode können wir die genaue Position zwischen zweiVector3
Werten zu einem bestimmten Zeitpunkt bestimmen . Ein zusätzlicher Vorteil dieser Methode ist, dass dasVector3
Ziel nicht überschritten wird .Vector3.Lerp
nimmt drei Parameter; Die Startposition, die Endposition und die aktuelle Position werden als Wert zwischen 0 und 1 dargestellt. Sie gibt die resultierende Position als a ausVector3
, die wir direkt als aktuelle Position festlegen können.Um Ihr Problem zu lösen, schlage ich vor
Vector3.Lerp
, zu einem zu wechselntargetPosition
. Nach dem Aufruf derMove
Methode in jedemUpdate
können wir überprüfen, ob wir das Ziel erreicht haben;Lerp.Vector3
wird nicht überschießen,transform.position == targetPosition
wird also zuverlässig. Wir können nun die Position überprüfen und ändern dietargetPosition
zuleftPosition
oderrightPosition
die Bewegung umgekehrt, entsprechend.Sie können dies in der folgenden Animation demonstrieren. Ich übersetze den blauen Würfel mit
Vector3.LerpUnclamped
, was uns ein ähnliches Ergebnis wie eine einfache ungeprüfte Übersetzung gibt. Ich übersetze den roten Würfel mitVector3.Lerp
. Wenn das Kontrollkästchen nicht aktiviert ist, gerät der blaue Würfel in Vergessenheit. während der rote Würfel genau dort anhält, wo ich es beabsichtige. Weitere Informationen zu dieser Art von Bewegung finden Sie in der Dokumentation zum Stapelüberlauf .quelle
Das Definieren
>=
einesVector3
Typs macht keinen Sinn. Was bestimmt, ob ein Vektor größer als ein anderer ist? Ihre Größe oder ihre einzelnen x-, y-, z-Komponenten?Ein Vektor ist eine Größe und eine Richtung. Was bestimmt also, welche Richtung größer ist?
Wenn Sie die Größen vergleichen müssen, können Sie verwenden
sqrMagnitude
.In diesem Fall werden
Vector3
Überschreibungen vorgenommen,==
um einfach die verschiedenen Komponenten zu vergleichen und festzustellen, ob sie identisch sind. (innerhalb einer Schwelle)Dies ist der gleiche Grund, warum das Multiplizieren von zwei Vektoren mit
*
nicht möglich ist. Es gibt einfach keinen mathematischen Weg, dies zu tun. Einige Leute verwenden*
für Punktprodukt, aber das ist ein unklares API-Design.quelle
Vector3
ist astruct
, daher ist der Absatz über den Referenzvergleich nicht ganz richtig.Dies ist eine alte Frage, aber um es weniger technisch auszudrücken: Ein Vector3 ist ein "Container" für 3 Float-Werte - x, y, z.
Sie können einzelne Werte vergleichen, z. B. die x-Werte von zwei Vector3s, da es sich nur um Zahlen handelt.
Ein ganzer Vector3 kann jedoch nicht mit einem anderen Vector3 verglichen werden, da es keinen einzigen Wert gibt, mit dem die beiden verglichen werden können.
quelle
Fügen Sie einfach das hinzu, was Gnemlock veröffentlicht hat, und fügen Sie der Vector3-Klasse Erweiterungsmethoden hinzu. Es gibt ein Problem in der Einheit (und ich bin sicher , dass andere Spiele - Engines) , wenn bestimmte Vergleichsoperatoren verwenden (
==
,<=
und>=
) zwischen zwei Float - Werte, durch, wie Fließkommaberechnung behandelt wird.Mathf.Approximately
sollte stattdessen verwendet werden, daher können die folgenden Erweiterungsmethoden hinzugefügt werden, um zu überprüfen, ob zwei Vektoren> = oder <= zueinander sind:quelle
Ich möchte eine andere Art der Interpretation dieser Frage vorschlagen. Ein Codemuster wie dieses:
versucht im Grunde, die Operatoren
>=
/<=
als "hat die linke Seite die rechte Seite erreicht oder passiert ?" zu verwenden. Tests.Die Verwendung von
>=
/<=
für "erreicht oder bestanden" ist in einem eindimensionalen Sinne sinnvoll, wenn meine Position nur ein Float ist:Aber im 3D-Raum haben wir keine Linie, an der wir messen können, um zu entscheiden, welche Seite "hoch / fern" und welche Seite "niedrig / nah" ist. Zum Beispiel könnten wir versuchen, zwischen den Punkten zu patrouillieren
Nun erwarten wir also
patrolStart <= myPosition <= patrolEnd
auf der X-Achse, aberpatrolEnd <= myPosition <= patrolStart
auf der Z-Achse. Unser Operator "erreicht oder bestanden" unterscheidet sich von einer Achse zur anderen, sodass es keine eindeutige Zuordnung mehr zwischen unserem Konzept des Überschreitens eines Schwellenwerts und einer einfachen Ungleichheitsprüfung gibt.Es gibt jedoch eine Möglichkeit, nur eine Linie im 3D-Raum auszuwählen und unser
>=
/<=
Verhalten wie das einzelne Float-Gehäuse entlang dieser von uns gewählten Linie zu verhalten:Wenn Sie den Achsenvektor vor der Verwendung normalisieren, stellen alle Punktprodukte als Bonus Entfernungen dar, sodass Sie genau messen können, wie weit Sie von beiden Enden entlang der Bewegungsachse entfernt sind.
quelle