Jump to content
Unity Insider Forum

Objektrotation Verständnissproblem


frameworker

Recommended Posts

Hallo,

 

bin Unity-Neuling, ich möchte ein Objekt um sich selbst drehen und mache das wie folgt:

 

 

 


Quaternion newRotation = new Quaternion(transform.rotation.x,transform.rotation.y,transform.rotation.z,transform.rotation.w);
newRotation = Quaternion.Euler(angleX, angleY, angleZ);
transform.rotation = newRotation;

 

Das Objekt liegt zu Anfang auf x=0, y=0, z=-10, also auf der XY Ebene. Und dort funktioniert die Drehung um Y- (seitwärts links/rechts), X- (vorwärts, rückwärts kippen) sowie Z-Achse (seitwärts links/rechts rollen). Der Pivotpunkt ist exakt in Objektmitte, also alle Rotationsbewegungen laufen objektlokal (um sich selbst).

 

Jetzt mein Problem:

Wenn ich bspw. das Objekt um die X-Achse nach vorne "kippe", sagen wir um 80 Grad, dann zeigt transform.forward zwar wie erwartet nach unten, aber die Seitwärtsdrehung um die Y-Achse funktioniert mit zunehmenden X nicht wie erwartet: Drehe ich bei X=90 "seitwärts", also die Y-Achse nach links od. rechts, dann macht das Objekt eine Drehung quasi um Z, es rollt. Z verändert sich natürlich nicht, es ändert sich Y, aber es bildet das nicht ab.

 

Ich bin davon ausgegangen, das die Achsen mit rotieren, aber da liege ich wohl falsch.

Wie bekomme ich dann aus jeder Rotationslage korrektes Yaw, Pitch und Roll?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo, willkommen und gleich mal herzlichen Glückwunsch: Das hört sich so an, als hättest du das Phänomen des sog. "Gimbal-Locks" entdeckt! :-)

 

Einzige oder zumindest die sinnvollste Abhilfe ist, der komplette Verzicht auf die "Euler Angles" und alle Rotationen über Quaternions zu steuern. Diese sind nämlich nicht von diesem "Gimbal-Lock" abhängig und funktionieren trotzdem.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, habe ich befürchtet. Habe einige Tutorials bzgl. Quaternions angeschaut, war aber kein's dabei was z.B. ähnlich gut die Sache zusammenfasst wie das Kapitel "Vector Cookbook" im Unity Manual.

Die meisten Video Tutorials zeigen das was man darüber schon weiss, Textsachen sind oft hochgradig mathematisch ohne Praxisbezug. Es ist ja auch die schiere Googlemasse über dieses Thema, wer weiss einen guten Link der ihr/ihm schon geholfen hat?

 

Bei Quaternions verstehe ich bspw. nicht, das man einen bestimmten Winkel nicht setzen kann, man muss offenbar immer mit Interpolation (Slerp o.a.) zwischen Rotation A und B arbeiten, was ich eigentlich nicht will. Ich möchte einfach sagen, Objekt hat einen Rotationswinkel von 45 Grad . Aber dann eben ohne anfangs beschriebene Gimbal-Lock Problematik.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Quaternions direkt zu setzen ist schlecht.

Du kannst aber ein Quaternion-Rotation als EulerAngle setzen, also quasi nur sagen, welchen Winkel du in Eulerangle erreichen willst. Unity dreht dann intern Quaternion.

http://docs.blackice...ion.eulerAngles

und

http://docs.blackice...uaternion.Euler

 

Ja und dann fragst du einfach das Quaternion ab und lässt dir die Winkel in Eulerangles ausgeben.

 

Edit: Siehe oben bei eulerAngles.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Gimbal Lock ist kein Problem, wenn du eine Rotation setzt. Es ist nur ein Problem, wenn du mit der Rotation rechnest.

 

Im Allgemeinen gilt zu Quaternionen: Die Mathematik dahinter ist anstrengend zu verstehen, und sie zu verstehen lohnt sich (als Unity-Benutzer) kaum.

Alles, was du für die Benutzung der Quaternionen brauchst, bietet Unity schon in Form von Funktionen, die meist in der Quaternion-Klasse stecken.

 

(In diesem Moment postet malzbie seine Antwort)

 

ToAngleAxis gibt doch gar nicht die Euler-Angles aus? :)

