Jump to content
Unity Insider Forum

Quiz multiple choice


Blattfressi

Recommended Posts

Hallo!

Ich möchte/soll für meine Schule ein Spiel für's  italienisch lernen programmieren. Es soll eine Art Suchbild werden, also die Frage steht oben z.B. "Es ist rot und steht im Regal." (also halt auf italienisch) und dann muss man im Bild auf besagtes Objekt klicken. 

Ich bin schon soweit, dass ich ein Array mit dem Text der Frage und einem GameObject angelegt habe. Was ich jetzt nicht hinbekomme ist, dass ich ja will, das beim anklicken des Bildes/gamelbjects, welches für die jeweilige Frage als Antwort markiert ist, etwas passiert (ein text mit "richtig!") zum Beispiel. 

Aber wie geht das, kann mir da jemand helfen?

 

Danke( =

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin!

Am 17.4.2021 um 19:41 schrieb Blattfressi:

Ich bin schon soweit, dass ich ein Array mit dem Text der Frage und einem GameObject angelegt habe.

Das ist schon sehr gut. So aus Interesse: Hast du dafür ein Struct benutzt?

Aber zur Frage: Der Ablauf muss prinzipiell beim Objekt losgehen, das angeklickt wurde. Du kannst den Objekten je einen Collider geben, der als Klickfäche dient, und dann sollte OnMouseDown immer noch funktionieren. Du kannst erst einmal mit so etwas simplem anfangen wie

private void OnMouseDown()
{
  Debug.Log(gameObject.name + " wurde angeklickt.");
}

Wenn das funktioniert, müssen wir von hier irgendwie zu deiner zentralen Stelle, wo das Array definiert ist. Ich nehme an, du hast ein GameObject mit deinem Script darauf, das das Array enthält.

Hier gibt es jetzt mehrere Möglichkeiten, von deinen keine direkt auszuschließen wäre - auf die Vor- und Nachteile einzugehen wäre aber vermutlich etwas viel für ein Schulprojekt :)

Da du ja bereits die "Klick-Objekte" in dein Array ziehst (finde ich wie gesagt sehr gut), ist es eher weniger sinnvoll, jetzt auch umgekehrt das Objekt mit dem Array wiederum in die Klick-Objekte zu ziehen. Stattdessen kann dein "Quiz-Master-Objekt" zu den Klick-Objekten gehen und ihnen Bescheid sagen, dass sie sich bei ihm melden sollen, wenn sie angeklickt werden.

Das geht z.B. so:

public class ClickableAnswer : MonoBehaviour
{
  public event Action clickResponse;

  private void OnMouseDown()
  {
    clickResponse();
  }
}

Ein Event ist ein Ding, das Reaktionen kennt (in Form von Code, der auszuführen ist) und diese ausführt, wenn es "ausgelöst" wird. Das auslösen passiert hier in OnMouseDown, sieht absichtlich wie bei einer Methode aus.

Anderer Code kann jetzt zu einem ClickableAnswer-Objekt gehen und eine Reaktion zum Event hinzufügen - so etwas wie "sag mir Bescheid", sozusagen.

So könnte dann der QuizMaster aussehen, in dem das Array drinsteht, wie ich es mir gerade nach deiner Beschreibung vorstelle:

public class QuizMaster : MonoBehaviour
{
  [System.Serializable]
  private struct QuestionAndAnswer
  {
    public string question;
    public ClickableAnswer answerObject; // Direkt den Komponententyp statt "GameObject"
  }
  
  public QuestionAndAnswer[] questions;

Jetzt kannst du in Start durch das Array gehen und allen Antwort-Objekten sagen, dass sie Bescheid sagen sollen, wenn sie angeklickt sind:

private void Start()
{
  foreach (var questionAndAnswer in questions)
  {
    var clickableObject = questionAndAnswer.answerObject;
    // Der folgende Teil für eine Reaktion zum Event hinzu.
    // Es soll OnAnswerWasClicked aufgerufen werden, mit dem angeklicken Objekt als Parameter.
    clickableObject.clickResponse += () => OnAnswerWasClicked(clickableObject);
  }
}

private void OnAnswerWasClicked(ClickableAnswer clickedObject)
{
  Debug.Log(clickedObject.gameObject.name + " wurde angeklickt");
}

Wenn du jetzt eine Frage auswählst, kannst du das passende Antwort-Objekt in einer Variable speichern und beim Aufruf von OnAnswerWasClicked schauen, ob dasselbe Objekt reinkommt:

private ClickableAnswer currentCorrectAnswer;

public void PickQuestion()
{
  var question = questions[Random.Range(0, questions.Length)];
  someText.text = question.question;
  currentCorrectAnswer = question.answerObject;
}

private void OnAnswerWasClicked(ClickableAnswer clickedObject)
{
  var isCorrectAnswer = clickedObject == currentCorrectAnswer;
  
  if (isCorrectAnswer)
  {
    someText.text = "Correttamente!";
  }
  else
  {
    someText.text = "Non corretto.";
  }
}

Das ist jetzt wie gesagt einer von vielen Wegen. An diesem Weg ganz gut ist, dass die ClickableAnswer-Objekte nicht alle etwas zugewiesen bekommen müssen. Du erstellst einmalig ein neues Element in deiner Liste im Inspektor und definierst da die Frage und welches Objekt die richtige Antwort darstellt. Bei einer schlechteren Variante müsste man mehr Schritte beim Verkabeln machen, bevor es funktioniert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 4 weeks later...

Archiviert

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

×
×
  • Neu erstellen...