Jump to content
Unity Insider Forum

Unity kommt in eine Endlosschleife bei Raycasts in Folge


uwe@doerrweb.de

Recommended Posts

Tja, das soll mal zum Spiel gehören ^^. Stell dir vor dem Spiegel eine Mauer vor, die unten nur eine Lücke hat.  Der Laser kann den Geist nicht direkt treffen, egal wie er schießt. Du hast nur einen 45 Grad Spiegel zur Verfügung, rechts positionieren und nach oben schießen klappt auch nicht. Also klappt nur, den Laser entsprechend verschieben und schräg nach unten den Spiegel treffen, der dann schräg nach oben durch die Lücke das Viech trifft.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich schaue immer noch warum  der Laser in einer bestimmten Konstellation in die falsche Richtung schießt ...

Scheinbar geht der Ray in die richtige Richtung, aber geht dann einmal um die ganze Unitywelt und trifft dann oben die Mauer und der Laser geht dann zum Collisions-Trefferpunkt und daher sieht es so aus als ob der Laser in die falsche Richtung geht -.-

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich bin jetzt auch mal wieder wortlos ^^. An der Bedingung if ((wo == -0.7f || wo == 0.7f) && counter == 0) kann es nicht liegen, denn wenn die nicht passt kommt GameOver. Wenn ein Objekt falsch getroffen wird oder es eine Mauer ist, kommt immer GameOver, eigentlich.

Die einzige Möglichkeit für so einen Effekt wäre ein Schuss in z-richtung, den Boden ignoriert er ja. Um in die Unity-Welt zu kommen, wenn er nicht z benutzt, müsste er ja durch eine Mauer schießen und das kann er nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mhh ich hab bei mir nur Boden und Object als Tags

Folgende Situation bei mir 1 Laser und 1 Spiegel der Spiegel ist auf (12.45 -4.93):
Der Laser schießt auf einen Spiegel, das geht über das Skript "Laserschuss"..
"Laserschuss" trifft einen Spiegel und übergibt diesem die nächste Schussrichtung ..  diese ist (0;-1)
"KristallSchuss" übernimmt mit der entsprechenden Richtung
und nun passiert es "KristallSchuss" trifft scheinbar wieder einen Spiegel was aber nicht sein kann bzw. darf...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Tag Mauer hab ich aber Layer nur "Boden" und "Objekt".

Hier nochmal die beiden Klassen sind nun haufenweise Debug-Ausgaben drin und ich hatte auch mal eine Sphere erzeugt am Collisionspunkt, kannst ja alles wieder rauswerfen was nicht brauchst. Nur das wir beide nun den gleichen Code haben:

using UnityEngine;

public class LaserSchuss : MonoBehaviour
{
    private LineRenderer lr;
    public LayerMask lm;
    RaycastHit2D hit;
    private bool updatean = true;
    GameObject kristall;
    private void Start()
    {
        lr = GetComponent<LineRenderer>();
        lr.enabled = true;
        lr.useWorldSpace = true;
       
    }


