Jump to content
Unity Insider Forum

Game-Objects zufällig auswählen


peachplayer

Recommended Posts

Hallo Leute

Ich habe folgendes Problem: ich möchte eine Art Quiz erstellen mit 8 verschiedenen Bildern, die als Game-Objects definiert werden.

Nun will ich die Game-Objects in zufälliger Reihenfolge anzeigen lassen. Leider klappt das nicht so richtig! Ausserdem bekomme ich eine Fehlermeldung in Zeile 41:

"IndexOutOfRangeException: Array index is out of range." Kann mir jemand helfen?

Gruss

Peachplayer

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

public class Video_show : MonoBehaviour
{
    public GameObject[] Felder;
    public GameObject button1;
    public string[] answers = new string[8];
    private int i;
    private int k;
    private int Score;
    public Text ScoreAnzeige;
    public Text Antwort;
    public InputField AnswerEingabe;
    public bool antwort;
    static int erwartet = 0;
    public int scoreValue;
    private Button button2;
    public Toggle anzeigeSchalter;
    public AudioClip richtig_sound;
    public AudioClip falsch_sound;
    public GUIText scoreText;
    private int score;
    private AudioSource source;

    void Awake()
    {

        source = GetComponent<AudioSource>();
    }
    
    
    // Use this for initialization
    void Start()
    {


        answers[0] = "Winterweizen"; //** hier kommt die Fehlermeldung!**
        answers[1] = "Naturwiese";
        answers[2] = "Wintergerste";
        answers[3] = "Naturwiese";
        answers[4] = "Winterweizen";
        answers[5] = "Winterweizen";
        answers[6] = "Mais";
        answers[7] = "Wintergerste";

        score = 0;
   
      

    // Update is called once per frame

    }
 

    public void NeueAntwortHinzu()
    {

               
                   k=Convert.ToInt32(Felder[i].tag);
                    if (answers[k] == AnswerEingabe.text)            {
                antwort = true;
                Antwort.text = "Richtig!";
                if (anzeigeSchalter.isOn)
                {
                    score++;
                    source.PlayOneShot(richtig_sound);
                }
                else
                    score += 3;
                source.PlayOneShot(richtig_sound);
                ScoreAnzeige.text = "Score: " + score;
               
  
                
              
            }
                    else
                        Antwort.text = "Falsch!";
                    source.PlayOneShot(falsch_sound);
                   
     
   
        
    }
    public void OnGUI()
    {
       
        if (GUI.Button(new Rect(100, 100, 100, 50), "vorwärts") && (i <= (Felder.Length - 1)))
        {

           
                
                    i = UnityEngine.Random.Range(0, 7);
                    Debug.Log(i);
                    Debug.Log(Felder[i].tag);
                    if (i > 0)
                    {
                        Felder[i - 1].SetActive(false);
                        Felder[i].SetActive(true);
                    }
                    else
                        Felder[0].SetActive(true);

                
            }
           
        

        }
    
    }
   

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Von der Bilderanzeige hast du bisher gar nichts erzählt? Worum geht es denn da?

So auf Anhieb sehe ich nur diese Stelle hier:

if (anzeigeSchalter.isOn)
                {
                    score++;
                    source.PlayOneShot(richtig_sound);
                }
                else
                    score += 3;
                source.PlayOneShot(richtig_sound);
                ScoreAnzeige.text = "Score: " + score;

und dass da der Sound zwei Mal abgespielt werden kann. Vermutlich fehlen da Klammern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich rate jetzt einfach mal, dass "Felder" die GameObjects referenzieren soll, die diese Bilder darstellen? Warum arbeitest du da mit Tags?

Außerdem solltest du dir angewöhnen, lokale Variablen zu beutzen. Man muss Variablen nicht ganz oben alle hintereinander definieren und wenn du da oben Variablen hast, die "k" oder "i" heißen, dann läuft schon einmal etwas schief. Auch, dass die Variablennamen mal groß, mal klein geschrieben sind, ist nicht gut. Mir fällt es insgesamt sehr schwer, deinen Code zu lesen.

Aber als erstes solltest du dich von Tags verabschieden. Du hast offenbar die Tags "1"-"8" oder so definiert. Tags sind aber überaus ungeeignet für das, was du machen willst. Ich schlage vor, du erstellst ein neues Script. Jedes Feld bekommt dann eine Instanz davon, und in diese Komponente schreibst du alles, was das Feld ausmacht, hinein. Statt also für deine metaphorische Garage einer Liste der Automarken und eine Liste der Farben zu führen, führst du nur noch eine Liste der Autos, und jeder Auto-Eintrag besteht dann aus Marke und Farbe. Wann immer man mehrere Listen hat, deren Indices übereinstimmen müssen, macht man etwas falsch und fällt dadurch früher oder später auf die Nase.

