Jump to content
Unity Insider Forum

[gelöst]Mouselook-Script und Rotation per Tastendruck


Malthea

Recommended Posts

Hallo,

ich habe ein Mouselook- und ein Charactercontrollerskript von holistic3d etwas abgewandelt, um später ingame die Möglichkeit zu haben, die Maus in Fenstern bzw bei Aktionen frei zu benutzen und gleichzeitig den Character weiter über die map zu bewegen.

Die Kamera ist an den Character geparentet, die straffe-Verschiebung auf der x-local-Achse habe ich herausgenommen - auch die Tastaturbelegungen in den Project Settings dafür. Wenn die Tasten zum Drehen des Characters benutzt werden, wird die Auswertung der Mausbewegung über eine Bool deaktiviert und wieder aktiviert, wenn die jeweilige Taste losgelassen wird. Zur Zeit funktionieren die Maussteuerung und die Characterrotation nur separat.

Das führt zu folgenden Resultaten (die Zahlen der Objektrotation um die Y-Achse sind nur zum Verständlichmachen des Problems angegeben): Start bei 0, durch Bewegen der Maus nach rechts bis 45. Drücken der Pfeil-rechts-Taste setzt den Y-Wert wieder auf 0 (und auch die Kamera an den Ausgangspunkt). Gedrückt halten bis Y 90. Beim Loslassen springt die Kamera auf 45 zurück. Usw. Jede Rotationsart "merkt" sich den jeweiligen Endpunkt der eigenen Bewegung und setzt dort wieder an.

Die Übertragung der Rotation von der Kamera zum Spielerobjekt und die Translation auf der x-z-Ebene durch die Tastatur funktioniert einwandfrei. In den vergangenen Tagen habe ich versucht, den Vektor2 mouseLook mit dem aktuellen Wert nach der Drehung mit den Tasten zu überschreiben bzw die Ausrichtung der Kamera an das Spielerobject vor dem Freigeben der Auswertung der Mausbewegungen zu aktualisieren, was leider nicht geklappt hat. Google hat nur workarounds für die Scripte von Unity geliefert.

Ich bin ziemlich ratlos, in welche Richtung ich suchen sollte. Vielleicht hat einer von euch eine Idee, wie dieses Problem gelöst werden kann.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class camMouseLook : MonoBehaviour {
	
	Vector2 mouseLook;
	Vector2 smoothV;
	public float sensitivity = 5.0f;
	public float smoothing = 2.0f;
	public bool mouseLookEnable = true;	
	GameObject charakter;

	void Start () {
		charakter = this.transform.parent.gameObject;
	}
	
	void Update () {
		if (mouseLookEnable) {
			var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
	
			md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
			smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
			smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
			mouseLook += smoothV;
			mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
		
			transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
			charakter.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, charakter.transform.up);
		}
	}
/*	
	private void PrintName(GameObject go) {
		print(go.name);
	} */
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class characterController : MonoBehaviour {
	public float speed = 10.0f;
	public float rotationSpeed =100.0f;
	public GameObject cam;
	private camMouseLook mouseLook;
	
	float y;
	
	void Start () {
		Cursor.lockState = CursorLockMode.Locked;
		Cursor.visible = false;
		mouseLook = cam.GetComponent<camMouseLook>();
	}
	
	void Update () {
		float translation = Input.GetAxis("Vertical") * speed; // Translation z-local
//		float rotation = Input.GetAxis("Horizontal") * speed;
		translation *= Time.deltaTime;  // move 10 Units per second instead 10 per frame
//		rotation *= Time.deltaTime;
		
		transform.Translate(0, 0, translation);
//		transform.Rotate(0, rotation, 0);
		if(Input.GetKeyUp("right")) {
			mouseLook.mouseLookEnable = true;
		}		
		if (Input.anyKey) {
			if(Input.GetKeyDown("right")) {
				mouseLook.mouseLookEnable = false;
			}
			if(Input.GetKey("right")) {
//				float rotation = Input.GetAxisRaw("Horizontal") * speed;
//				Debug.Log ("rotation = " + rotation);
//				rotation *= Time.deltaTime;
//				transform.Rotate(0, rotation, 0);
//				mouseLookEnable = GetComponent<camMouseLook>();
				y += Time.deltaTime * 10;
				Debug.Log ("Eulerrotation = " + y);
				transform.rotation = Quaternion.Euler(0, y, 0);				
			}
		
			if (Input.GetKeyDown("escape")) {
				if (Cursor.lockState != CursorLockMode.Confined) {

					Cursor.lockState = CursorLockMode.None;
					Cursor.lockState = CursorLockMode.Confined;
					Cursor.visible = true;
				}
			}
		
			if (Input.GetKeyDown("space")) {
				if (Cursor.visible) {
					Cursor.lockState = CursorLockMode.Locked;
					Cursor.visible = false;
					Debug.Log("cursor false gesetzt");
				} else {
					Cursor.lockState = CursorLockMode.Confined;
					Cursor.visible = true;
					Debug.Log("cursor true gesetzt");
				}
			}
		}
	}
}