    private void Update()
    {
        if (updatean)
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                hit = Physics2D.Raycast(transform.position, transform.up, 1000f, lm.value);
            }
            if (hit.collider)
            {
                lr.SetPosition(0, transform.position);
                lr.SetPosition(1, hit.point);
                switch (hit.collider.tag)
                {
                    case "Mauer":
                        SoundManager.instance.GameOver.Play();
                        Destroy(this);
                        break;
                    case "Kristall":
                        updatean = false;
                        Debug.DrawRay(hit.point, hit.normal, Color.red, 100f);
                        Debug.Log("hit laser:" + hit.collider.transform.gameObject);
                        Vector2 wohin = Vector2.Reflect(transform.up, hit.normal);
                        Debug.Log("wohin Laser: " + wohin);
                        Vector2 wogetroffen = hit.point + hit.normal * 0.1f;
                        float wo = hit.normal.x;
                        wo = (float)System.Math.Round(wo, 1);
                        if (wo == -0.7f || wo == 0.7f)
                        {
                            SoundManager.instance.pickup.Play();
                            kristall = hit.collider.gameObject;
                            kristall.GetComponentInChildren<Kristall45Schuss>().schuss(wohin,wogetroffen,0);
                            break;
                        }
                        else
                        {
                            SoundManager.instance.GameOver.Play();
                            Destroy(this);
                            break;
                        }
                    case "Geist":
                        SoundManager.instance.missplace.Play();
                        Destroy(this);
                        break;
                    default:
                        Debug.Log("Ups!!!!!");
                        Destroy(this);
                        break;
                }
            }
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Kristall45Schuss : MonoBehaviour
{
    private LineRenderer lr;
    RaycastHit2D hit;
    public LayerMask lmk;
    public GameObject vater;
    GameObject kristall;
    // Update is called once per frame

    private void Start()
    {
        lr = GetComponent<LineRenderer>();
        lr.enabled = true;
        lr.useWorldSpace = true;
    }
    public void schuss(Vector2 wohin,Vector2 wov, int count)
    {        
        //hit = Physics2D.Raycast(transform.position,-transform.up, 1000f, lmk.value);
        hit = Physics2D.Raycast(wov, wohin, 5f, lmk.value);
        Debug.DrawRay(wov, wohin, Color.blue, 10f);
        Debug.Log("hit kristall:" + hit.collider.transform.gameObject);
        if (hit.collider)
        {
            lr.SetPosition(0, wov);
            lr.SetPosition(1, hit.point);
            GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            go.transform.position = hit.point;
            go.transform.localScale = new Vector3(0.5f,0.5f,0.5f);
            int counter = 0;
            switch (hit.collider.tag)
            {
                case "Mauer":
                    SoundManager.instance.GameOver.Play();
                    Destroy(this);
                    break;
                case "Kristall":
                    wohin = Vector2.Reflect(wohin, hit.normal);
                    Debug.Log("wohin Spiegel: " + wohin);
                    Vector2 wogetroffen = hit.point + hit.normal * 0.1f;
                    float wo = hit.normal.x;
                    wo = (float)System.Math.Round(wo, 1);
                    wo = 0.7f; // kannst wieder rausnehmen war nur zu testen
                    if ((wo == -0.7f || wo == 0.7f) && counter==0)
                    {
                        SoundManager.instance.pickup.Play();
                        kristall = hit.collider.gameObject;
                        Debug.Log("Rekursion: " + count + " Getroffen: " + kristall);
                        if (count < 10)
                        {
                            this.transform.parent.gameObject.GetComponent<PolygonCollider2D>().enabled = false;
                            kristall.GetComponentInChildren<Kristall45Schuss>().schuss(wohin, wogetroffen, ++count);
                        } else
                        {
                            Debug.Log("Rekursion zu hoch, breche ab !");
                        }
                        //DestroyImmediate(this);
                        break;
                    }
                    else
                    {
                        SoundManager.instance.GameOver.Play();
                        counter = 1;
                        Destroy(this);
                        break;
                    }
                case "Geist":
                    SoundManager.instance.missplace.Play();
                    Destroy(this);
                    break;
                default:
                    Debug.Log("Ups!!!!!");
                    Destroy(this);
                    break;
            }
        }
    }
}


Am besten lagerst du den ganzen Case-Quellcode auch mal nur in eine Klasse aus, weil beide Codeteile sind nahezu identisch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich übernehme mal alles. Du hast aber wieder alles in der Scene hingebastelt ^^. Die Situation, wo es nicht klappt hast du aber nicht dabei ^^. Layer Boden und Objekte ist so gedacht, ist ja nur für die Layermask gedacht. Der Tag ist für die Objekte, die trifft. Spiegel-Tag oder später Geister-Tag ist gut, falsche Treffer der Spiegel und Tag-Mauer sind GameOver.

Ich habe im Game dem Laser einen Rechtsklick verpasst und den Spiegel auf die fünfte Stelle vom Spielfeld in y gesetzt. Dann mit 3 rechtsklicks in die waagerechte Position gebracht. Wenn ich dann den Laser auslöse passiert nichts, kein Schuss zu sehen. Danach hab ich dem abschuss des Lasers den Tag Mauer gegeben und er geht sofort in GameOver, also schießt er  zurück zum Sender, warum auch immer.

Ich danke dir für dein Engagement, jetzt muss ich aber langsam mal entspannen und dann ins Bett zu meinen Laser-Albträumen ^^. 

Gruß

Uwe

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wegen deines Problem noch. In der Klasse LaserSchuss prüfst du auch die Variable "wo" und in der Situation wo der Laser nicht gegen die Wand schießt ist "wo" = 0.
Und damit wird beim Spiegel in der Klasse LaserSchuss die Methode "schuss" nicht aufgerufen.

                        wo = (float)System.Math.Round(wo, 1);
                        Debug.Log(wo);
                        if (wo == -0.7f || wo == 0.7f)
                        {

Wn8KFli.png

Link zu diesem Kommentar
Auf anderen Seiten teilen

Na klar gibt es auch eine Anleitung und auch Verschönerungen der Grafik, Startbildschirm, Gameover-Bild usw.

Aber das kommt erst, wenn alle Technik funktioniert ^^.

Die Steuerung ist aber ganz einfach, wenn man den Laser links anklickt, lässt er sich in der Spalte wo er steht hoch und runter verschieben. Nochmal links klicken und der platziert sich in dem eingerasteten Feld. Mit Rechtsklick kann man in 45 Grad-Schritten drehen. Mit dem Spiegel ist es auch so, er springt nur aus dem "Lager" ins Spielfeld und folgt da der Maus. Abgestellte Objekte können auch umplatziert werden. Wenn ein Spiegel mit Linksklick aufgenommen hat, kann man den mit Rechtsklick löschen. Mehr zu steuern gibts da nicht, denn wenn der Laser gestartet ist, ist die Runde vorbei.

Gruß

Uwe

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mit dem Laser ging das so halbwegs, aber die Spiegel lagen ja außerhalb der Scene und ich kam da übers Game gar nicht ran. Wenn ich einen Spiegel in die Szene geschoben hatte (über Szeneview), dann konnte ich ihn meist nicht verschieben (rotieren ging hin und wieder mal). Ich denke man braucht sowas wie einen Objekt-Cursor (eine Art Rahmen) der anzeigt, ob ein Objekt markiert ist und eine andere Markierung wenn es sich im  "Rotate"- oder im "Move"-Modus befindet ;) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hm? Das verstehe ich jetzt nicht ^^. Das Spielfeld ist ein festes Raster mit x/y Einheiten. Die Camera ist auch so eingestellt, dass das Spielfeld gezeigt wird. Ich kann keinen Spiegel außerhalb des Spielfeldes platzieren. Das klicken zum Auswählen gibt einen Sound ab, beim Bewegen folgt der Spiegel der Maus, innerhalb des Spielfeldes. Beim Rotieren wird ja die Rotation sofort ausgeführt, sonst nichts, der Spiegel oder Laser wäre dann nur ein Klick lang markiert. Eine Markierung, wenn die Maus darüber ist, wäre bestimmt gut.

Wenn du innerhalb des Games einen Spiegel außerhalb des Spielfeldes platzieren kannst, geb ichs auf ^^.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...