Jump to content
Unity Insider Forum

OnTriggerStay nur von bestimmten Collidern zulassen - GELÖST


Der_Stefan_

Recommended Posts

Hallo Leute,

ich stehe gerade etwas auf dem Schlauch. Ich habe einen Tresor gebaut, der von Spieler mittels richtiger Kombination geöffnet werden kann (Wird ein Escape-Room-Spiel). 

Aktuell habe ich schon mal den Tresor, das  Öffnen wenn man davor steht, Sounds etc. für die grundsätzliche Funktion gescriptet. Die Nummernsteuerung folgt später. 

Funktioniert auch alles, alles cool. Wo ich mich aber grad wundere, ich habe dem Trigger-Collider gesagt, dass er sich nur öffnen soll, wenn der Spieler in ihm steht, sprich im Spiel, der Spieler vor dem Tresor. Jetzt die entscheidene Frage: Mache ich das nicht, indem ich den Collider nicht mit "other", sondern mit dem Namen des Spieler-Colliders benenne? Also in meinem Fall mein Männchen "Horst"?  (Siehe Zeile 18:  "void OnTriggerStay(Collider Horst)" ).

Ich habe den Trigger Collider jetzt erstmal vor den Tresor gesetzt, so dass für den Moment alles vernünftig funktioniert und ich an anderen Stellen weiterarbeiten kann. Ist aber eben nur eine temporäre Lösung, da der Tresor durchaus vom Schrank gestoßen oder der Schrank mitsamt Tresor umgeworfen werden kann. Dann ist der Schrank oder Fußboden schon Hindernis genug um ihn zu öffnen zu können - Was natürlich gerade NICHT sein soll... 

Im Anhang ein Screenshot des Tresors, mit den beiden Collidern (Tresor selbst, und der Trigger-Collider VOR dem Tresor). Und im Folgenden, mein Script so far...

Vielen Dank für eure Ideen und Anregungen.

 

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

public class Tresoroeffnen : MonoBehaviour
{
    public GameObject Karatsafe;
    public Animator anim;
    private bool open = false;
    public AudioClip Safesound;
    
    void Start()
    {
        anim = GetComponent<Animator>();
    }


    void OnTriggerStay(Collider Horst)
    {
        if (Input.GetKeyDown(KeyCode.Space) && !open)
        {
            open = true;
            anim.Play("Karatoeffnen");
            AudioSource.PlayClipAtPoint (Safesound, transform.position,1);
        }
        else if (Input.GetKeyDown(KeyCode.Space) && open)
        {
            open = false;
            anim.Play("Karatschliessen");
            AudioSource.PlayClipAtPoint (Safesound, transform.position,1);
        }
    }
}

 

snip1.JPG

Link zu diesem Kommentar
Auf anderen Seiten teilen

Da hast du grundsätzlich was falsch verstanden. Die OnTriggerStay-Methode liefert dir immer den Collider der gerade im Trigger steht. wie du diese Variable benennst, ob "other" oder "fremderCollider" oder "horst" ist völlig egal. Allerdings kannst du dir über den Collider das zugehörige GO geben lassen und hier prüfen ob es sich es im das GO handelt welches den Spieler definiert. Viele machen das über den Tag des GOs:

//Check to see if the tag on the collider is equal to Player
if (other.tag == "Player")
{
  Debug.Log("Triggered by the Player");
}

, du kannst aber auch eine Komponente des GOs abfragen und so ermitteln, welcher Collider dort in deinen Trigger geraten ist:

//Check to see if the gameObject of the collider has a PlayerController component
PlayerController playercontroller = other.gameObject.GetComponent<PlayerController>();
if (playercontroller != null)
{
   Debug.Log("Triggered by the Player");
}

In dem Beispiel hat der Spieler einen PlayerController und er wird darüber "erkannt".

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ach herrlich... Funktioniert sofort und ohne Probleme. So gefällt mir das  :)

Für alle mit dem gleichen Problem und die durch die Sucher hier gelandet sind: Hier noch mal das Script-Update an entsprechender Stelle:

 