Aber genau dieses Eulerwinkel-ausgeben-Lassen ist das, wovon ich abraten würde. Ein Objekt im Gimbal Lock hat als Drehung ein völlig harmloses Quaternion, während selbes Quaternion als Eulerwinkel-Vektor mathematische Probleme verursacht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke für Eure Antworten. Ich werde die Links noch mal durchgehen. Ich habe erstmal eine Lösung gefunden, die aber alles andere als elegant ist, aber das gewünschte Resultat bringt:

 

	if (Input.GetKey (KeyCode.RightArrow) && !Input.GetKey (KeyCode.LeftShift)) {
		moveRightCounter = 3;
		transform.RotateAround (transform.up, 0.1f);
	}

	if (Input.GetKey (KeyCode.LeftArrow) && !Input.GetKey (KeyCode.LeftShift)) {
		moveLeftCounter = 3;
		transform.RotateAround (-transform.up, 0.1f);
	}

	if (moveRightCounter > 0) {
		moveRightCounter--;
	}

	if (moveLeftCounter > 0) {
		moveLeftCounter--;
	}

	if(moveRightCounter == 0 || moveLeftCounter == 0)
		rigidbody.angularVelocity = Vector3.zero;

 

Und dasselbe für alle anderen Achsen.

Die meisten Enginefunktionen verursachen ja ein Momentum, das muss man dann ja irgendwie mit Countern steuern, um das "interaktive" Gefühl beim Spieler zu geben.

Aber wie gesagt, mehr ist mir bis heute nicht eingefallen...

Link zu diesem Kommentar
Auf anderen Seiten teilen

@ Sascha: Hast recht. Der Link war dumm. Habe es oben korrigiert.

 

@frameworker:

Was willst du denn erreichen? Du nutzt zwar ein RotateArround, gibst aber keinen Punkt für das herum an, also wird es wohl um die eigene Achse sein. Aber wofür hast du den moveLeftCounter und den MoveRightCounter?

Was bringt es, wenn maximal 2 Updates oder FixedUpdates später deine Angular-Velocity auf zero gestellt wird?

Link zu diesem Kommentar
Auf anderen Seiten teilen

@malzbie: Es geht erstmal nur um das reine Verständnis für Rotation im Raum im Rahmen der Engine. AddTorque habe ich natürlich als erstes probiert und war sofort irritiert: Dort wird ja auch ein Drehmoment erzeugt, den man dann immer "gegensteuern" muss um ihn zu "verlangsamen", das mag für Autorennspiele o.a. aus rein simulations-physikalischen Gesichtspunkten richtig sein. Soweit ich gelesen habe, ist es schwierig das ganze exakt "zu stoppen". Da taucht immer mal wieder die Sache mit den Behelfscountern auf.

 

Trotzdem gibt es genügend Beispiele, wo eine exakte vom Spieler ausgeführte Drehung notwendig ist, bspw. ein Puzzleteil in eine bestimmte Form "zu rotieren" od. ein Werkzeug auf bestimmte Weise zu handhaben, d.h. der Spieler rotiert exakt und muss nicht "gegensteuern".

 

Ich weiss ja auch noch nicht alles über Unity, vielleicht gibt es ja bessere Lösungen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was ich sehr gerne mag ist wenn man einen kleinen "Kompass" einbaut..

Einfach ein Empty GO als z.B. Child auf das zu drehende Objekt legen und den Kompass dann immer direkt die gewünschte Rotation annehmen lassen (z.B. durch LookAt() oder einfach die Rotation setzen).

Also was ganz kurzes und einfaches:

public class Compass : MonoBehaviour{
  public Transform target;

  void Update(){
     if(target){
        transform.LookAt(target);
     }
  }
}

Dann kann man ganz gemütlich mit Quaternion.Slerp() die Rotation des Objekts das man eigentlich rotieren möchte, an die des Kompasses angleichen.

Funktioniert zwar nicht immer und überall aber wenn man z.B. eine Drehung des Puzzleteils sichtbar machen möchte kann man das recht einfach so machen, man muss hald dann die Update anpassen


void Update(){
if(Input.GetKeyDown(KeyCode.D)){
transform.eulerAngles += new Vector3(0,90,0);
}
if(Input.GetKeyDown(KeyCode.A)){
transform.eulerAngles -= new Vector3(0,90,0);
}
}
[/Code]

 

Ich benutz das auch oft für KI ^^ Einen Verfolger, eine Drone die selbstständig zum Ziel fliegt, ein Panzer dessen Geschützturm eine gewisse Zeit braucht um sich zu drehen,..

 

Hoffe du kannst das vllt mal brauchen :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...