In deinem Fall wäre das Script also etwa sowas:

class AnswerField : MonoBehaviour
{
  public string answer;
}

und in deinem Script oben machste dann

public AnswerField[] answerFields;

Zugriff dann z.B. so:

Debug.Log(answerFields[0].answer);

 

Am Ende noch: Verabschiede dich so früh wie möglich von OnGUI. Solange du keine Editor-Plugins schreibst oder wirklich schnell prototypen willst, hast du ausschließlich Nachteile davon, das zu benutzen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke für die Antwort! Habe den Code nochmals geändert und bekomme leider in Zeile 43 noch die Fehlermeldung: "NullReferenceException: Object reference not set to an instance of an object". Kann mir jemand helfen?

Gruss
Peachplayer

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

public class Video_show : MonoBehaviour
{
    public GameObject[] Felder;
    public GameObject button1;
    public string[] Answer;
    private int i;
    private int k;
    private int Score;
    public Text ScoreAnzeige;
    public Text Antwort;
    public InputField AnswerEingabe;
    public bool antwort;
    static int erwartet = 0;
    public int scoreValue;
    private Button button2;
    public Toggle anzeigeSchalter;
    public AudioClip richtig_sound;
    public AudioClip falsch_sound;
    public GUIText scoreText;
    private int score;
    private AudioSource source;
    public AnswerField[] answerFields;

    void Awake()
    {

        source = GetComponent<AudioSource>();
    }
    
    
    // Use this for initialization
    void Start()
    {

        answerFields = new AnswerField[8];

        answerFields[0].Answer = "Winterweizen";
        answerFields[1].Answer = "Winterweizen";
        answerFields[2].Answer = "Naturwiese";
        answerFields[3].Answer = "Wintergerste";
        answerFields[4].Answer = "Naturwiese";
        answerFields[5].Answer = "Winterweizen";
        answerFields[6].Answer = "Winterweizen";
        answerFields[7].Answer = "Mais";
        answerFields[8].Answer = "Wintergerste";

        score = 0;
   
      

    // Update is called once per frame

    }
 

    public void NeueAntwortHinzu()
    {


        for (int i = 0; i < 8; i++)
        {
            if (answerFields[i].Answer == AnswerEingabe.text) //** hier kommt die Fehlermeldung **
            {
                antwort = true;
                Antwort.text = "Richtig!";
                if (anzeigeSchalter.isOn)
                {
                    score++;
                    source.PlayOneShot(richtig_sound);
                }
                else
                    score += 3;
                source.PlayOneShot(richtig_sound);
                ScoreAnzeige.text = "Score: " + score;




            }
            else
                Antwort.text = "Falsch!";
            source.PlayOneShot(falsch_sound);


        }
        
    }
    public void OnGUI()
    {
       
        if (GUI.Button(new Rect(100, 100, 100, 50), "vorwärts") && (i <= (Felder.Length - 1)))
        {

           
                
                    i = UnityEngine.Random.Range(0, 7);
                    Debug.Log(i);
                    Debug.Log(Felder[i].tag);
                    if (i > 0)
                    {
                        Felder[i - 1].SetActive(false);
                        Felder[i].SetActive(true);
                    }
                    else
                        Felder[0].SetActive(true);

                
            }
           
        

        }
    
    }


 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ist bei mir Zeile 68 und der Grund ist, daß "AnswerEingabe" ein "InputField" ist welches von Außen dem Skript übergeben werden muss. Wenn du deinem Skript im Inspektor nichts übergibst, dann kommt diese NPE sobald du versucht auf "AnswerEingabe" zuzugreifen und da die Referenz bei dir vermutlich nicht gesetzt ist kommt bei dir der Fehler.

Link zu diesem Kommentar
Auf anderen Seiten teilen

NullReferenceExceptions treten dann und nur dann auf, wenn links vom Punkt oder ein Array beim Zugriff null ist.

Bei deiner Zeile Code heißt das, entweder answerFields ist null oder answerFields ist null. Da answerFields nicht null sein wird, weil es von Unity Deserialisiert wird, muss answerFields null sein. Da muss im Editor also noch etwas reingezogen werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dann hast du meinen Post nicht richtig gelesen. Du solltest im Allgemeinen immer erst verstehen, was da passiert, bevor du Code abtippst. Dass du meine Codeschnipsel übernommen hast, ohne verstanden zu haben, wie die überhaupt gemeint sind, ist eine sehr schlechte Idee. Stelle lieber Fragen über Dinge, die du daran nicht verstanden hast.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mein Code sieht jetzt folgendermassen aus. Leider kommt immer noch die " "NullReferenceException: Object reference not set to an instance of an object" Fehlermeldung! bei Zeile 64 und 81. Kann mir jemand helfen?

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

