Worms123 Geschrieben 22. Januar 2017 Melden Share Geschrieben 22. Januar 2017 Hallo zusammen! Ich habe folgendes Problem. Doch bevor ich dies genauer erläutern kann möchte ich erklären was bereits funktioniert. Was bereits Funktioniert: Via Scripting konnte ich mir eine third-Person Camera basteln welches sich mit dem Controller steuern lässt. Mit dem linken Joystick kann ich den Spieler bewegen, mit dem Rechten die Kamera in der x,y Achse rotieren (sphärisch um den Spieler). Mit Transform Translate dreht sich der Spieler ( in meinem Fall eine Kapsel) in die Z Richtung der Kamera (ohne dass sich der Spieler neigt wenn die Kamera in die Y Achse rotiert). Ich arbeite mit 5 Raycasts. 4 davon verlaufen in den Öffnungswinkel der Kamera (Clippingpoints). Eine trifft die ganze Zeit den Spieler. Falls eine der 5 Clippingrays auf ein Hindernis trifft, fährt die Kamera näher zum Spieler hin. Nun zum Problem: Meine Kamera Clippt durch Wände. Ich arbeite bereits mit einem Physics.CheckSphere und die funktioniert relativ gut wenn ich die Kamera in Richtung der Wand drehe. Wenn ich jedoch von einem komischen Winkel zur Wand hinlaufe Clippt meine Kamera dennoch hinein. Wenn ich rückwärts laufe (quasi gegen die Kamera) Clippt sie ebenfalls durch. Was ich bereits probiert habe: - Sphere Collider & Rigidbody --> Nützt nichts, da ich die Kamera mittels Joystick in die Wand rein drücke. - RayCasts ---> bringt nur bei gewissen Winkel etwas ausserdem wird das Script schnell unübersichtilich - Unity Cameras---> Sie bringen mir nicht die gewünschten Ergebnisse. Ausserdem wollte ich von Grund auf die Kamera selber programmieren. Mein Wunsch: - Die Kamera soll Wänden und Hindernissen automatisch aus den weg gehen. - Wenn sich der Spieler auf die Kamera zu bewegt und hinter der Kamera befindet sich eine Wand soll die Kamera rotieren. - Wenn sich die Kamera in eine Ecke befindet soll sie sich einigermassen elegant rausmanövrieren ohne in die Wand gedrückt zu werden. Ich bedanke mich im Voraus für jede Hilfe die ich bekommen kann. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Helishcoffe Geschrieben 22. Januar 2017 Melden Share Geschrieben 22. Januar 2017 Was genau meinst du mit "komischen Winkel"? Ich denke mal da müste man eine genauere Erklärung + Code sehen. Außerdem frage ich mich, warum das mit einem einfachen Raycast nicht funktioniert. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Worms123 Geschrieben 22. Januar 2017 Autor Melden Share Geschrieben 22. Januar 2017 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ThirdPersonCameraScript : MonoBehaviour { public GameObject target; public Camera cam; private float Y_Angle_MIN = 1.0f; // für Y Winkel der Kamera private float Y_Angle_Max = 40.0f; private float X_Angle_MIN; private float X_Angle_Max; private float currentX = 0.0f; // wird gebraucht um Kalkulationen auszuführen private float currentY = 0.0f; // wird gebraucht um Kalkulationen auszuführen private float distance = 10.0f; // Distanz zwischen Camera und spieler public float MIN_Distance =5; // Für maximal und minimal distanz der kamera public float MAX_Distance = 10; public float cameraspeed = 10; // Geschwindigkeit der Kamera public float rayLength; // strahlenlänge public Transform lookAt; // Spieler Transform position private Transform camTransform; // Camera Transform position public Vector3[] intoArray; // Array für die Clipping Plane Punkte der kamera bool ClipPointsFree = true; public bool hitsTheWall= false; void Start () { camTransform = transform; cam = Camera.main; // cam ist gleich der main Camera in der Szene (mit dem Tag main) rayLength = MAX_Distance; } void Update () { currentY = Mathf.Clamp (currentY, Y_Angle_MIN, Y_Angle_Max); // ein Clamp um den Radius zu veringern (siehe rotation im Inspector) distance = Mathf.Clamp (distance,MIN_Distance,MAX_Distance); // setzt eine Distanzlimmite } private void LateUpdate () { if (!Camera.main) return; //currentX += (int)Input.GetAxis ("Mouse X")*5; // bei Input Manager muss noch der Input von Mouse auf Joystick3thd gewechselt werden //currentY += (int)Input.GetAxis ("Mouse Y")*5; target.GetComponent<Rigidbody> ().rotation = Quaternion.AngleAxis (currentX, Vector3.up); // Erstellt einen 2dimensionalen Kreis um die spähre und berrechnet die x achse der Kamera. // d.h. der Spieler dreht sich um die eigene achse wenn sich die kamera dreht! #region KameraEckPunkte intoArray = new Vector3[5]; float z = Camera.main.nearClipPlane; float x = Mathf.Tan (Camera.main.fieldOfView / 3.41f) * z; float y = x / Camera.main.aspect; Quaternion atRotation = new Quaternion (); //bottom right intoArray [0] = (atRotation * new Vector3 (-x, y, z)) + gameObject.transform.forward; //bottom left intoArray [1] = (atRotation * new Vector3 (x, y, z)) + gameObject.transform.forward; // top right intoArray [2] = (atRotation * new Vector3 (-x, -y, z)) + gameObject.transform.forward; // top left intoArray [3] = (atRotation * new Vector3 (x, -y, z)) + gameObject.transform.forward; //cameraPosition intoArray [4] = gameObject.transform.position - Camera.main.transform.forward; #endregion // Berrechnungen der Kamera Clipping Planes mit Trigonometrie #region dieVierRays //BottomRight Raycast Ray bottomRightray = new Ray (); bottomRightray.origin = gameObject.transform.position; bottomRightray.direction = intoArray [0]; //Kameradirection zum endpunkt der kamera hin Debug.DrawRay (bottomRightray.origin, bottomRightray.direction * rayLength, Color.red); RaycastHit bottomrighthit; if (Physics.Raycast (bottomRightray, out bottomrighthit, rayLength)) { // ray wird hier mitgegeben, out hit bedeutet das sie information in hit gespeichert wird , 10 ist die distanz Debug.DrawRay (bottomRightray.origin, bottomRightray.direction * 10, Color.cyan); // hier kann ich meinen ray sehen. if (bottomrighthit.collider.tag == "Wall") { if (distance > MIN_Distance) distance = distance - 0.5f; // falls die Kamera auf eine Wand trifft geht sie nach vorne ClipPointsFree = false; } } //bottomLeft Ray bottomLeftRay = new Ray (); bottomLeftRay.origin = gameObject.transform.position; bottomLeftRay.direction = intoArray [1]; Debug.DrawRay (bottomLeftRay.origin, bottomLeftRay.direction * rayLength, Color.red); RaycastHit bottomlefthit; if (Physics.Raycast (bottomLeftRay, out bottomlefthit, rayLength)) { // ray wird hier mitgegeben, out hit bedeutet das sie information in hit gespeichert wird , 10 ist die distanz Debug.DrawRay (bottomLeftRay.origin, bottomLeftRay.direction * 10, Color.cyan); // hier kann ich meinen ray sehen. if (bottomlefthit.collider.tag == "Wall") { if (distance > MIN_Distance) distance = distance - 0.5f; // falls die Kamera auf eine Wand trifft geht sie nach vorne ClipPointsFree = false; } } //topRight Ray topRightray = new Ray (); topRightray.origin = gameObject.transform.position; topRightray.direction = intoArray [2]; Debug.DrawRay (topRightray.origin, topRightray.direction * rayLength, Color.red); RaycastHit toprighthit; if (Physics.Raycast (topRightray, out toprighthit, rayLength)) { // ray wird hier mitgegeben, out hit bedeutet das sie information in hit gespeichert wird , 10 ist die distanz Debug.DrawRay (topRightray.origin, topRightray.direction * rayLength, Color.cyan); // hier kann ich meinen ray sehen. if (toprighthit.collider.tag == "Wall") { if (distance > MIN_Distance) distance = distance - 0.5f; // falls die Kamera auf eine Wand trifft geht sie nach vorne ClipPointsFree = false; } } //topLeft Ray topLeft = new Ray (); topLeft.origin = gameObject.transform.position; topLeft.direction = intoArray [3]; Debug.DrawRay (topLeft.origin, topLeft.direction * rayLength, Color.red); RaycastHit toplefthit; if (Physics.Raycast (topLeft, out toplefthit, rayLength)) { // ray wird hier mitgegeben, out hit bedeutet das sie information in hit gespeichert wird , 10 ist die distanz Debug.DrawRay (topLeft.origin, topLeft.direction * rayLength, Color.cyan); // hier kann ich meinen ray sehen. if (toplefthit.collider.tag == "Wall") { if (distance > MIN_Distance) distance = distance - 0.5f; // falls die Kamera auf eine Wand trifft geht sie nach vorne ClipPointsFree = false; } } #endregion if (!Physics.Raycast (topRightray, out toprighthit, rayLength) && distance <= MAX_Distance && !Physics.Raycast (topLeft, out toplefthit, rayLength) && distance <= MAX_Distance && !Physics.Raycast (bottomRightray, out bottomrighthit, rayLength) && distance <= MAX_Distance && !Physics.Raycast (bottomLeftRay, out bottomlefthit, rayLength) && distance <= MAX_Distance) { ClipPointsFree = true; } if (ClipPointsFree == true) { // Falls die Rays der Kameras nicht mit der Wand kollidieren soll die Kamera an distanz zunehmen if (distance < MAX_Distance) { distance += 0.5f; hitsTheWall = false; } if (distance > MAX_Distance) distance = MAX_Distance; } Ray ray = new Ray (); // eine neues Objekt mit der Klasse Ray wird erstellt ray.origin = gameObject.transform.position; // ihm werden position und die richtung mitgegeben ray.direction = transform.forward; // ray direction in der Z achse, da sie sonst irgendwohin strahlt RaycastHit hit; if (Physics.Raycast (ray, out hit, MAX_Distance)) { // ray wird hier mitgegeben, out hit bedeutet das sie information in hit gespeichert wird , 10 ist die distanz Debug.DrawRay (ray.origin, ray.direction * MAX_Distance, Color.cyan); // hier kann ich meinen ray sehen. if (hit.collider.tag == "Wall") { if (hit.collider.tag == "Player") { //Debug.Log ("I hit the Player"); } } } if (Physics.CheckSphere (gameObject.transform.position,1)) { // erstellt eine Sphere um die kamera die kollisionen abfragt Debug.Log (" i am casting"); if (distance > MIN_Distance) distance = distance - 0.5f * Time.smoothDeltaTime; // falls die Kamera auf eine Wand trifft geht sie nach vorne ClipPointsFree = false; Debug.Log ("sphere hits the Wall"); hitsTheWall = true; } if (hitsTheWall == false) { // falls die Kamera nicht mit einer Wand Kollidiert currentX += (int)Input.GetAxis ("Mouse X") *cameraspeed ; // bei Input Manager muss noch der Input von Mouse auf Joystick3thd gewechselt werden currentY += (int)Input.GetAxis ("Mouse Y") * cameraspeed; Vector3 dir = new Vector3 (0, 0, -distance); Quaternion rotation = Quaternion.Euler (currentY, currentX, 0); Debug.Log (" should not rotate"); camTransform.position = lookAt.position + rotation * dir; camTransform.LookAt (lookAt.position); } if (hitsTheWall == true) { // if spherecast hits the wall currentY += (int)Input.GetAxis ("Mouse Y") * cameraspeed; //currentX += (int)Input.GetAxis ("Mouse X") * cameraspeed; //currentX += (int)Input.GetAxis ("Mouse X") * -Vector3.Distance (gameObject.transform.position, spherehit.point); //currentX += 0; currentX += (int)Input.GetAxis("Mouse X") * 0.01f; // falls die Kamera mit einer Wand kollidiert bewegt sie sich ganz langsam Vector3 dir = new Vector3 (0, 0, -distance); Quaternion rotation = Quaternion.Euler (currentY, currentX, 0); Debug.Log (" should not rotate"); camTransform.position = lookAt.position + rotation * dir ; camTransform.LookAt (lookAt.position); } } } Was genau meinst du mit "komischen Winkel"? Ich denke mal da müste man eine genauere Erklärung + Code sehen. Außerdem frage ich mich, warum das mit einem einfachen Raycast nicht funktioniert. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Worms123 Geschrieben 22. Januar 2017 Autor Melden Share Geschrieben 22. Januar 2017 Was genau meinst du mit "komischen Winkel"? Ich denke mal da müste man eine genauere Erklärung + Code sehen. Außerdem frage ich mich, warum das mit einem einfachen Raycast nicht funktioniert. Danke für deine Hilfe Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 22. Januar 2017 Melden Share Geschrieben 22. Januar 2017 - Wenn sich der Spieler auf die Kamera zu bewegt und hinter der Kamera befindet sich eine Wand soll die Kamera rotieren. - Wenn sich die Kamera in eine Ecke befindet soll sie sich einigermassen elegant rausmanövrieren ohne in die Wand gedrückt zu werden. Das wird einigermaßen unmöglich. Wenn du nicht deine ganzen Szenen mit handgesetzten Daten übersähst,die der Kamera sagen, wie sie sich zu bewegen hat, wirst du immer Fälle haben, in denen die Kamera entweder irgendwo reinclipt oder Spasmen kriegt. Die weit verbreitete Lösung ist, einen einzelnen Ray (alternativ Spherecast) vom einem Punkt in der Spielfigur in Richtung der Kamera zu schießen und die Kamera auf die gewünschte Position oder die des RaycastHits zu setzen, je nach dem, was näher dran ist. Ist auch wesentlich weniger verwirrend als eine Kamera, die sich steuern lässt, dann aber plötzlich selbstständig wird und durch die Gegend fliegt. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Worms123 Geschrieben 22. Januar 2017 Autor Melden Share Geschrieben 22. Januar 2017 Das wird einigermaßen unmöglich. Wenn du nicht deine ganzen Szenen mit handgesetzten Daten übersähst,die der Kamera sagen, wie sie sich zu bewegen hat, wirst du immer Fälle haben, in denen die Kamera entweder irgendwo reinclipt oder Spasmen kriegt. Die weit verbreitete Lösung ist, einen einzelnen Ray (alternativ Spherecast) vom einem Punkt in der Spielfigur in Richtung der Kamera zu schießen und die Kamera auf die gewünschte Position oder die des RaycastHits zu setzen, je nach dem, was näher dran ist. Ist auch wesentlich weniger verwirrend als eine Kamera, die sich steuern lässt, dann aber plötzlich selbstständig wird und durch die Gegend fliegt. Danke viel Mals Sascha das erscheint mir logisch und umzusetzbar Und ich bin auch froh zu hören das ich hier das Maximum aus dem hier rausgeholt habe was möglich ist. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.