Jump to content
Unity Insider Forum

Script wird nicht immer ausgeführt - GELÖST


Der_Stefan_

Recommended Posts

Hello again :)

 

Ich habe das unten folgende Script für ein Lichtsystem (Das Script ist eigentlich komplexer, aber zum Testen/ zur Fehlersuche habe ich es so weit runtergebrochen, dass es quasi nur noch ein einfacher Lichtschalter Ein/Aus ist):

 

Das Script funktioniert... aber aus irgendeinem Grund nicht immer. Ich drücke die Leertaste, Licht geht an ich drücke sie noch mal, Licht geht aus. Oder auch nicht. Erst wenn ich noch mal drücke. Dann funktioniert es wieder 2, 3 mal ohne Probleme, dann wieder nicht, dann wieder doch usw. Es ist auch keine Regelmäßigkeit eines Musters zu erkennen. Es funktioniert wie zufällig nicht oder doch.

Ich vermute, es liegt nicht am Script. Weil sonst würde es ja überhaupt nicht funktionieren. Aber habt ihr eine Idee wo ich sonst nachgucken könnte?
Eventuell hatte ich gebackene Lightmaps im Verdacht, aber das kann ich ausschließen. Liegt es vielleicht - ganz profan - an meiner Rechenleistung? Dass der Computer zunächst die neuen Lichtverhältnisse errechnen muss und ich erst nach Abschluss des Vorgangs einen neuen Status, sprich Ein oder Aus, setzen kann? Scheint für mich gerade die logischste Erklärung.

 

 

Hier das Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ControlerNull: MonoBehaviour 
{
    public Light Deckenlampe;
    public float intensity_off = 0f;
    public float intensity_on = 2f;


    void Start()
    { 
        Actionnote.SetActive(false);
        Deckenlampe = Deckenlampe.GetComponent<Light>();
        Deckenlampe.intensity = intensity_off;
    }

    void OnTriggerStay (Collider other)
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (Deckenlampe.intensity == intensity_on)
                {
                    Deckenlampe.intensity = intensity_off;
                }
            else
                {
                    Deckenlampe.intensity = intensity_on;
                }
        }
    }
 
Link zu diesem Kommentar
Auf anderen Seiten teilen

Schau mal hier: https://docs.unity3d.com/Manual/ExecutionOrder.html

OnTriggerStay passiert, wie FixedUpdate auch, im Physik-Update. Das kann zwischen zwei Updates mehrere Male oder auch mal gar nicht passieren. Hier hast du da einen Artikel von mir zu.

Input-Updates passieren zusammen mit Update. Im ersten Update wird die Taste gedrückt, und wenn dann direkt das nächste Update kommt, gilt sie nicht mehr als "frisch" gedrückt und GetKeyDown gibt false zurück. Wenn zwischen den beiden Updates kein FixedUpdate passiert, dann geht die Info, dass die Taste zwischenzeitlich gedrückt wurde, einfach unter.

Deine Möglichkeiten bestehen alle auf die eine oder andere Art darin, den Input und die Triggerphysik zu synchronisieren.

Du kannst z.B. auf OnTriggerStay verzichten und stattdessen Update verwenden:

private bool inTrigger = false;

private void OnTriggerEnter(Collider other)
{
  inTrigger = true;
}

private void OnTriggerExit(Collider other)
{
  inTrigger = false;
}

private void Update()
{
  if (inTrigger && Input.GetKeyDown(...))
  {
    // ...
  }
}

Wäre hier auch meine präferierte Methode.

Was auch geht, ist dass du dir den Input-Status merkst und überträgst:

private bool spaceDown = false;

private void Update()
{
  spaceDown = spaceDown || Input.GetKeyDown(KeyCode.Space);
}

private void OnTriggerStay(Collider other)
{
  if (spaceDown)
  {
    // ...
    spaceDown = false;
  }
}

Das wäre bei mir eher so die Variante bei FixedUpdate statt bei On...Stay, weil man hier ja kein On...Enter und On...Exit hat.

Eine letzte Variante wäre, das "..Down" selber zu bauen:

private bool spaceWasPressed = false;

private void OnTriggerStay(Collider other)
{
  var spaceIsPressed = Input.GetKey(KeyCode.Space); // Nicht GetKeyDown!
  
  if (spaceIsPressed && !spaceWasPressed)
  {
    // Space ist frisch gedrückt, tu Dinge
  }
  
  spaceWasPressed = spaceIsPressed;
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich gehe davon aus, dass es ein Timingproblem ist.
Ein Timingproblem deswegen, Weil OnTrigger in der FixedTime abläuft aber Input in der GameTime, also im Updatezyklus.
Beide Zeitzyklen sind unterschiedlich schnell (oft) und somit kann es sein, dass das DownEvent nicht mehr ansteht, wenn der FixedTime Zyklus dran ist.
 

Setze stattdessen in der OnTriggerEnter() (nicht Stay) Funktion einfach nur eine boolsche Variable, die bei OnTriggerExit() wieder zurück gestellt wird.
Diese Variable nutzt du dann in der Update() mit deiner Input Abfrage zusammen, um die Lampe ein oder auszuschalten.


MAAAN, eine Sekunde zuspät gedrückt. :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hach... Hätte auch zu schön sein können -.- 

Mit dem vereinfachten Test-Script funktioniert es tadellos (Wuhu :) ), beim kompletten Script funktioniert das komplette ohne die Angabe von Fehlermeldungen einfach gar nicht... Hmmm... Na ja. Jetzt habe ich aber zumindest erstmal einen funktionierenden Ansatz und begebe mich auf Fehlersuche.