Grüße Malthea

Link zu diesem Kommentar
Auf anderen Seiten teilen

nochmal vielen Dank für deine Erklärungen, Sascha! Diese haben mir weitergeholfen.

Ich habe allerdings bisher keine Objekthierachie gefunden, in der nach Anwendung der Rotationen / Translation alle lokalen Koordinatensysteme gleich ausgerichtet waren bzw sich über dem gleichen Punkt der x-z-Ebene befanden. An einer Stelle muss immer entweder die Drehung oder die globale Position des jeweiligen Parents korrigiert werden.

Mein derzeitiger "Versuchsaufbau" sieht wie folgt aus: Hierachie: Empty -> Spieler -> Kamera. Das script auf dem empty ist für die Drehung um y durch die Tastatur und die Translation zuständig, das script auf dem Spielerobjekt für die Drehung um y durch die Maus und das script auf der Kamera für die Blickrichtung nach oben bzw unten.

Da die Drehung durch die Maus nur die lokalen Koordinatensysteme des Spielerobjekts und der Kamera anpasst, "läuft" der Spieler danach in die "alte" z-local-Richtung des empties. Ich hatte es zwischendurch auch mit einem weiteren empty versucht, um die Translation und die Drehung durch die Tastatur zu trennen, was aber nicht erfolgreich war.

Vielleicht hat jemand eine Idee, wie das gelöst werden kann oder sind an dieser Stelle die Möglichkeiten der Aufteilung der einzelnen Bewegungen durch eine Objekthierachie erreicht?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Es ist nicht sinnvoll, die Bewegung um die Y-Achse auf zwei Objekte aufzuteilen... oder funktionieren die beiden Drehungen unterschiedlich abgesehen vom Input? Da dein Parent ein leeres GameObject ist, denke ich, dass du einfach beide Drehmethoden in ein Script packen kannst.

Anschließend kannst du dann einfach dieses eine GameObject, das sich um die Y-Achse dreht immer im eigenen Local Space bewegen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich glaube, ich habe alle möglichen Kombinationen ausprobiert, auch beide Drehungen um die Y-Achse in einem script. Geparentet ist wie folgt:

Objekt1 -> Objekt2 -> Kamera

Ob Objekt1 das empty oder das Spielerobjekt ist oder entsprechend Objekt 2, scheint egal zu sein, die Kamera bewegt sich bei allen Kombinationen so mit, wie sie soll.

Fall 1: Objekt 1 ist nur für die Translation zuständig, Objekt 2 für beide Drehungen: Objekt1 wird nicht mitgedreht.
Fall 2: Objekt1 ist für beide Drehungen zuständig, Objekt 2 für die Translation: Objekt1 bleibt bei der Translation am Ausgangspunkt.
Fall 3 und 4: Objekt1 ist für die Translation und eine der Drehungen zuständig: Objekt1 wird bei der anderen Drehungsart nicht mitgedreht.

Eine Lösung wäre so etwas wie

transform.parent.position = transform.position - transform.localpostiion;

um Objekt1 mitzudrehen. Ich habe deinen Blogbeitrag so verstanden, dass man durch eine geeignete Hierachie solche Zugriffe unnötig macht. Mein Problem ist, eine geeignete Hierachie zu finden. Wenn es diese nicht geben sollte, kann ich es ja mit transform.parent.position lösen.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Prinzipiell sollte bei so etwas kein Objekt von sich aus Einfluss auf seinen Parent nehmen. Ich blicke eventuell noch nicht durch deinen Plan durch, aber so wie ich das verstehe, baust du einen First-Person-Controller. Für den brauchst du eigentlich nur die Spielfigur, die sich um die Y-Achse dreht und sich entlang ihrer Ausrichtung bewegt, und eine Kamera, die sich nach oben und unten neigt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja - es sollte auch nur ein First-Person-Controller werden - allerdings ergaben sich "Hacker" beim Wechsel von der Tastaturdrehung zur Mausdrehung um Y und umgekehrt (siehe 1.Post). Etwas besser wurde es, nachdem ich die Maus-Drehung aus dem Kameraskript heraus genommen und in den Gamekontroller gepackt habe - danach klappte schon mal der Wechsel von der Tastatur zur Maus.

In der Zwischenzeit habe ich den Fehler gefunden: Für die eine Rotation habe ich transform.rotation und für die andere transform.Rotate verwendet. Nachdem ich jetzt beides mit transform.Rotate drehe, funktioniert alles, wie es soll.

Nochmal Danke für die Hilfe.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...