Dies ist das erste von zwei Tutorials zum Ausrichten eines Objekts auf ein anderes in Unity. Genauer gesagt sehen wir uns an, wie wir das 3D-Modell einer Überwachungskamera automatisch auf den Player ausrichten können, sodass sie seinen Bewegungen innerhalb der Szene folgt.
Für dieses Tutorial ist keine Deutsche Tonspur verfügbar. Unten kannst du das Video mit Englischer Tonspur und Untertiteln auf Deutsch, Englisch und in weiteren Sprachen ansehen. Unter dem Video findest du die ins Deutsche übersetzte Transkription.
Videotranskript
Hallo zusammen!
Dies ist das erste von zwei Tutorials zum Ausrichten eines Objekts auf ein anderes in Unity. Genauer gesagt sehen wir uns an, wie wir das 3D-Modell einer Überwachungskamera automatisch auf den Player ausrichten können, sodass sie seinen Bewegungen innerhalb der Szene folgt.

Dieses Tutorial wurde mit Unity 2022 erstellt und ist in zwei Teile unterteilt.
Im ersten Teil analysieren wir das Problem und nähern uns der Lösung mithilfe der Methode Rotate, um eine sofortige Drehung der Kamera zu erreichen.
Im zweiten Teil verwenden wir Quaternionen und die Methode Slerp, um weichere und gleichmäßigere Rotationen zu erzeugen.
Bevor wir mit der Implementierung beginnen, analysieren wir zunächst das zu lösende Problem.
Die Kamera kann sich nur um ihre lokale vertikale Achse drehen, daher können wir das Problem auf die 2D-Ebene reduzieren. Um diesen Aspekt verständlicher zu machen, zeige ich die Szene aus der TOP-Perspektive im Orthogonal-Modus.

Sowohl das 3D-Modell der Überwachungskamera als auch der Player besitzen, wie alle GameObjects, XYZ-Positionskoordinaten, die ihre Position in der Szene definieren.
Die Koordinate position.y interessiert uns nicht, da sich die Kamera nur um diese LOKALE Achse drehen kann. Wir berücksichtigen daher nur die Positionskoordinaten x und z, so als befänden sich beide Objekte auf derselben Ebene mit identischem y-Wert.
In unserem Fall kann die Überwachungskamera außerdem als Ursprung des Bezugssystems betrachtet werden, also als Punkt 0,0 einer kartesischen Ebene.
Darüber hinaus können wir die Blickrichtung der Kamera, die in diesem Fall der negativen LOKALEN Y-Achse entspricht, als eine der kartesischen Achsen betrachten.
Wir können nun die Richtung bestimmen, die die virtuelle Kamera mit der Position des Players in der Szene verbindet. Dabei handelt es sich einfach um einen Vektor, den wir ebenfalls nur zweidimensional betrachten, also in GLOBAL X und Z.
Daraus folgt, dass die Rotation, die wir auf die Überwachungskamera anwenden möchten, dem Winkel entspricht, der zwischen der aktuellen Ausrichtung des Assets, also seiner negativen lokalen Y-Achse, und dem idealen Vektor zwischen Überwachungskamera und Player liegt. Wenn wir diesen Winkel bestimmen, erhalten wir die Rotation, die um die lokale vertikale Achse auf das 3D-Modell angewendet werden muss.

Wir haben großes Glück: Es gibt eine mathematische Funktion namens Zwei-Argumente-Arctan, implementiert durch die Methode Atan2 in Mathf, die genau diesen Winkel berechnet. Als Parameter erhält sie den Richtungsvektor, also die Differenz der Koordinaten der beiden Punkte.
Konkret berechnet Atan2 den Winkel zwischen der X-Achse der kartesischen Ebene und dem Richtungsvektor zwischen Ursprung und Ziel.
In unserem Fall wird der Ursprung durch die X- und Z-Koordinaten des 3D-Modells der Überwachungskamera definiert. Die Zielkoordinaten x und y ergeben sich aus den Koordinatendifferenzen zwischen Überwachungskamera und Player. Die X-Achse entspricht dabei der negativen lokalen Y-Achse der Überwachungskamera.
Die Funktion erwartet ihre beiden Parameter in umgekehrter Reihenfolge. In der kartesischen Ebene schreiben wir atan2(y, x). In unserem Fall, unter Berücksichtigung des Unity-Referenzsystems, bei dem die X-Achse die seitliche Achse ist, die Z-Achse die frontale Achse und die Y-Achse die vertikale Achse, die wir hier nicht berücksichtigen, schreiben wir atan2(x, z).
Die Online-Dokumentation von Unity erklärt, dass Mathf.Atan2 die y- und x-Koordinaten entgegennimmt, die in unserem Fall x und z sind, und als float-Wert den Winkel in Radiant zurückgibt, dessen Tangens y durch x ist.