public class Video_show : MonoBehaviour
{
    public GameObject[] Felder;
    public GameObject button1;
   

    private int k;
    private int Score;
    public Text ScoreAnzeige;
    public Text Antwort;
    public InputField AnswerEingabe;
    public bool antwort;
    static int erwartet = 0;
    public int scoreValue;
    private Button button2;
    public Toggle anzeigeSchalter;
    public AudioClip richtig_sound;
    public AudioClip falsch_sound;
    public GUIText scoreText;
    private int score;
    private AudioSource source;
    public string[] Antworten;
    public List<AnswerField> liste_answer;

    void Awake()
    {

        source = GetComponent<AudioSource>();
    }
    
    
    // Use this for initialization
    void Start()
    {

        Antworten = new string[9];

        Antworten[0] = "Winterweizen";
        Antworten[1] = "Winterweizen";
        Antworten[2] = "Naturwiese";
        Antworten[3] = "Wintergerste";
        Antworten[4] = "Naturwiese";
        Antworten[5] = "Winterweizen";
        Antworten[6] = "Winterweizen";
        Antworten[7] = "Mais";
        Antworten[8] = "Wintergerste";
               
        score = 0;
        Listefüllen();
    }
    public void Listefüllen()
    {
       
        for (int i = 0; i < 9; i++)
        {
 
            AnswerField eintrag = new AnswerField(Antworten[i], i);
            liste_answer.Add(eintrag); // ** hier gibts eine Fehlermeldung **
        }
        }

   
  

    // Update is called once per frame


 

    public void NeueAntwortHinzu()
    {

        Debug.Log(AnswerEingabe.text);
        for (int i = 0; i < 9; i++)
        {
            if (liste_answer[i].getanswer() == AnswerEingabe.text) // ** hier gibts eine Fehlermeldung **
            {
                antwort = true;
                Antwort.text = "Richtig!";
                if (anzeigeSchalter.isOn)
                {
                    score++;
                    source.PlayOneShot(richtig_sound);
                }
                else
                    score += 3;
                source.PlayOneShot(richtig_sound);
                ScoreAnzeige.text = "Score: " + score;




            }
            else
                Antwort.text = "Falsch!";
            source.PlayOneShot(falsch_sound);


        }
        
    }
    public void OnGUI()
    {
        
        if (GUI.Button(new Rect(100, 100, 100, 50), "vorwärts") && (k <= (Felder.Length - 1)))
        {

           
                
                    k = UnityEngine.Random.Range(0, 7);
                    Debug.Log(k);
                    Debug.Log(Felder[k].tag);
                    if (k > 0)
                    {
                        Felder[k - 1].SetActive(false);
                        Felder[k].SetActive(true);
                    }
                    else
                        Felder[0].SetActive(true);

                
            }
           
        

        }
    
    }

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich mir diese Zeile

AnswerField eintrag = new AnswerField(Antworten[i], i);

so ansehe, dann kann ich meine letzte Antwort nur wiederholen. Du rätst gerade einfach nur blind und das führt zu nichts. Dein Code besteht inzwischen aus mehr unnützen Zeilen aus irgendwelchen Experimenten als aus tatsächlich nützlichem Code. An deiner Stelle würde ich jetzt echt die Handbremse ziehen, das Ding wegschmeißen und noch einmal ganz von vorne anfangen. Bei Fragen helfen wir auch gerne.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sehe ich auch so wie Sascha, die Fehler kommen von unsauberem Code und diese Stellen werden immer mehr, wenn du den Code nicht aufräumst und daher wäre es am besten du fängst noch einmal von vorn an und versuchst erst einmal eine bestimmte Sache zu lösen und wenn diese sauber läuft, dann baust du den Code weiter aus.
Versuche auch einmal die public Variablen zu reduzieren und wenn du welche verwendest, dann bitte in der Start-Methode prüfen, ob gültige Referenzen übergeben wurden. Zudem würde ich dir raten nur Listen zu verwenden, da ich vermute, daß die Verwendung von Arrays für dich zu komplex ist. 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielleicht sollte man erstmal eim C# Tutorial in Erwägung ziehen und ein bisschen lernen. Dann klappt das mit dem Verständnis für deine Fehler in deinem Array auch besser. Habe mir jetzt nur kurz überflogen aber es macht auf mich den Eindruck, dass es besser ist sich intensiver mit den Basics von C# und Unity zu befassen oder sich andere Projekte anzuschauen und diese versuchen zu verstehen. Ich denke mal wenn dir hier jede Zeile vorgegakelt wird, weißt du am Ende des Tages wahrscheinlich immernoch nicht was du da genau gemacht hast. 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich verstehe die Frage nicht so ganz, du hast doch sämtliche Gameobjekte über das Array im Zugriff und über den Index wählst du eines aus. Zudem haben die Gameobjekte auch Namen, die du im Inspektor setzen kannst. Ich denke du kannst dich komplett von den Tags verabschieden.
Die Reihenfolge der Gameobjekte innerhalb des "Felders"-Arrays bleibt erhalten, so wie du sie dem Skript von außen übergibst.

