Overview
Trivia Quiz Kit is a finished, portrait trivia game you can ship as-is or reskin. Each language is one asset holding its questions, categories and UI text, edited in a dedicated editor window, so adding content or a new language needs no code. Every system (content, scoring, hints, profile, achievements, store, saving) sits behind a small interface, so you can replace any piece, for example load questions from your own server, without touching the rest.
1,600+ sample questions
Six categories in English, German and Spanish: 10 questions for every category, question type and difficulty in every language.
Three question types
Single choice, multiple choice and true/false, each with optional images and explanations.
Multilingual
One asset per language with its questions, categories and UI text. The player switches language in Settings.
Timer & scoring
Per-difficulty question count, time limit and multiplier, with streak and speed bonuses.
Hints & Skips
50/50 and Reveal hints, and Skips as the in-game currency that never breaks a streak.
Profile & achievements
Lifetime stats, per-category accuracy, and achievements that reward Skips (plus optional 50/50 and Reveal hints) when unlocked.
Hint store
Consumable Skip, 50/50 and Reveal packs through Unity IAP 5 (optional). A fake store works in the editor.
Themes
Midnight, Daylight and Candy palettes. Recolour the whole UI by editing one asset.
Editor tools
A Quiz Manager window to edit languages, categories and questions, and to import or export JSON.
Requirements
| Dependency | Version | Notes |
|---|---|---|
| Unity | 6000.0 or newer | Unity 6. |
com.unity.inputsystem | 1.20.0+ | The kit uses the Input System package only (no legacy Input class). |
com.unity.ugui | 2.0.0+ | uGUI with TextMesh Pro, built in to Unity 6. |
com.unity.nuget.newtonsoft-json | 3.2.1+ | JSON import/export and save files. |
com.unity.purchasing | 5.x | Optional Only needed to sell hint packs for real money. |
The UI is designed for portrait phones (1080×1920 reference resolution, scaled to width, with safe-area support). Content ships inside the build with your other assets, so it loads the same way on every platform.
Quick start
- Import the package Unity installs the Input System, uGUI and Newtonsoft JSON dependencies automatically.
- Enable the Input System In , set Active Input Handling to Input System Package (New) or Both. Unity restarts the editor.
- Open the sample scene
Assets/HardArtcore/TriviaKit/Scenes/TriviaQuizSample.unity - Press Play Choose a category (or Any Category), pick a mode and play a round.
In the editor the store uses a fake backend, so you can test buying hint packs without any store setup. Your progress is saved between play sessions; use Settings › Reset progress to start over.
Add the game to your own scene
- Drop in the UI prefab Drag
Prefabs/TriviaQuizUI.prefabinto your scene. It holds every screen and theQuizGameController. - Add an EventSystem Use an
EventSystemwith anInputSystemUIInputModule(not the old Standalone Input Module). - Check the controller On
QuizGameController, assign a Game Config, the Achievements you want and a Theme. The sample assets inSamples/andThemes/work as-is.
Project structure
Assets/ ├── HardArtcore/TriviaKit/ │ ├── Art/ Generated icons, UI sprites, sounds, Poppins font (OFL) │ ├── Editor/ Quiz Manager window, JSON importer/validator, sample scene builder │ ├── Prefabs/ TriviaQuizUI (root) + one prefab per screen │ ├── Runtime/ │ │ ├── Config/ GameConfig, LanguagePackAsset, SpriteLibrary │ │ ├── Data/ Question repository, query, JSON settings │ │ ├── Models/ QuestionData, AnswerData, CategoryData, LanguagePack │ │ ├── Services/ Session, scoring, hints, profile, achievements, store, saving │ │ ├── Purchasing/ Unity IAP 5 adapter (compiles only when IAP is installed) │ │ └── UI/ QuizGameController, screen views, theming, animation │ ├── Samples/ GameConfig, SpriteLibrary, sample achievements │ │ └── Languages/ Language_en, Language_de, Language_es (questions + UI text) │ ├── Scenes/ TriviaQuizSample.unity │ ├── Tests/ EditMode and PlayMode tests │ └── Themes/ Midnight, Daylight, Candy
How the game flows
QuizGameController is the only class that knows how the pieces fit together. It builds the
services, listens to the screens' events and switches screens. The screens (views) only display data and
raise events, so you can restyle or replace them freely.
- Main menu Play, Store, Profile and Settings, plus the player's Skip balance.
- Category One button per category, plus Any Category last. Any Category starts a mixed round straight away (every category and question type).
- Mode Single choice, Multiple choice or True/False. Each button shows how many questions exist for the chosen category and difficulty; modes with none are disabled.
- Quiz The question, answers, timer, score and hint buttons. After each answer, feedback is shown for
FeedbackSecondsbefore the next question. - Result A star rating that animates in, the score, and a breakdown of how it was earned. From here the player can play again or go back to the menu.
The difficulty is not asked for each round: the player sets it once in Settings.
| Prefab | View | Purpose |
|---|---|---|
MainMenu | MainMenuView | Entry point and Skip balance. |
Categories | CategorySelectView | Category list with icons. |
Modes | ModeSelectView | Question type choice with counts. |
Quiz | QuizView | Gameplay: question, answers, timer, hints, pause. |
Result | ResultView | Stars, score and breakdown tiles. |
Store | StoreView | Skip, 50/50 and Reveal packs for real money. |
Profile | ProfileView | Stats, per-category accuracy, achievements. |
Settings | SettingsView | Language, difficulty, volumes, reset progress. |
Dialog, Toast | DialogView, ToastView | Pause/confirm dialogs; "Achievement unlocked" notifications. |
Questions, categories & languages
Content is stored in regular Unity assets, so it ships inside the build (compressed with your other assets) and is edited in the editor with full Undo.
| Where | Contains |
|---|---|
GameConfig › Categories | The global category list: id, icon id and default name. Shared by all languages. |
GameConfig › Languages | The language assets the game offers, in the order shown in Settings. |
Language asset (LanguagePackAsset) | Everything for one language: its code and name, the categories it offers with their translated names, its questions, and its UI text. The samples are in Samples/Languages/. |
Use the Trivia Quiz Manager to edit all of it. You can also open a language asset in the Inspector.
Categories per language
Categories are defined once, globally, so that profile stats and icons stay consistent across languages.
Each language chooses which of them it offers: a new global category isn't offered anywhere
until you enable it for a language. A language shows only the categories it offers, in the global order,
with its own translated names (empty = the default name). iconId is looked up in the
Sprite Library.
A question may only use categories its language offers. The Quiz Manager only shows those when you edit a question, and import and Check report any other category as an error. Questions are independent in each language: a German pack doesn't need the same questions as the English one.
JSON import/export format
For bulk content and translation, a language's questions and categories can be exported to and imported from JSON with the Quiz Manager:
{
"languageCode": "en",
"displayName": "English",
"categories": [
{ "id": "geography", "localizedName": "Geography" }
],
"questions": [
{
"id": "q-fr-capital",
"text": "What is the capital of France?",
"type": "SingleChoice",
"difficulty": "Easy",
"categoryIds": [ "geography" ],
"answers": [
{ "id": "a1", "text": "Paris", "isCorrect": true },
{ "id": "a2", "text": "Lyon", "isCorrect": false },
{ "id": "a3", "text": "Berlin", "isCorrect": false },
{ "id": "a4", "text": "Madrid", "isCorrect": false }
],
"explanation": "Paris has been the capital of France since 987 AD."
}
]
}
| Field | Required | Description |
|---|---|---|
id | No | Stable question id. Leave it blank when importing and a unique id is generated for you. |
text | Yes | The question shown to the player. |
type | Yes | SingleChoice, MultipleChoice or TrueFalse. |
difficulty | Yes | Easy, Medium or Hard. |
categoryIds | Yes | One or more ids of categories this language offers (listed in categories). A question can belong to several. |
answers | Yes | The options: id, text, isCorrect and an optional imageId. |
imageId | No | An image shown above the question, resolved through the Sprite Library. |
explanation | No | Shown after the player answers. |
Question type rules
The importer and validator enforce these rules, so a pack that imports cleanly always plays correctly.
| Type | Answers | Correct answers | The player must… |
|---|---|---|---|
SingleChoice | 2 or more | Exactly 1 | Tap the correct answer. |
MultipleChoice | 2 or more | 1 or more | Select exactly the correct set, then press Submit. A missing or an extra pick counts as wrong; correct options the player missed are shown in amber. |
TrueFalse | Exactly 2 | Exactly 1 | Tap True or False (the two answer texts are yours to choose). |
Images & the Sprite Library
Content refers to images by id, never by file path, so it can be exported and imported as JSON. A
SpriteLibrary asset ()
maps each id to a Sprite. Assign it to the Game Config's Sprites field. Ids are used for category icons,
question images (imageId) and answer images (answers[].imageId). An unknown id simply
shows no image. The Quiz Manager offers the library's ids as a dropdown.
Trivia Quiz Manager
Open it with . It edits the categories on the selected Game Config and the language assets it lists. The toolbar has Save and pickers for the Game Config and Sprite Library to use.
| Tab | What you can do |
|---|---|
| Languages | See every language with its question and category counts, and change its code or name. Check validates a language and lists any problems; Select shows its asset; Delete removes it. Create a new language from a code (fr) and a display name (Français): the asset is created next to the Game Config and added to its Languages. |
| Categories | Add, rename or delete global categories and pick their icons. Then, per language, tick the categories it offers and type their translated names. Unticking a category that questions use asks first, then removes it from those questions. |
| Questions | Filter by category, difficulty and type, search question and answer text, add questions, and edit everything: text, type, difficulty, image, explanation, categories (only those the language offers) and answers. |
| Import / Export | Paste or load question JSON, Validate it (errors block the import; warnings don't), then Import with a merge mode; an unknown language code creates a new language. Export a language's questions, and export or import its UI text as JSON. |
Import modes
| Mode | Behaviour |
|---|---|
AddNew | Adds only questions whose id isn't in the pack yet; existing questions are kept unchanged. |
UpdateExisting | Replaces questions with a matching id and adds the new ones. |
ReplacePack | Discards the language's questions and categories and uses the imported ones. |
Categories listed in the imported JSON are enabled for the language (they must exist as global categories).
Every edit can be undone with Ctrl+Z. Like any asset change, edits are written to disk when you save the project or press Save in the Quiz Manager.
Write or generate questions in the pack format in any tool (a spreadsheet export, a script), leave the ids empty, and import them with AddNew. The validator reports each problem with the question it belongs to.
Configuration
Game Config
Create one with and assign it to QuizGameController. The sample uses Samples/GameConfig.asset.
| Field | Default | Description |
|---|---|---|
Categories | 6 samples | The global categories. Each language chooses which of them it offers. See Categories per language. |
Languages | en, de, es | The language assets offered in Settings, in this order. |
DefaultLanguageCode | en | Language on first launch, and the fallback for missing UI strings. |
Sprites | — | The Sprite Library for icons and images. |
StarterHintsPerType | 3 | 50/50, Reveal and Skip hints granted once on first launch (and again after a progress reset). |
FeedbackSeconds | 1.5 | How long the right/wrong feedback stays before the next question. |
StoreProducts | 5 packs | Hint packs sold in the store. See Store. |
Easy / Medium / Hard | see below | Tuning for each difficulty. |
Difficulty tuning
| Difficulty | Questions per round | Seconds per question | Score multiplier |
|---|---|---|---|
| Easy | 10 | 30 | ×1.0 |
| Medium default | 15 | 20 | ×1.5 |
| Hard | 20 | 12 | ×2.0 |
Set Seconds per question to 0 for an untimed game (this also disables the time bonus). A round draws up to Questions per round random questions that match the category, type and difficulty; if fewer exist, the round is shorter. The sample content has 10 questions per category, question type and difficulty, so a round in one category and one mode has up to 10 questions; Any Category draws from all 180 questions of the chosen difficulty.
Gameplay systems
Scoring
Each correct answer earns 100 base points. The final score is:
Total = round(BasePoints × DifficultyMultiplier) + StreakBonus + TimeBonus
- Streak bonus: the 2nd correct answer in a row adds 10, the 3rd adds 20, the 4th adds 30, and so on. A wrong answer resets the streak; a Skip does not.
- Time bonus: up to 50 points per correct answer, scaled by the fraction of the time left (answer instantly = 50, at the buzzer = 0).
Medium difficulty (×1.5, 20 s), three correct answers in a row, each after 5 seconds: base 300 × 1.5 = 450, streak 10 + 20 = 30, time 3 × 38 = 114. Total 594.
The Result screen shows these parts as tiles: Correct, Difficulty, Base points, Streak bonus and Time bonus.
Star rating
The Result screen shows three stars: one for each full third of the round answered correctly, so all three need a perfect game (for 10 questions: 4 correct = 1 star, 7 = 2 stars, 10 = 3 stars). Earned stars pop in one after another with a chime (QuizAudio.Star), then gently pulse. ResultView.StarDelay sets the pause between stars.
Timer
The timer counts down per question and ticks each second during the last 5 seconds. When it runs out, the question counts as wrong and the correct answer is shown. Pausing (the pause button, or Back/Escape) stops the timer.
Answer order
Answers appear in a new random order every time a question is shown, so players can't memorize where the correct one sits. True/False questions keep their fixed order. Turn it off with ShuffleAnswers on the QuizView (the Quiz prefab), for example if your answers include "All of the above". Shuffling never changes the order stored in the language asset.
Hints & Skips
| Hint | Effect | How the player gets more |
|---|---|---|
| 50/50 | Removes half of the answers, all of them wrong ones (4 answers → the correct one and one wrong one remain). | Starter hints, achievement rewards and the store. |
| Reveal | Highlights the correct answer(s). | Starter hints, achievement rewards and the store. |
| Skip | Moves on without recording the question: it doesn't count as wrong, doesn't break the streak and doesn't affect stats. | Starter hints, achievement rewards and the store. |
Skips are the in-game currency. Their balance is shown on the main menu; the store shows the balance of all three hints. Every player starts with StarterHintsPerType of each (Game Config, default 3).
Profile & achievements
The Profile screen shows the player's total score, games played, accuracy, questions answered, best streak, and accuracy for each category played. Below that is the achievement list.
Achievements
Each achievement is an asset ().
Add the ones you want to the Achievements list on QuizGameController. When one unlocks, the
player gets its rewards and a notification. On the Profile screen each achievement shows its progress bar and one
reward badge per hint it grants (icon + amount, for example Skip "+5" and 50/50 "+2").
| Field | Description |
|---|---|
Id | Unique id. The built-in ids below are tracked automatically. |
Title, Description | Plain text or a UI string key (e.g. ach_perfect_game_title), so they can be translated. |
Icon | Sprite shown in the row. |
Target | Progress needed to unlock (e.g. 100 for "answer 100 questions"). |
SkipReward | Skips granted on unlock. Every achievement rewards at least 1 Skip. |
FiftyFiftyReward, RevealReward | Optional 50/50 and Reveal hints granted on unlock (0 = none). |
Secret | Title and description stay hidden (???) until unlocked. The reward is still shown as a teaser. |
Built-in achievements
| Id | Sample | Tracks | Target | Reward |
|---|---|---|---|---|
games_played | Getting Started | Finished games | 5 | 3 Skips, 1 50/50 |
questions_answered | Quiz Addict | Answered questions | 100 | 10 Skips, 3 50/50, 3 Reveals |
correct_answers | Sharp Mind | Correct answers | 25 | 5 Skips, 2 Reveals |
perfect_game | Flawless | Games with no mistakes | 1 | 5 Skips, 2 50/50, 2 Reveals |
For your own achievements, choose any id and report progress from code. See Report a custom achievement.
Store & in-app purchases
The store sells consumable hint packs. Each product in StoreProducts has a ProductId, a Title (text or UI string key), the Hint it grants (Skip, FiftyFifty or Reveal) and the Amount. The defaults in Game Config are:
| Product id | Title key | Grants |
|---|---|---|
skips_5 | store_skips_5 (Handful of Skips) | 5 Skips |
skips_20 | store_skips_20 (Bag of Skips) | 20 Skips |
skips_50 | store_skips_50 (Chest of Skips) | 50 Skips |
fifty_fifty_10 | store_fifty_fifty_10 (50/50 Pack) | 10 50/50 |
reveal_10 | store_reveal_10 (Reveal Pack) | 10 Reveals |
Selling with Unity IAP
- Install Unity IAP 5 Add
com.unity.purchasing5.x through the Package Manager. The kit's adapter assembly (HardArtcore.TriviaKit.Purchasing) compiles as soon as the package is present and registers itself; no code is needed. - Create the products In Google Play Console and/or App Store Connect, create consumable products with exactly the ids from
StoreProducts. Prices come from the store, already localized. - Test on a device Use a test account from the store.
| Situation | Store behaviour |
|---|---|
| Unity IAP installed | Real store (App Store / Google Play). |
| No IAP, editor or development build | Fake store: purchases succeed instantly, for testing. |
| No IAP, release build | No store: the Store button is hidden. Hints are still earned from achievements. |
Hints are granted and saved before the order is confirmed with the store. If the app is closed mid-purchase, the store delivers the order again on the next launch, and already granted transactions are remembered, so the player never loses or doubles a purchase.
UI & theming
The UI is uGUI + TextMesh Pro with the Poppins font. Each coloured element has a ThemedGraphic
component with a colour role; a UITheme asset provides the colour for each role.
Assign a theme to QuizGameController.Theme and the whole UI is recoloured at startup.
| Role | Used for |
|---|---|
Background | Screen background. |
Surface / SurfaceAlt | Cards, rows and dialogs / secondary buttons and unanswered options. |
Primary / OnPrimary | Main buttons and highlights / text and icons drawn on them. |
Text / MutedText | Main and secondary text. |
Correct / Wrong / Missed | Answer feedback; Missed marks correct options the player didn't pick. |
Danger | Destructive actions (Reset progress). |
Overlay | The dimmed background behind dialogs. |
Three themes are included in Themes/: Midnight (dark, default), Daylight (light) and Candy (purple and pink). To make your own, duplicate one or use . To theme an element you add yourself, give it a ThemedGraphic and pick a role.
Rebuilding the prefabs
regenerates every UI prefab, the sample scene, and the generated art and sounds. Existing themes, the Game Config and the art files are reused rather than overwritten.
Rebuilding overwrites changes made to the kit's prefabs and sample scene, and resets the sample achievements' targets and rewards. Customize copies or prefab variants of the prefabs, not the originals.
Localization
Text comes from two places:
- Content (questions, answers, category names) comes from the language assets. See Questions, categories & languages.
- UI strings (buttons, titles, messages) come from the UI Strings list on the same language asset: key → text pairs.
{0},{1}… are filled in at runtime.
Edit single strings in the Inspector of the language asset. For translators, the Quiz Manager's Import / Export tab exports a language's UI text as a flat JSON table and imports it back:
{
"menu_play": "Play",
"game_question_progress": "Question {0} of {1}",
"result_title_perfect": "Perfect!",
"achievement_reward": "Reward: {0}",
"store_skips": "+{0} skips"
}
A key missing from the active language falls back to the default language's table, then to the key itself, so a missing translation never breaks the UI. Static labels in the prefabs use the LocalizedText component with a Key; they update when the player changes language.
Add a language
- Create the language In the Quiz Manager's Languages tab, enter the code (
fr) and name (Français) and press Create. It's added to the Game Config and appears in Settings right away, starting with a copy of the default language's UI text. - Choose its categories In the Categories tab, tick the categories the language offers and type their translated names.
- Add questions Write them in the Questions tab, or import a translated question JSON.
- Translate the UI Edit the UI Strings on the language asset, or export the UI text, translate the values (keep the keys) and import it back.
Poppins covers Latin scripts. For Cyrillic, Greek, Arabic, CJK and other scripts, add a TextMesh Pro font asset with those glyphs as a fallback font of the Poppins font assets.
Audio
QuizAudio (on the Audio object inside TriviaQuizUI) plays music and sound effects on two AudioSources whose volumes follow the player's Settings. Leave a clip empty to silence it.
| Clip | Played when |
|---|---|
Music | Looping background music. |
Click | Any button is pressed. |
Correct / Wrong | An answer is right / wrong or time runs out. |
Tick | Each of the last 5 seconds of the timer. |
Unlock | An achievement unlocks or a purchase completes. |
Star | Each earned star pops in on the Result screen. |
Input & navigation
- Touch and mouse work through uGUI with the Input System's UI module.
- Back: Esc, the gamepad's East button (B / Circle) and Android's back gesture go back one screen, and pause during a game.
- Gamepad: when a gamepad is connected, each screen selects its first button, so the whole game can be played without a pointer.
Saving & player data
| Data | Stored in |
|---|---|
| Profile (stats, last 50 answers) | persistentDataPath/TriviaQuizKit/profile.json |
| Achievement progress | persistentDataPath/TriviaQuizKit/achievements.json |
| Hints & Skips | persistentDataPath/TriviaQuizKit/hints.json |
| Settings (language, difficulty, volumes) | PlayerPrefs, key HardArtcore.TriviaKit.Settings |
Settings › Reset progress clears the profile, achievements, hints and settings, and grants the starter hints again. To save somewhere else (for example a cloud save), implement ISaveService. See Services.
Scripting & extending
Services
QuizServices bundles every system. QuizGameController creates it in Awake
with QuizServices.CreateDefault and exposes it as QuizGameController.Services.
All types are in the HardArtcore.TriviaKit.* namespaces.
| Property | Interface | Default implementation |
|---|---|---|
Repository | IQuestionRepository | LanguagePackRepository (the Game Config's language assets) |
ScoreCalculator | IScoreCalculator | DefaultScoreCalculator |
Hints | IHintService | DefaultHintService |
Profile | IProfileService | DefaultProfileService |
Achievements | IAchievementService | DefaultAchievementService |
Localization | ILocalizationService | AssetLocalizationService (the language assets' UI strings) |
Settings | ISettingsService | PlayerPrefsSettingsService |
Save | ISaveService | JsonFileSaveService |
Purchases | IPurchaseService | Unity IAP adapter, FakePurchaseService, or none |
Repository and ScoreCalculator can be replaced from your own script after the
controller's Awake (see the example below). The other services are connected to each other when they are
created (for example, achievements grant Skips through Hints), so to replace one of those, change
the QuizServices.CreateDefault(...) call in QuizGameController.Awake. To use a
different store backend, set QuizServices.PurchaseServiceFactory before the scene loads.
Change the scoring
using HardArtcore.TriviaKit.Services;
using HardArtcore.TriviaKit.UI;
using UnityEngine;
// Order 100: Awake runs after QuizGameController.Awake (order 0) and before any Start.
[DefaultExecutionOrder(100)]
public class TriviaCustomization : MonoBehaviour
{
[SerializeField] private QuizGameController game;
private void Awake()
{
// 250 points per correct answer, +25 per streak step, up to 100 time bonus.
game.Services.ScoreCalculator = new DefaultScoreCalculator(
game.Config, pointsPerCorrect: 250, streakStep: 25, maxTimeBonus: 100);
}
}
For completely different rules, implement IScoreCalculator: it receives the finished round (QuizSessionResult, with every answer's correctness, time taken and hint use) and returns a ScoreBreakdown.
Report a custom achievement
Create an Achievement asset with your own id (e.g. share_result), add it to the controller's Achievements list, and report progress when it happens:
// Adds 1 to "share_result"; at its Target it unlocks, grants its hint rewards and shows a notification.
game.Services.Achievements.Report("share_result");
// Report(id, amount) adds more than one at a time.
game.Services.Achievements.Report("daily_streak", 1);
Grant hints
// For example, as a rewarded-ad reward. The balance updates everywhere and is saved.
game.Services.Hints.Grant(HintType.Skip, 3);
game.Services.Hints.Grant(HintType.FiftyFifty, 1);
game.Services.Hints.Grant(HintType.Reveal, 1);
Load questions from your server
Implement IQuestionRepository. Its methods are async, so remote loading fits in naturally. Assign it from a script like the one in Change the scoring:
using System.Collections.Generic;
using System.Threading.Tasks;
using HardArtcore.TriviaKit.Data;
using HardArtcore.TriviaKit.Models;
public class RemoteQuestionRepository : IQuestionRepository
{
public Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync() { /* languages to offer in Settings */ }
public Task<LanguagePack> GetLanguagePackAsync(string languageCode) { /* one full pack, or null */ }
public Task<IReadOnlyList<CategoryData>> GetCategoriesAsync(string languageCode) { /* translated categories */ }
// Apply the query's filters (query.Matches(question)), then Shuffle/Seed and Limit.
public Task<IReadOnlyList<QuestionData>> GetQuestionsAsync(QuestionQuery query) { /* ... */ }
}
// In your Awake (order 100): game.Services.Repository = new RemoteQuestionRepository();
Use QuizJson.Deserialize<LanguagePack>(json) to parse data in the kit's format, so your server can serve the same question JSON the Quiz Manager exports. LanguagePackRepository can then serve the downloaded packs: new LanguagePackRepository(config.Categories, packs).
Use the game logic without the UI
The services work on their own if you build a completely different UI:
var services = QuizServices.CreateDefault(config);
await services.Localization.SetLanguageAsync("en");
var session = services.StartNewSession();
session.QuestionChanged += question => Debug.Log(question.Text);
session.Completed += result => Debug.Log("Score: " + result.Score.Total);
await session.StartAsync(new QuestionQuery("en")
{
Difficulty = QuizDifficulty.Easy,
Type = null, // null = every question type
CategoryIds = null, // null = every category
Shuffle = true,
Limit = 10
});
// For each question: submit the selected answer ids, then advance.
var picked = new List<string> { session.Current.Answers[0].Id };
AnswerRecord record = session.Submit(picked, secondsTaken: 4f);
session.Advance(); // or session.Skip() to pass without recording
// Afterwards: services.Profile.Apply(result); services.Achievements.Evaluate(result);
services.Dispose(); // when you are done with it
Tests
The kit includes EditMode tests (content validation, scoring, sessions, hints, achievements, saving, sample content) and a PlayMode test that plays through every screen of the sample scene. Run them from .
The PlayMode flow test plays and buys like a real player, so it changes your editor's local save data (profile, achievements, hints).
Troubleshooting
"You are trying to read Input using the UnityEngine.Input class"
Set Active Input Handling to Input System Package (New) or Both, and make sure your scene's EventSystem uses InputSystemUIInputModule.
"No questions" dialog
No question matches the selected category, type and difficulty. Change the difficulty in Settings, pick another mode, or add questions for that combination in the Quiz Manager.
A language is missing in Settings
The game offers the language assets listed in the Game Config's Languages. Languages created in the Quiz Manager are added automatically; a language asset you made yourself must be added to that list. Use Check in the Languages tab to spot duplicate codes.
A category doesn't show up
Each language offers only the categories ticked for it in the Quiz Manager's Categories tab, and a new global category isn't ticked anywhere yet.
Text is invisible or shows squares
Import the TextMesh Pro essentials (); the sample builder does this automatically. Squares mean the font lacks those characters. See Fonts.
The Store button is missing in a build
Release builds have no store unless Unity IAP 5 is installed. See Selling with Unity IAP.
My prefab changes disappeared
Build Sample Quiz Scene regenerates the kit's prefabs. Keep your changes in copies or prefab variants.
Credits & licenses
- Poppins font, © 2020 The Poppins Project Authors, licensed under the SIL Open Font License 1.1 (
Art/Fonts/Poppins/OFL.txt). - All other art and sounds (icons, UI sprites, sound effects, music) are generated by the kit's own editor tools and are covered by the Asset Store EULA.
Release notes
0.1.0
- First release.
Need help?
Questions, bug reports or feature requests: I usually reply within a day.
Last updated September 28, 2026.