(...)

    void OnTriggerStay(Collider other)
    {
        if (other.tag == "Player")
        {
            Debug.Log("Triggered by the Player");

            {
                if (Input.GetKeyDown(KeyCode.Space) && !open)

(...)

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 weeks later...

@ Christoph und Sascha. Wieso ist die Identifizierung nach dem Player-Tag denn nicht so gut?
Und... wahrscheinlich hab ich jetzt wieder 'n Klops im Kopf, aber die GetComponent sucht doch nur in den eigenen Reihen, oder nicht? Das entsprechende Script liegt doch auf einem ganz anderen Object als jenes, welches durch den Trigger läuft und als Player getagt ist... 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Problem bei einem Tag ist, dass es ein String ist. Also ein Wort, dass irgendwie geschrieben werden kann. Wenn der Tag "Player" heissen würde, du aber nach "player" suchst, dann wirst du ihn nicht finden, denn ein großes P ist nunmal anders als ein kleines p. Du bekommst auch beim Programmieren keinen Hinweis auf deinen Schreibfehler. Erst beim Testen des Spiels, wirst du dich wundern, dass der Code nichts macht und es kann recht lange dauern, bis du merkst, dass es einfach nur ein Schreibfehler war.

Im Gegenasatz dazu ist eine Komponente, sobald sie einmal erstellt ist, bekannt. Sie wird dir beim programmieren schon in der richtigen Schreibweise vorgeschlagen.

Komponenten kann man überall suchen, nicht nur in seinem eigenen Objekt. Du musst natürlich vorher erst einmal das Objekt selbst kennen um da drin dann die richtige Komponente zu suchen.  Beim Triggern fragst du ja das andere Objekt ab. Die Variable "other" wird dabei mit dem eben getroffenen Collider bestückt. Und bei der Abfrage willst du wissen wie der Tag des anderen Objektes "other" denn heisst. Jetzt kannst du aber auch fragen, ob das andere Objekt "other" denn eine Komponente hat, die "Player" heisst.
Zurück bekommst du bei beiden Abfragen true oder false.
Beides ist also mehr oder weniger das Gleiche.
Strings abzufragen ist immer so ein Problem, weil man sich schnell verschreiben kann und man den Fehler dann meistens nicht sofort erkennt. Wenn du z.B. mit dem Animator arbeitest, wirst du sehr schnell sehen, wie doof das ist, dass man über Strings die Animationen steuert. Mir passiert es ständig, dass ich mich entweder verschreibe oder nicht mehr weiss, wie ich den Parameter genannt hatte. Also immer wieder den Animator aufmachen und gucken was fürn Wort er denn jetzt nun haben will.

Klar wenn es einmal geht, dann geht's. Aber es ist halt sehr fehleranfällig, wenn man mit Strings arbeitet. Deswegen schlägt Sascha vor nach Möglichkeit auf Tags zu verzichten und stattdessen nach Komponenten zu suchen.

:)


 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Morgen und danke für die ausführliche Erklärung :) 
Verstehe. Das "Problem" hier ist also tatsächliche nur dass leicht Fehler bei der Eingabe passieren können. Ich hätte jetzt erstmal irgendwelche Performance-Einbußen oder sowas in der Richtung vermutet :D Immer gleich vom schlimmsten ausgehen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Performance ist nicht das wichtigste - Fehler, die schwer zu beheben sind oder Code, dessen Wartungsaufwand sehr hoch ist, schon eher :)

Aber falls es dich interessiert: Ich habe das mal durch nen Benchmark durchlaufen lassen. GetComponent ist schneller als CompareTag ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 30 Minuten schrieb Sascha:

Performance ist nicht das wichtigste - Fehler, die schwer zu beheben sind oder Code, dessen Wartungsaufwand sehr hoch ist, schon eher :)

Aber falls es dich interessiert: Ich habe das mal durch nen Benchmark durchlaufen lassen. GetComponent ist schneller als CompareTag ;)

:D :D Okay okay. Die Techniker wieder. Alles klar. Pro GetComponent... ich werd's mir merken ;) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...