PS:
Du kannst Gameobjekte auch untereinander vergleichen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo Leute

Habe mein Projekt neu gemacht und das Problem mit der Referenzierung mit hilfe von "enumerationen" und den "Gameobject-names" gelöst.

Jetzt klappt eigentlich alles, ausser die Text-Anzeige "richtig" oder "falsch" funktioniert leider nicht richtig. Kann mir jemand helfen?

Gruss

Peachplayer

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


public class Video_show : MonoBehaviour
{
    public GameObject[] Felder;
    public GameObject button1;
    public enum Antworten { Naturwiese = 1, Winterweizen = 0, Wintergerste = 2, Mais = 3};
    private int i;
    private int k;
    private int Score;
    public Text ScoreAnzeige;
    public Text Antwort;
    public InputField AnswerEingabe;
    public bool antwort;
    private Button button2;
    public AudioClip richtig_sound;
    public AudioClip falsch_sound;
    private int score;
    private AudioSource source;
    private int currentIndex = 0;
    private int count = 0;
    public Dropdown dropDown;
  

    void Awake()
    {

        source = GetComponent<AudioSource>();
    }


    // Use this for initialization
    void Start()
    {
        
        count = Felder.Length;
        Switch(0);

        score = 0;


        // Update is called once per frame

    }

    public void NeueAntwortHinzu()
    {
        Antworten answer1, answer2, answer3, answer4;

        Antwort.text = "";
        k = dropDown.value;
        i = currentIndex;
        Debug.Log(Felder[i].name);

        answer1 = Antworten.Naturwiese;
        if ((int)answer1 == dropDown.value && (Felder[i].name == "Naturwiese"))
        {
            antwort = true;
            Antwort_ausgeben(antwort);
        }
            else
        {
            antwort = false;
            Antwort_ausgeben(antwort);
        }
            answer2 = Antworten.Winterweizen;
        if ((int)answer2 == dropDown.value && (Felder[i].name == "Winterweizen"))
        {
            antwort = true;
            Antwort_ausgeben(antwort);
        }
            else
        {
            antwort = false;
            Antwort_ausgeben(antwort);
        }
            answer3 = Antworten.Wintergerste;
            if ((int)answer3 == dropDown.value && (Felder[i].name == "Wintergerste"))
            {
                antwort = true;
                Antwort_ausgeben(antwort);
            }
                else
            {
            antwort = false;
            Antwort_ausgeben(antwort);
            }
                answer4 = Antworten.Mais;
                if ((int)answer4 == dropDown.value && (Felder[i].name == "Mais"))
                {
                    antwort = true;
                    Antwort_ausgeben(antwort);

                }
            }
       
    

    public void OnGUI()
    {

        if (GUI.Button(new Rect(100, 100, 100, 50), "vorwärts") )
        {



            currentIndex++;
            if (currentIndex >= count)
                currentIndex = 0;
            Switch(currentIndex);
        }
}

    void Antwort_ausgeben(bool antwort)
    {
        if (antwort == true)
        {
            Antwort.text = "Richtig!";
            score++;
            ScoreAnzeige.text = "Score: " + score.ToString();
            source.PlayOneShot(richtig_sound);
        }
        else 
        {
            Antwort.text = "Falsch!";
            ScoreAnzeige.text = "Score: " + score.ToString();
            source.PlayOneShot(falsch_sound);
        }
    }
    void Switch(int activeIndex)
        {
            for(int i=0; i< count; i++)
            {
                if(i != activeIndex)
                {
                    Felder[i].SetActive(false);
                }
                else
                {
                    Felder[i].SetActive(true);
                }
            }
        

    }

}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...