UGTK cat mascotUGTKengine within an engine Request access

UGTK / Toolkit / Gameplay Systems / Quiz System Completed

Gameplay Systems — UGTK

Quiz System

Summary

A data-driven quiz minigame: quizzes and questions are authored in SO_LinearQuiz / SO_GridQuiz ScriptableObjects (importable/exportable as CSV/JSON), one database per language. A manager picks the localized database, a controller builds and sequences questions, and a UI manager shows answer groups and colored correct/wrong feedback, tallying points to a win/lose result.


Content


Modules Dependencies

Carried inside the prefabs. These modules are not referenced by the assembly definition - the components are simply already attached to the prefabs this module ships. Remove one of them from the project and the prefab keeps its layout and loses that behaviour, with nothing in the console to say so.

Module Component, and the prefab carrying it
UIModule/TextUpdaterSystem Mn_TextUpdater (in SingleAnswer)

Setup

The questions live in an asset, not in the scene.

  1. Create a quiz database: SO_LinearQuiz for a fixed run of questions, or SO_GridQuiz when the questions form a board (categories across, difficulty down).
  2. Fill it in the inspector, or import a CSV - QuizTemplate_Example.csv in Debug/ is the shape the importer expects.
  3. Add the QuizManager prefab and give it the database. Mn_QuizManager runs the quiz; Mn_QuizController drives one question; Mn_QuizUiManager is a Mn_Singleton holding the screens.
  4. Choose the answer layout: QuizGroup2 through QuizGroup6 are ready-made for two to six answers, with SingleAnswer as the button they clone and Question as the question row.

Check the CSV import against a question containing a comma before trusting it, and quote the field the way the template does. A quiz whose questions are ordinary prose will contain commas on the first day, and an importer that splits naively shifts every later column without ever failing.

If the game is multilingual, the LanguageSystem picks the database per language through a generated S_Dictionary - one quiz asset per language, selected for you.


How To Use

  1. Author data: create an SO_LinearQuiz (or SO_GridQuiz) asset holding quizzes; each quiz has a list of S_Question (question text, one correct answer, wrong answers, points, position/randomization flags). Data can be imported/exported via the CSV and JSON utilities (QuizCsvUtility, QuizJsonUtility, QuizExportEditorUtility).
  2. Scene setup: place the provided prefabs — QuizManager, QuizController, QuizUiManager, a Question, SingleAnswer and the QuizGroupN answer-layout groups (2–6 answers).
  3. Localized databases: on Mn_QuizManager, the localizedQuizDatabases dictionary auto-generates one slot per language declared in Mn_LanguageManager (keys are code-generated, do not edit by hand); assign an SO_LinearQuiz per language. A legacy single-database field is migrated automatically.
  4. Start a quiz: call StartWithFirstQuiz(), StartWithRandomQuiz(), or StartWithIDQuiz(id) (or enable startWithFirstQuizOnStart). The manager resolves the database for the current language (falling back to the first assigned one).
  5. Flow: Mn_QuizController.Init clones the quiz (optionally trimming to a fixed count or a random range of questions), then PrepareNewQuestion builds each Mn_Question and asks Mn_QuizUiManager to show the matching QuizGroupN UI. Clicking an Mn_Answer calls AnswerToQuestion, firing onAnsweredCorrectly / onAnsweredBadly; the UI manager flashes the answer color for feedbackTime seconds (optionally revealing the correct one) and then auto-advances.
  6. End: when questions run out the controller invokes onEndedQuiz; Mn_QuizManager.EndQuiz compares gained points to minimumPointsForWin and fires onWin or onLose.

Testing Scene

Open QuizSceneExample in the module's Debug/ folder.

What to do, in order:

  1. Play a full quiz to the end and check the score.
  2. Answer wrongly on purpose and see what the feedback says.
  3. Let a timed question run out without answering.
  4. Import a CSV whose question text contains a comma, and a quoted field.

Step 4 is the one that breaks naive implementations: a question containing a comma is completely ordinary, and a parser that simply splits on the separator corrupts the whole row. Step 3 is the state players reach constantly and developers rarely test.

QuizSceneExample running the four sample riddles: the counter advances, the score updates, and the answer positions are shuffled between questions because answersRandomPosition is on.


Technical Info


© 2026 Marcello De Bonis. All rights reserved

Real dependenciesOpen in the map →

Measured from the repository: code references (asmdef) plus prefab and asset GUIDs. Importing this module alone brings in 14 modules in total.