Erstmal muss ich jetzt aber vor die Tür :)
Schönen Sonntag!

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 22 Stunden schrieb Sascha:

Eine letzte Variante wäre, das "..Down" selber zu bauen:


private bool spaceWasPressed = false;

private void OnTriggerStay(Collider other)
{
  var spaceIsPressed = Input.GetKey(KeyCode.Space); // Nicht GetKeyDown!
  
  if (spaceIsPressed && !spaceWasPressed)
  {
    // Space ist frisch gedrückt, tu Dinge
  }
  
  spaceWasPressed = spaceIsPressed;
}

 

Guten Morgen Sascha,

zu dieser dritten Variante habe ich mal eine Frage: Im Zuge meiner Recherchen und Suchen danach wie ich was, wie umsetzen kann, bin ich immer mal wieder über diese Variablen "var" gestoßen. Ich habe mittlerweile gelernt, dass die aus dem JavaScript kommen und sich Java nicht unbedingt immer mit C# verstehen. Die Frage ist jetzt, wenn das also ein gewisses Problempotential bietet und geplante Abläufe trotz richtigen Code-Teilen einfach nicht funktionieren, warum mischt man dann überhaupt Java und C# (Also... innerhalb einer Anwednung, nicht innerhalb eines Scriptes versteht sich)? Bietet das irgendwelche Vorteile? Kann Java Dinge, die C# nicht kann oder so?  Oder ist das schlicht und einfach persönliches gusto?

 

PS: Mein Problem mit den Lampen habe ich gestern Abend übrigens noch komplett gelöst bekommen. Kleiner Fehler im Script, schnell gefunden, alles cool, Stefan glücklich. Ich habe jetzt quasi perfekt gesteuert die Lampen an :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Der_Stefan_:

PS: Mein Problem mit den Lampen habe ich gestern Abend übrigens noch komplett gelöst bekommen. Kleiner Fehler im Script, schnell gefunden, alles cool, Stefan glücklich. Ich habe jetzt quasi perfekt gesteuert die Lampen an

Super! :)

vor einer Stunde schrieb Der_Stefan_:

zu dieser dritten Variante habe ich mal eine Frage:

Oh, da sind ganz viele Dinge falsch.

  1. JavaScript und Java sind zwei Sprachen, die unterschiedlicher kaum sein könnten. Niemals durcheinander bringen!
  2. Java und C# sind sehr ähnliche Sprachen, aber hier wird gar nicht gemischt. var gibt's in Java nicht, und in JavaScript funktioniert es anders als in C#.
    Ich habe dir reinen C#-Code gepostet :)

JavaScript ist eine dynamisch typisierte Sprache, was heißt, dass Variablen keinen festen Typ haben. Du kannst also so etwas machen:

var ding = 5;
ding = "Peter";
ding = Auto();

Der Typ der Variable "ding" ändert sich in jeder Zeile. In C# (und Java) geht das nicht. Trotzdem bietet C# var an, aber hier passiert Typ-Inferenz. Statt

int number = 10;

kannst du also schreiben

var number = 10;

und weil der Compiler weiß, dass 10 ein int ist, kann er sich das schon selber denken. Im Gegensatz zu JavaScript kann man aber jetzt nicht in der nächsten Zeile plötzlich einen String da rein tun. Man kann var auch nur an Stellen nutzen, wo der Typ der Variable eindeutig aus der Initialisierung ableitbar ist:

// Geht nicht
var number;
number = 10;

Also zusammengefasst: Wenn ich in meinem C#-Code var schreibe, dann hat das nichts mit JavaScript (und schon gar nichts mit Java) zu tun, hier wird nichts gemischt und es funktioniert Problemlos :)

Was man mit var in C# tut ist, die Robustheit ein bisschen zu erhöhen (weil man dann nicht den Variablentyp bei der Deklaration ändern muss, wenn man einen anderen Typ haben will). Dafür muss man ein bisschen auf die Lesbarkeit achten, weil es Fälle geben kann, in denen es etwas schwerer ist, zu verstehen, was die Variable macht, wenn der Typ nicht in der Deklaration drinsteht. Es zwingt einen damit aber auch zu besserer Variablenbenennung, was wieder gut ist. Ich benutzt das für lokale Variablen so ungefähr überall.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hmmm... Okay. (ich glaube) ich verstehe das... ( mehr oder weniger... :D )

Aber wenn du sagst, dass die Variablen zwar einem in Java geschriebenen Code sehr ähnlich sind aber tatsächlich doch in C# gescriptet werden, wundere ich mich dass ich das so oft im Netz lese. Ist es denn grundsätzlich möglich die Scripte in Unity in Java statt in C# zu schreiben? 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin ! Schätze du musst da etwas auf deine Quellen achten Stefan ... in früheren versionen von Unity wurden neben C# auch noch JavaScript und Boo als ScriptSprachen unterstützt. Beides wird aber (glaube ich) seit Unity 2017? 🤔 nicht mehr supported ! Falls du also Code schnipsel im internet oder in büchern findest die älter als 3 Jahre sind, kann es durchaus sein das die noch in einer anderen, heute nicht mehr unterstützten sprache geschrieben wurden.

 

Das mischen der sprachen ist grundsätzlich NICHT möglich und Unity unterstützt wie gesagt auch nur noch C# als sprache

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...