Die Funktion Rotate in Unity erwartet einen Rotationswinkel in Grad. Deshalb müssen wir diesen Unterschied in der Maßeinheit und die entsprechende Umrechnung im Code berücksichtigen.
Nachdem wir das Problem und seine Lösung analysiert haben, kommen wir zur ersten Implementierung: sofortige Rotation mit Rotate.
Zuerst erstelle ich ein neues C#-Skript mit dem Namen LookAtObject, das der eigentlichen Überwachungskamera zugewiesen wird. Ich sage eigentliche Überwachungskamera, weil dieses Asset tatsächlich aus drei Elementen besteht: einer Basis zur Befestigung an der Wand, einem Pivot-Element und der Kamera.
Uns interessiert, dass sich die Kamera um ihre eigene vertikale Achse dreht, also um ihre LOKALE vertikale Achse.
Im virtuellen Universum von Unity ist die GLOBALE vertikale Achse die Y-Achse. Jedes Objekt kann jedoch sein eigenes LOKALES Bezugssystem besitzen. Beim 3D-Modell der Überwachungskamera ist dies die LOKALE Z-Achse, wie wir sehen können, wenn wir im Unity-Editor in den LOCAL-Anzeigemodus wechseln.

Diese Unterscheidung bringt eine kleine zusätzliche Komplexität in unser Projekt. Wir müssen den Rotationswinkel in der globalen Ebene der Szene berechnen, indem wir die X- und Z-Koordinaten der Objekte verwenden, und anschließend die Drehung um die lokale vertikale Achse des Assets durchführen.
Zunächst erstellen wir eine Referenz auf das Objekt, das verfolgt werden soll. Dazu legen wir eine Transform-Variable mit dem Namen objectA an und weisen sie im Inspector dem Player zu.
[SerializeField] private Transform objectA;

Nachdem das erledigt ist, können wir direkt in die Update-Methode wechseln, um die zuvor besprochene Lösung zu implementieren. Ich erinnere daran, dass die LOKALE vertikale Achse der Kamera ihre Z-Achse ist.
Wir benötigen nur drei Codezeilen.
In der ersten berechnen wir den Winkel zwischen der aktuellen Ausrichtung der Kamera und der gewünschten Ausrichtung, also derjenigen, bei der sie auf das Objekt zeigt.
In der zweiten berechnen wir die Drehung um die lokale Z-Achse der Kamera, die erforderlich ist, um diese gewünschte Ausrichtung zu erreichen.
In der dritten führen wir die eigentliche Rotation mit der Methode Rotate aus. Dafür müssen wir zwei Parameter übergeben: den lokalen vertikalen Vektor und den Rotationswert um diesen Vektor.
Beginnen wir mit der Berechnung des Winkels zwischen der aktuellen Ausrichtung der Überwachungskamera und der gewünschten Ausrichtung mithilfe der Funktion Atan2 aus Mathf. Diese liefert einen Wert in Radiant, den wir in Grad umrechnen.
Wir haben gesehen, dass Atan2 in der 2D-Ebene zwei Parameter erwartet: die Differenz der Y-Koordinaten und die Differenz der X-Koordinaten der beiden Punkte, also Ziel und Beobachter in dieser Reihenfolge.
In unserem Szenario mit dem globalen Koordinatensystem von Unity, bei dem X und Z die 2D-Ebene bilden und GLOBAL Y die vertikale Achse der Szene darstellt, schreiben wir:
float theta = Mathf.Atan2((objectA.transform.position.x - transform.position.x), (objectA.transform.position.z - transform.position.z)) * Mathf.Rad2Deg;
Nachdem wir das getan haben, kommen wir zur zweiten Anweisung. Wir berechnen die auszuführende Rotation in Grad mit:
float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.z, theta);
Dabei stellt transform.eulerAngles.z die aktuelle Ausrichtung der Überwachungskamera dar, während theta die im vorherigen Schritt berechnete Zielausrichtung ist.
Die dritte und letzte Anweisung führt die Rotation der Überwachungskamera aus:
transform.Rotate(Vector3.forward, deltaAngle);
Beachten Sie, dass ich Vector3.forward verwendet habe, das die LOKALE Z-Achse des Objekts bezeichnet, als Vektor, um den die Rotation erfolgt. Das liegt daran, dass bei diesem 3D-Modell die LOKALE Z-Achse nicht die Vorwärts- und Rückwärtsrichtung angibt, sondern die LOKALE vertikale Achse des Objekts.
Speichern Sie das Skript, wechseln Sie zum Unity-Editor und drücken Sie Play, um das Endergebnis zu überprüfen.
HINWEIS - Falls Sie feststellen, dass die Überwachungskamera nicht auf das Ziel zeigt, stellen Sie sicher, dass die anfänglichen XYZ-Rotationswerte der Überwachungskamera im Inspector auf 0 gesetzt sind, und versuchen Sie es erneut.


Fassen wir zusammen: In diesem ersten Teil haben wir das zu lösende Problem analysiert und gesehen, wie man die beiden Objekte als auf derselben Ebene liegend betrachtet, wie man den Richtungsvektor berechnet und vor allem, wie man ihn auf den speziellen Fall der Überwachungskamera anwendet, unter Berücksichtigung ihres lokalen Bezugssystems.
Anschließend haben wir mithilfe der Funktion Rotate eine sofortige Rotation auf das Objekt angewendet, sodass es in jedem Frame des Spiels auf den Player zeigt.
Im nächsten Teil werden wir sehen, wie man Rotationsquaternionen berechnet und die Funktion Slerp verwendet, um das Objekt langsamer und gleichmäßiger zu drehen.