Complete Unity project for Android and iOS. Play the computer at 10 levels, play a friend on the same phone, and solve 2,000 mate puzzles.
Unity 6 (6000.0 LTS)Android & iOS10 AI levels2,000 puzzlesPuzzle EditorAdMob + UMPUnity IAP 55 languages
Introduction
Thank you for purchasing Chess Crown. This guide covers everything from opening the project to publishing your own version of the game. The settings you need are in one place (the Game Config), the screens and popups are regular prefabs, the chess engine is plain C# you can read and change, and the puzzles are a CSV file you can edit with the built-in Puzzle Editor.
Homevs ComputerPuzzlesGame over
Play the computer10 levels from beginner (about 250 Elo) to champion (about 2200), calibrated with engine matches so each level is clearly stronger than the one before. The computer thinks on a background thread, the game never freezes.
2 players, one phonePass and play with an optional chess clock (1 min to 30 min, with or without increment) and a board that turns for the player to move.
2,000 mate puzzlesMate in 1 to mate in 4, ordered by difficulty and unlocked one after the other, with 3 stars per puzzle. Every puzzle was proven by a mate solver: one key move, no faster mate. Any other move that still mates in time is accepted.
Daily puzzleA new puzzle every day with a bigger reward and a streak counter, on a clock that can't be fooled by changing the date.
Puzzle EditorBrowse and edit the puzzles, set up a position and let the solver find the mate, play-test in one click, import thousands of puzzles from the Lichess database (credit Lichess if you ship them), or generate new ones with the engine.
Complete chess rulesCastling, en passant, promotion with a piece picker (or auto-queen), check, checkmate, stalemate, threefold repetition, 50-move rule, insufficient material, resign, draw, flag fall. Move generation is verified with the standard perft tests.
Opening namesAbout 80 opening lines name the opening as it is played (Sicilian Najdorf, Ruy Lopez...) and give the computer varied, sound first moves.
Hints & undoA hint shows the best move with an arrow, undo takes a move back. Bought with coins, earned with a rewarded ad, won from the Lucky Spin or the Star Chest.
RewardsCoins for wins and solved puzzles, a free daily Lucky Spin, a Star Chest filled by stars and wins, stats and a continue button for unfinished games.
AdMobBanner, interstitial, rewarded and app open ads, with Google's UMP consent form (GDPR) and the iOS tracking prompt built in.
In-app purchasesCoin packs, a starter bundle and No Ads through Unity IAP 5 (Google Play Billing 9), with receipt validation, a hook for your own server, restore on iOS and payments that complete later.
Safe progressRewards are saved the moment they are won, the save is signed so coins and purchases can't be edited by hand, and setting the clock back doesn't bring the daily rewards back.
5 languagesEnglish, French, Spanish, Portuguese and German, in one CSV file. More languages are one column away.
A look of its ownGreen felt, polished brass and ivory, polished gold titles, chunky glossy buttons and full colour icons. Brass buttons catch a passing sheen of light, gold dust drifts over the home screen, popups have engraved corner ornaments.
PolishTap or drag to move, legal move dots, last move and check highlights, coordinates, captured pieces, move list, piece sounds, safe area and notch support, Android back button, haptics and music.
Clean projectRuntime and editor code in their own assemblies, every setting in one Game Config, plain prefabs, no paid assets. All art and sound is original.
Included content & third parties
A short list of what the download contains and what it doesn't, so you (and anyone checking the package) can verify it quickly.
Topic
What is in the package
AdMob ids
None. No AdMob App ID, ad unit id or publisher id is in any file. The ad unit fields of the Game Config ship empty: Assets/ChessCrown/Resources/GameConfig.asset is a plain text (YAML) file, and its lines 165 to 175 read admobAndroid: and admobIos:, each with empty banner:, interstitial:, rewarded: and appOpen:, then testDeviceIds: []. The only scene (Scenes/Main.unity) and the prefabs contain no ad ids and don't reference the Game Config; the game loads it from Resources. You enter your own ids (see Setting up AdMob).
Google Mobile Ads plugin
Not included. The download contains no Google file: no DLL, AAR, JAR, native library or framework, and no GoogleMobileAds, ExternalDependencyManager or Plugins folder. AdMobProvider.cs is only compiled after you import Google's plugin yourself.
Unity IAP
Not included. It is a Package Manager dependency ("com.unity.purchasing": "5.4.3" in Packages/manifest.json) that Unity downloads from its registry. No Unity IAP DLL or assembly is in the project: there is no Plugins or Libraries folder anywhere, and Assets holds only ChessCrown, Resources (Unity IAP's one-line BillingMode.json store setting) and TextMesh Pro (its essential resources). See Setting up Unity IAP.
Puzzles
Original, no Lichess content. All 2,000 puzzles in Resources/Puzzles/puzzles.csv (ids cc0001 to cc2000) were made with Chess Crown's own engine: it played games against itself, the puzzle generator cut mate positions out of them and the mate solver proved each one. No row comes from Lichess or any other database, and Documentation/Puzzle origins (all 2000 puzzles).csv traces every puzzle to the generator run and engine game it came from (see How they were made). The CSV only uses the same columns as the Lichess puzzle database so that the optional Import Lichess CSV tool can read Lichess files you download yourself. If you ship puzzles you imported from Lichess, you must credit Lichess as the Lichess database license requires (CC BY 4.0 attribution, see Puzzles & Puzzle Editor).
Fonts and icons
Cinzel and Lato (SIL Open Font License 1.1) and the check and plus icons from Tabler Icons (MIT); their licenses are in ChessCrown/ThirdPartyLicenses. Assets/TextMesh Pro holds TextMesh Pro's essential resources (shaders, settings and its default LiberationSans font), the files Unity adds to every project that uses TextMesh Pro. Everything else (code, engine, art, sounds, puzzles) is original work by the author.
Screens
Every screen and popup of the game, as screenshots taken on an Android phone (Samsung Galaxy A71, 1080 × 2400). The Puzzle Editor of the Unity editor is shown in Puzzles & Puzzle Editor.
HomeNew game: level and colorvs Computer, with a hintOther themes2 players: clock and board2 players with a clockPuzzle mapPuzzlePuzzle solvedDaily puzzleGame overShopLucky SpinStar ChestThemesStatsSettings
Requirements
Unity 6000.0 LTS (made with 6000.0.84f1, newer 6000.0 patches work too).
For Android: the Android Build Support module with its SDK, NDK and OpenJDK (all installed from Unity Hub).
For iOS: the iOS Build Support module, a Mac with Xcode and CocoaPods.
Unity packages come from Unity's Package Manager, not from the download. Unity IAP 5.4.3 (com.unity.purchasing, Unity's free In-App Purchasing package, with Google Play Billing Library 9) and uGUI with TextMesh Pro are listed in Packages/manifest.json, so Unity downloads them by itself the first time you open the project. No package is copied into the download; only TextMesh Pro's essential resources (shaders and settings) sit in Assets/TextMesh Pro, as in every project that uses TextMesh Pro.
Not included: the Google Mobile Ads Unity plugin. Google distributes it, so you import it from Google when you want AdMob ads (free, see Ads). Without it the game runs without ads; the editor and development builds show simulated ads.
Your own accounts and possible costs
AdMob and Unity IAP are third-party services. The project contains the complete integration, but to show real ads, sell in-app purchases and publish the game you have to set up your own accounts, and some of them cost money:
Google AdMob (ads): your own AdMob account. Creating it is free; Google pays your ad earnings under its own terms and payment thresholds.
Google Play (Android release and in-app purchases): a Google Play Console developer account, with a one-time registration fee (US$25 at the time of writing).
App Store (iOS release and in-app purchases): an Apple Developer Program membership (US$99 per year at the time of writing) and a Mac.
Store fees: Google and Apple keep a commission on every in-app purchase, usually between 15% and 30%.
Unity: Unity's own license terms apply; Unity Personal is free within Unity's revenue limits.
These accounts and fees belong to Google, Apple and Unity, not to this project. Check their current terms and prices on their websites before you publish, as they can change. The game itself needs no server and has no running costs: everything (engine, puzzles, saves) runs on the phone.
Getting started
Two packages come from outside the download:
Unity IAP (in-app purchases): Unity's Package Manager installs it by itself when you open the project, and the CC_IAP define switches itself on. See Setting up Unity IAP to check it step by step.
Google's Mobile Ads Unity plugin (AdMob ads and the GDPR consent form): not included, the download has no Google files at all. Import it from Google when you want ads: see Setting up AdMob.
Unzip the download. In Unity Hub choose Add → Add project from disk and select the ChessCrown folder.
Open it with Unity 6000.0. The first import takes a few minutes. If Unity offers to install the Microsoft GDK package (only needed for the Xbox store), choose Don't install.
Open the scene with Tools → Chess Crown → Open Main Scene and press Play.
Switch the platform to Android or iOS in File → Build Profiles.
Open the settings with Tools → Chess Crown → Game Config.
The game runs in the editor just like on a phone. Ads are simulated until you add Google's plugin and your own AdMob ids, and purchases go through Unity's test store, so you can try every feature before setting anything up.
Opens Scenes/Main.unity, the only scene of the game.
Game Config
Selects the Game Config asset so you can edit it in the Inspector.
Documentation
Opens this page.
Cheats
Unlock all puzzles, add 10,000 coins, add 10 hints and 10 undos, fill the Star Chest, reset the daily spin, reset the daily puzzle, or reset all progress. They change the progress saved on your computer, which Play mode uses.
Ads → AdMob Status
Shows whether the Google Mobile Ads plugin is in the project, whether your App IDs are set and how many ad unit ids the Game Config has. AdMob switches itself on when the plugin is imported (see Ads).
Reset Art Import Settings...
Reapplies the import settings the pictures in ChessCrown/Art need (sprite mode, borders, compression).
Project structure
Folder
Contents
ChessCrown/Art
Pieces: one folder per piece set, w_king.png, b_queen.png... Boards: one picture per board. UI: buttons, panels, frames, backgrounds, the logo emblem and the app icon. Icons: the full colour icons, the coin, the star, reward tokens, shop pictures, the home card pictures and the mode and result pictures made of pieces.
ChessCrown/Audio
Sound effects (move, capture, castle, check, promote...) and the music loop.
ChessCrown/Config
Board, piece set and background theme assets.
ChessCrown/Documentation
This page.
ChessCrown/Fonts
Cinzel Bold (titles and the logo), Lato Bold (buttons and numbers) and Lato Regular (text), with their TextMesh Pro font assets and shadow materials.
ChessCrown/Prefabs
The puzzle button, and in UI every screen, every popup and the logo.
ChessCrown/Resources
GameConfig, the puzzles (Puzzles/puzzles.csv) and the texts (Localization/strings.csv).
ChessCrown/Scenes
Main.unity.
ChessCrown/Scripts
Runtime: the game (assembly ChessCrown), with the chess engine in Runtime/Chess. Editor: the Puzzle Editor, the menu, the import rules and the project checks (assembly ChessCrown.Editor).
ChessCrown/ThirdPartyLicenses
Licenses of the fonts and the Tabler icons (check and plus).
ChessCrown/link.xml
Keeps the receipt validation keys in builds that strip unused code (see Receipt validation).
Not in the download: these folders appear when you import Google's Mobile Ads plugin (see Ads).
TextMesh Pro
TextMesh Pro's essential resources (shaders and settings).
Resources/BillingMode.json
Created by Unity IAP, it tells Android builds to use Google Play.
Game Config
All gameplay, economy, ads and shop settings live in ChessCrown/Resources/GameConfig.asset. Select it with Tools → Chess Crown → Game Config; hover a field in the Inspector for a short explanation.
Computer
Field
Meaning
Ai Levels
One entry per level, from the easiest (see Chess engine & levels). Add or remove entries to change the number of levels; level names come from the level_name_N texts.
Ai Min Think Seconds
The computer never answers faster than this, so its moves are easy to follow (0.6).
Engine Memory Mb
Memory for the engine's position table (16 MB).
Hint Think Ms
How long a hint searches for the best move (1200 ms).
Two players
Field
Meaning
Time Controls
The clocks offered in the new game popup: minutes per player and seconds added after each move. 0 minutes means no clock.
Puzzles
Field
Meaning
Puzzle File
The puzzle CSV in a Resources folder, without the extension (Puzzles/puzzles).
Puzzle Coins, Coins Per Star
Coins for solving a puzzle the first time, plus coins per star. A replay only pays for stars the puzzle didn't have yet. Stars: 3 without a mistake, 2 with one mistake, 1 with more mistakes or a hint.
Daily Puzzle Coins
Coins for the daily puzzle, once a day.
Economy
Field
Meaning
Start Coins, Start Boosters
What a new player starts with (coins, hints and undos).
Win Coins Base, Win Coins Per Level
Coins for beating the computer: base + level × per level (30 at level 1, 120 at level 10).
Draw Coins Share
Part of the win coins given for a draw against the computer.
Booster Pack Size, Booster Ad Amount
Hints or undos bought at once with coins, and given for a rewarded ad in the booster popup.
Hint Price, Undo Price
Price of a pack in coins.
Free Coins Amount
Coins for watching a rewarded ad in the shop.
Two player games give no coins, so they can't be used to farm rewards; undo is free there.
Star Chest and Lucky Spin
Field
Meaning
Chest Stars, Chest Rewards
Stars needed to open the chest, and what it gives. Stars come from puzzles, and from computer games: 3 per win, 1 per draw.
Spin Slots
The eight wheel slots: reward, weight (higher = more likely) and color.
Spin Ads Per Day
Extra spins a player can unlock with rewarded ads each day, after the free one.
Ads, purchases, links, themes
Ads and purchases are explained in Ads and In-app purchases, themes in Themes. The Links group holds your privacy policy, your store pages (for the Rate button) and your support e-mail, used by the Settings popup.
Chess engine & levels
The engine is plain C# in Scripts/Runtime/Chess, with no Unity code in it, so it is easy to read, test and reuse:
Class
Role
Board
A position: pieces, side to move, castling, en passant, move generation, make / unmake, FEN, repetition and draw rules. Verified with the standard perft positions.
ChessGame
A game: the moves played with their notation, the result and its reason, undo, the opening name and PGN export.
Search, Evaluation, TranspositionTable
The computer: iterative deepening alpha-beta (PVS) with a transposition table, quiescence search, null move pruning, late move reductions, killer and history move ordering, and a tapered evaluation (material, piece-square tables, pawn structure, mobility, king safety, endgame knowledge).
ChessAi, AiLevel
Plays a level: book moves while in the opening book, then a search. Weak levels score every move with a shallow search and add random noise, which makes them blunder like human beginners; strong levels search deeper for longer.
OpeningBook
About 80 named opening lines, used for the computer's first moves and to show the opening name.
MateSolver
An exact mate-in-N prover, used to check puzzles and to answer alternative solutions.
Notation, Puzzle, PuzzleGenerator
SAN / UCI notation, the puzzle format, and the puzzle generator of the Puzzle Editor.
Computer levels
Each entry of Ai Levels has these fields:
Field
Meaning
Rating
The approximate strength shown to the player (a guide, not an official rating).
Noise Cp, Multi Depth
When Noise Cp is above 0, every legal move is scored with a search of Multi Depth plies, then random noise of about that many centipawns is added and the best noisy score is played. More noise = more human mistakes. A mate is never missed because of noise.
Max Depth, Time Ms
Without noise, a full search to Max Depth plies (0 = no limit) or until Time Ms runs out.
Book Plies
The computer plays from the opening book for this many half moves.
The default levels were tuned with hundreds of engine-against-engine games so each level wins most games against the one below it: 1-2 play random-ish beginner moves, 3-6 hang fewer and fewer pieces, 7-8 rarely blunder, 9 and 10 search fully (level 10 thinks up to 2.5 seconds). The computer runs on a background thread (AiRunner), so the game keeps animating while it thinks.
To make the strongest level stronger, raise its Time Ms. To add an easier level, insert an entry with more noise (for example Noise Cp 300, Multi Depth 1) and add its level_name_N text.
Opening book
The lines are in OpeningBook.Lines: a name, then the moves in standard notation. Add your own lines there; positions reached by another move order are found too. Names with a colon (Sicilian Defense: Najdorf) share the family name until the variation is clear.
Puzzles & Puzzle Editor
The puzzles are in ChessCrown/Resources/Puzzles/puzzles.csv, played in file order and unlocked one after the other. The included 2,000 puzzles are original: they come from games played by the engine, and each one was proven by the mate solver (one winning first move, no faster mate). They go from mate in 1 (rated about 600) to mate in 4 (about 2000).
Where the included puzzles come from. All 2,000 puzzles were made with Chess Crown's own puzzle generator (Scripts/Runtime/Chess/PuzzleGenerator.cs, the same code as Generate in the Puzzle Editor). None of them comes from Lichess or from any other database or website, and the file is not a mix. How they were made:
Engine games. In each game Chess Crown's engine played itself: a strong side (search depth 5 or 6) against a weaker, mistake-prone side (one of the beginner to intermediate levels). 16 generator runs (seeds 1001 to 1016) played 700 games each, 11,200 games in total.
Mate positions. Whenever the strong side found a forced mate in 1 to 4 moves (after at least 12 plies, with no position used twice), that position became a candidate.
Proof. The mate solver (MateSolver.cs) proved every candidate: exactly one winning first move and no faster mate. 5,921 candidates passed.
Selection. 2,000 of them were picked for a smooth difficulty curve (500 mates in 1, 800 in 2, 550 in 3, 150 in 4), rated, sorted by rating and renumbered cc0001 to cc2000.
The download includes Documentation/Puzzle origins (all 2000 puzzles).csv, which traces every puzzle to the generator run, seed and engine game it came from. The Lichess import below is an optional tool for your own game: the CSV only uses the same column layout as the Lichess puzzle database, so files from both work in the Puzzle Editor.
Moves (UCI, space separated) starts with that opponent move, which the game plays and highlights, then the solution: player, opponent, player...
Themes: mateInN marks a mate puzzle, and any other move that still mates in time is accepted. Without it, only the moves of the file are accepted (the last move may be any checkmate). playerFirst means there is no opponent move: the player moves at once (puzzles set up by hand in the editor).
Puzzle Editor
Open Tools → Chess Crown → Puzzle Editor. The list on the left shows every puzzle in game order: search it, move puzzles up and down, sort by rating, delete, and Save. Select a puzzle to see it on the board and step through the solution with the arrows.
Check proves a mate puzzle: it reports a faster mate, no mate, or more than one winning first move.
Play Test plays the selected puzzle in the Main scene without saving anything.
New opens the set-up board: pick a piece and click squares (click again to remove), choose the side to move, then Find Mate & Add. The solver finds the shortest mate (up to 5 moves) and writes the solution for you. Add as tactic adds the position without a solution: click the moves on the board to record them.
Import Lichess CSV... reads lichess_db_puzzle.csv (download it from database.lichess.org and unpack it). Choose the themes (for example mateIn2, fork, endgame), a rating range and a maximum count. Invalid lines are skipped.
Generate plays engine games and adds original mate puzzles (about one per game, a second or so each).
Attribution required for imported Lichess puzzles. Puzzles you import come from the Lichess puzzle database and stay under the Lichess database license (see database.lichess.org). If your game ships any imported puzzle, you must comply with its attribution requirements (CC BY 4.0): credit Lichess in your game, for example on a credits or about screen and in your store listing: "Puzzles from the Lichess puzzle database (lichess.org)". Check the license on that page before you publish. The 2,000 puzzles that come with Chess Crown are not from Lichess and need no attribution.
Sort by rating after an import so the difficulty keeps rising.
Daily puzzle
The daily puzzle is picked from the middle of the list by the date, the same for everyone on a given day, and pays Daily Puzzle Coins once per day. It follows GameClock, so changing the phone's date doesn't give extra rewards.
Themes
Boards
A board theme (ChessCrown/Config/Board_*.asset) has a name key, a price, the board picture (a1, bottom left, is a dark square), the light and dark square colors (used for the coordinates) and the colors of the last move, selection and legal move dots. Eight are included. To add one, duplicate an asset, assign your picture and add it to Board Themes in the Game Config.
Piece sets
A piece set (Pieces_*.asset) has a name key, a price and twelve sprites: pawn, knight, bishop, rook, queen and king, for white and for black. Six are included: classic, wood, marble, gold & onyx, crystal and candy. Pieces are square pictures with the piece standing on the bottom of the picture and some room around it.
Backgrounds
Background themes (Background_*.asset) have a name key, a price, the background sprite and the color of the faint diamond pattern laid over it (set its alpha to 0 to hide the pattern). Six are included: green felt, walnut, navy leather, burgundy leather, slate and black marble. Add more to Backgrounds in the Game Config.
The Themes popup has a tab for each kind and scrolls, so any number of themes fits.
Reskinning
Pictures: replace any PNG in ChessCrown/Art with your own file of the same name. Buttons, panels and frames are 9-sliced, keep the borders when you draw your own. Tools → Chess Crown → Reset Art Import Settings... reapplies the import settings if you change them by mistake.
Colors: the brass buttons use btn_brass.png; the dark buttons, cards and round buttons use white pictures (btn_face, card, round_face) tinted by the Image color, with a brass outline on top. Change the colors on the prefabs, or redraw the pictures.
Effects: the light sweeping over the brass buttons is the Sheen component (child "Sheen" of each brass button face: change its interval, or delete the child to switch it off). The drifting gold dust is AmbientMotes on the home and loading screens (count, size, speed and color in the Inspector).
Icons: the icons are full colour pictures (icon_*_gold.png, booster_*_gold.png and token_*.png in Art/Icons); replace any of them with your own picture of the same name. icon_check and icon_plus are white on transparent and tinted in the scene. The coin, the star, the coin packs of the shop and the home card pictures are full colour too.
Screens and popups: open the prefabs in ChessCrown/Prefabs/UI. Everything is plain uGUI and TextMesh Pro. The game screen places the board, the player panels and the move list itself to fit any screen.
Logo: edit Prefabs/UI/Logo.prefab (the brass emblem, the gold king and the word mark), used by the loading screen and the home screen. Art/UI/logo.png is a picture of the same logo for the Unity splash screen, which is off by default; replace it too if you turn the splash on.
Fonts: assign another TextMesh Pro font asset to the texts, or replace the TTF files in ChessCrown/Fonts.
Sounds: replace the WAV files in ChessCrown/Audio, keeping the names, or assign new clips on the Audio object of the Main scene.
App icon and name:Edit → Project Settings → Player. The icon files are app_icon*.png in Art/UI: the full icon, the round one for older Android versions, and the background and foreground layers of the Android adaptive icon.
Localization
The game comes in English, French, Spanish, Portuguese (Brazil) and German. On first launch it follows the phone's language (English for any other), and the language button in Settings cycles through all of them.
All texts are in ChessCrown/Resources/Localization/strings.csv: one row per text, the key first, then one column per language. Lines starting with # are section titles and are ignored.
key,en,fr,es,pt,de
# General
language_name,English,Français,Español,Português,Deutsch
reason_checkmate,Checkmate,Échec et mat,Jaque mate,Xeque-mate,Schachmatt
Edit the file in any spreadsheet program and save it as CSV (UTF-8).
To add a language, add a column with its code (for example it) and fill in language_name for it. Then add the matching case in FromSystemLanguage in Loc.cs so the game picks it from the phone's language. The language button in Settings cycles through every column.
The fonts cover Latin alphabets with accents (ñ, ã, ç, ß...). For Cyrillic, Greek or Asian languages, add a fallback font to the TextMesh Pro font assets.
Right-to-left languages (Arabic, Hebrew, Persian, Urdu) are not supported out of the box. TextMesh Pro doesn't join Arabic letters or reverse right-to-left text by itself, so adding such a column shows the letters unconnected and in the wrong order. To add one, use a shaping solution such as the free RTLTMPro package (it replaces the TextMesh Pro text components) together with a font that has the Arabic or Hebrew letters, and check the layouts of the popups, which are made for left-to-right text.
Chess notation (Nf3, O-O) and the opening names stay in English, as in most chess apps.
In the scene, texts use the Localized Text component with a key. In code, use Loc.Get("key") or Loc.Format("key", value). Numbers go through Loc.Number, which formats them the way each language expects.
Ads (AdMob)
The AdMob integration (banner, interstitial, rewarded and app open ads, and Google's UMP consent) is in Scripts/Runtime/Services/Ads/AdMobProvider.cs. Two things are not included:
Google's Mobile Ads Unity plugin, with Google's UMP consent SDK. Google distributes it, so you import it from Google: the download contains none of its files (no DLLs or native libraries), and AdMobProvider.cs is only compiled once the plugin is in your project.
AdMob ids. Chess Crown comes with no AdMob ids at all: the ad unit ids in the Game Config are empty and there is no App ID. Fill in your own ids before you build.
Your own AdMob account is required. AdMob is a Google service: to show real ads and get paid you need to create your own AdMob account (free) and add your apps to it. Google's terms and payment thresholds apply. See Your own accounts and possible costs.
Setting up AdMob
Download the latest GoogleMobileAds-v11.x.x.unitypackage from Google's releases page (Chess Crown is tested with 11.5.0). Google's Unity quick start also explains how to add it with the Package Manager.
Import it with Assets → Import Package → Custom Package.... Chess Crown notices the plugin and switches its AdMob code on (the CC_ADMOB define).
For Android, run Assets → External Dependency Manager → Android Resolver → Force Resolve (the External Dependency Manager comes with Google's plugin) and enable the Gradle templates it asks for.
In AdMob, add your app (Android and iOS are separate apps) and create one ad unit per format: banner, interstitial, rewarded and app open.
Put your App IDs in Assets → Google Mobile Ads → Settings. Google's plugin stops a build that has no App ID.
Paste your ad unit ids into Admob Android and Admob Ios in the Game Config. A format you leave empty is simply not shown.
Tools → Chess Crown → Ads → AdMob Status shows whether the plugin is in, whether your App IDs are set and how many ad unit ids the Game Config has. Until there is at least one ad unit id (or without the plugin), the editor and development builds show simulated ads, so you can test every ad flow, and release builds show none. A warning in the Console reminds you when you make a release build without your ids.
Testing ads
Never click your own live ads: Google can limit or close an account for invalid traffic. While you develop, use test ads, as Google explains in its test ads guide:
Test devices (recommended): run your build on your phone once and look in the log (Android: adb logcat, iOS: the Xcode console) for the line that mentions setTestDeviceIds with your device id. Add that id to Test Device Ids in the Game Config: your phone then gets test ads from your own ad units, everyone else gets real ads. Android emulators and the iOS simulator always get test ads.
Google's sample ad units: the same guide lists sample ad unit ids that always show test ads. If you paste them into the Game Config to try something, put your own back before you publish, because a build with Google's sample ids earns nothing.
Consent (GDPR)
The game uses Google's User Messaging Platform. Create a consent message in AdMob under Privacy & messaging and the form shows automatically to users in regions that need it. Ads are only requested once consent allows it, and a Privacy button appears in Settings when the user must be able to change their choice. If the consent request fails (no internet), it is tried again when the app comes back to the foreground.
When ads show
Format
Behavior (Game Config)
Banner
At the bottom of every screen when Use Banner is on. The layout moves up to make room, and the board shrinks a little to fit.
Interstitial
When the player leaves a finished game or puzzle (rematch, next puzzle, home), after Interstitial After Games finished games, every Interstitial Every games, and never within Interstitial Cooldown seconds of another full screen ad. Never in the middle of a game.
Rewarded
Double reward after a win or a solved puzzle, free coins in the shop, hints and undos in the booster popup, extra Lucky Spins. These buttons only become available once an ad has loaded.
App open
When the player comes back after at least App Open After Seconds away, if Use App Open is on. Skipped right after another full screen ad and while a purchase is in progress.
The No Ads purchase removes banners, interstitials and app open ads. Rewarded ads stay available because the player chooses to watch them. To turn ads off completely, untick Enable Ads in the Game Config.
Turning ads off
Untick Enable Ads in the Game Config to run without ads while keeping the plugin. To remove AdMob completely, delete the folders Google's plugin added (GoogleMobileAds, ExternalDependencyManager and its files in Plugins): Chess Crown switches its AdMob code off by itself and compiles without any Google code.
In-app purchases
Your own store accounts are required, and the stores charge fees. Unity IAP sells through Google Play and the App Store, so you need your own Google Play Console account (one-time US$25 registration) and Apple Developer Program membership (US$99 per year), prices at the time of writing. Both stores keep a commission on every purchase, usually 15% to 30%. See Your own accounts and possible costs.
Purchases use Unity IAP 5 (package com.unity.purchasing 5.4.3), which uses Google Play Billing Library 9 on Android and StoreKit 2 on iOS. Unity IAP is not included in the download: it is Unity's own package, listed in Packages/manifest.json, and Unity's Package Manager installs it when you open the project (you see it in Window → Package Manager → In-App Purchasing). If it is missing, Chess Crown says so in the Console and the shop can't sell anything until you install a 5.x version there. IAPManager is written for the 5.x API: the CC_IAP define in ChessCrown.asmdef turns the store code on for any 5.x version.
Setting up Unity IAP
Install the package. Opening the project is enough: Packages/manifest.json lists "com.unity.purchasing": "5.4.3", so Unity downloads it from its registry during the first import (this needs an internet connection). To check, open Window → Package Manager, choose In Project and look for In-App Purchasing 5.4.3. If it isn't there (for example after you removed it), choose Unity Registry, select In-App Purchasing, pick a 5.x version and click Install.
The CC_IAP define switches itself on. You don't add it anywhere: Assets/ChessCrown/Scripts/Runtime/ChessCrown.asmdef has a Version Define that sets CC_IAP whenever Unity IAP 5.x is installed (select the asmdef and look at Version Defines in the Inspector). Without Unity IAP 5.x the store code is left out, the game still runs, and a warning in the Console says what to install. Don't add CC_IAP to the Player settings by hand: without the package it would only cause compile errors.
Check that it works. Press Play, open the shop and tap a price: Unity IAP's Fake Store window opens (see Testing in the editor).
Add your products. Put your product ids in the Game Config (below) and create the same products in Google Play Console and App Store Connect.
Unity IAP version. Keep Unity IAP on a 5.x version (5.4.3 or newer). If another version is installed, the store code is switched off and Chess Crown tells you right away: a dialog and a warning in the Console when the project opens, a warning when you build, and a message in the log when the game starts. Update or downgrade in Window → Package Manager → In-App Purchasing.
The shop sells the Products listed in the Game Config:
Field
Meaning
Product Id
Must match the id you create in Google Play Console and App Store Connect.
Kind
Coins (consumable), NoAds (non-consumable) or Bundle (coins + hints and undos; non-consumable when it removes ads).
Coins, Boosters, Removes Ads
What the purchase gives. Boosters is the number of hints and of undos.
Title Key, Icon, Best Value
How it looks in the shop.
Fallback Price
Shown until the store returns the real, localized price.
Change the ids from com.yourcompany.chesscrown.* to your own.
Create the same products in Google Play Console (Monetize → Products → In-app products) and App Store Connect. Google only returns products once a build is uploaded to a testing track.
Add your Google account as a license tester to buy without being charged.
One-time products (No Ads, the starter bundle) are delivered once and disappear from the shop after purchase. On a new phone or after a reinstall they come back by themselves when the store connects (without their coins, which were already given). Payments the store confirms later, such as cash payments on Google Play or Ask to Buy on iOS, show a "Purchase pending" message and are delivered when they go through, even in a later session. On iOS, Settings and the shop have a Restore button, as Apple requires (it also shows in the editor so you can test it).
Each purchase is delivered, saved, and only then confirmed to the store. The ids of delivered transactions are kept in the save, so if the app closes between the delivery and the confirmation, the store sends the purchase again at the next launch and it is only confirmed, never delivered twice.
Testing in the editor
In Play mode Unity IAP uses its fake store. Tapping a price opens a small Fake Store window: Buy completes the purchase, Cancel cancels it like a player closing the store sheet.
Test Purchases (Game Config): in the editor and in development builds, purchases are simulated while the store has no products yet, so you can test the whole flow on your phone. Release builds always use the real store and show "Store not available right now" until your products are live.
Receipt validation
Every purchase is checked before it is delivered. A purchase that fails the check gets no coins and is not confirmed, so the store refunds it automatically (Google Play after three days).
On the device (Google Play). Unity IAP's CrossPlatformValidator verifies the signature of each Google Play receipt with your app's license key, and IAPManager also checks that the receipt is for the product that was bought. Set it up once:
In Google Play Console open your app, then Monetize with Play → Monetization setup, and copy the Licensing key (Base64-encoded RSA public key).
In Unity choose Services → In-App Purchasing → Receipt Validation Obfuscator..., paste the key and press Obfuscate Google Play License Key.
Unity writes GooglePlayTangle.cs and AppleTangle.cs to Assets/Scripts/UnityPurchasing/generated. There is nothing else to do: IAPManager finds them by name, and ChessCrown/link.xml keeps them in stripped builds.
Until the key is set, Android builds log "Google Play receipts are not validated yet" and purchases are delivered without the check.
On the device (App Store). StoreKit 2 verifies every transaction itself on iOS 15 and newer. On iOS 13 and 14 (StoreKit 1) the App Store receipt is checked with AppleTangle from the same obfuscator.
On your own server (optional). A check on the device can be bypassed on a rooted or jailbroken phone. For the strongest protection, set IAPManager.ServerValidation: the game then waits for your server's answer before it delivers a purchase.
using System;
using UnityEngine;
using UnityEngine.Networking;
using ChessCrown;
public class MyReceiptCheck : MonoBehaviour
{
[SerializeField] string url = "https://example.com/verify-purchase";
void Awake() => IAPManager.ServerValidation = Check;
// your server answers {"valid": true} or {"valid": false}
[Serializable] class Answer { public bool valid; }
void Check(PurchaseReceipt purchase, Action<bool> done)
{
var request = UnityWebRequest.Post(url, JsonUtility.ToJson(purchase), "application/json");
request.timeout = 15;
request.SendWebRequest().completed += _ =>
{
bool valid = false;
if (request.result == UnityWebRequest.Result.Success)
{
try { valid = JsonUtility.FromJson<Answer>(request.downloadHandler.text)?.valid == true; }
catch (ArgumentException) { } // not JSON: treat as not valid
}
request.Dispose();
done(valid);
};
}
}
Add the script to any object of the Main scene. PurchaseReceipt carries the product id, the transaction id, the store name, Unity IAP's receipt, the Google Play purchase token and the App Store signed transaction. Your server checks them with the store:
Google Play: call the Google Play Developer API purchases.products.get with your package name, the product id and googlePurchaseToken (it needs a Google Cloud service account linked to your Play Console). The purchase is valid when purchaseState is 0.
App Store: verify the appleSignedTransaction JWS with Apple's certificate chain (Apple's App Store Server Library does it), or ask the App Store Server API for the transaction with transactionId.
Call done exactly once, on the main thread (UnityWebRequest callbacks are). When your server can't be reached, answer false: the purchase stays unconfirmed, comes back at the next launch and is checked again.
Save data & cheating
Protected save
Progress, stats, the unfinished game, coins, hints, undos and purchases are saved in PlayerPrefs (key chesscrown_save) as JSON that is signed with HMAC-SHA256 and lightly scrambled, so the values can't be read or changed with a PlayerPrefs or XML editor. When a save has been edited or damaged, the signature doesn't match: the game starts a new save and keeps the rejected one under chesscrown_save_broken, in case a player writes to support.
Set your own secret before your first release. The signature uses SaveManager.Secret in Scripts/Runtime/Core/SaveManager.cs. Replace it with your own random text (for example a new GUID) so your saves can't be forged with the secret everyone who bought the project has. A warning appears when you build while it is still the original one. Never change it after release: saves signed with another secret are treated as edited and start over.
This stops casual cheating, which is what a game that keeps its data on the phone can do: the secret is inside the app, so a determined player with a decompiler could still rebuild a save. If your economy needs more than that, keep the wallet on a server.
Daily rewards and the device clock
The Lucky Spin and the daily puzzle follow GameClock, not the phone's clock directly. It remembers the latest time it has seen and never goes back from it:
Clock set back (the classic trick to get the daily rewards again): detected as soon as the game reads the time. The free spin doesn't come back, the log says how far the clock went back, and the Lucky Spin shows "Clock set back: free spin comes later".
Clock set forward: the player gets the next days' rewards early, but then waits until the real date catches up, so there is nothing to gain over time.
Time zones: a reward is given only on a later calendar day than the last one, so flying across time zones (or faking it) doesn't give an extra one.
Limits: the game doesn't check the time online. A player who moves the clock far into the future takes a few rewards early and then waits until that date for the next one, and deleting the app's data resets everything, like any game saved on the phone. If your game has a server, give daily rewards from the server's time instead.
Building
Android
In Edit → Project Settings → Player set your company name, product name, Package Name and version.
Create a keystore under Publishing Settings.
If Gradle complains about missing dependencies, run Assets → External Dependency Manager → Android Resolver → Force Resolve.
Tick Build App Bundle (Google Play) in the build profile and build.
The project targets Android 7.0 (API 24) and newer, ARM64 and ARMv7 with IL2CPP, and uses ASTC texture compression. The engine benefits from IL2CPP: it searches much faster than in the editor.
iOS
Set the Bundle Identifier and signing team in the Player settings. The minimum iOS version is 13.
Build, then open the generated .xcworkspace (not the .xcodeproj). CocoaPods installs the Google Mobile Ads SDK during the build.
Set up the tracking prompt as explained below.
App Tracking Transparency (iOS)
Since iOS 14.5, an app must ask permission before it uses the advertising identifier (IDFA) for personalized ads. The game doesn't show this prompt from its own code: Google's UMP SDK shows it, as part of the consent flow that runs at launch (ConsentForm.LoadAndShowConsentFormIfRequired in AdMobProvider). This is how it works:
The game starts and asks UMP for the consent status.
If you published an IDFA explainer message in AdMob and the player hasn't answered the tracking question yet, UMP shows your explainer screen first (and the GDPR form before it, in the regions that need it).
When the player continues, UMP asks iOS for permission and the system prompt "Allow ... to track your activity across other companies' apps and websites?" appears, with the text you entered as User Tracking Usage Description.
Ads start once consent allows it. With Allow, AdMob can show personalized ads; with Ask App Not to Track, ads still show, without the IDFA.
Without an IDFA explainer message, iOS never shows the prompt and AdMob serves ads without the IDFA. Set it up like this:
In Assets → Google Mobile Ads → Settings, fill in User Tracking Usage Description (it becomes NSUserTrackingUsageDescription in Info.plist). Write it yourself, it is what the player reads.
In AdMob open Privacy & messaging, create an IDFA explainer message (shown as "IDFA message" / "iOS ATT" depending on the AdMob version), choose your iOS app, and publish it. Publish your GDPR message there too.
Check it before you submit to the App Store:
Install the build on a real iPhone (iOS 14.5 or newer) from Xcode or TestFlight.
In Settings → Privacy & Security → Tracking, make sure Allow Apps to Request to Track is on. When it is off, iOS answers "no" for every app and never shows the prompt.
Launch the game: the explainer appears, then the system prompt with your text. iOS asks only once per install, so delete the app and install it again to see it another time.
In the Xcode console, check that no error mentions NSUserTrackingUsageDescription, and that ads load after you answer.
To test the GDPR form outside Europe, add debug settings to the request in AdMobProvider.RequestConsent, then remove them before release:
var request = new ConsentRequestParameters
{
ConsentDebugSettings = new ConsentDebugSettings
{
DebugGeography = DebugGeography.EEA,
TestDeviceHashedIds = new List<string> { "YOUR-HASHED-DEVICE-ID" } // printed in the Xcode console
}
};
ConsentInformation.Update(request, ...);
In App Store Connect, answer the App Privacy questions to match: with AdMob, "Device ID" and "Advertising Data" are used for third-party advertising, and tracking is declared when you show the prompt. Apple checks that the prompt appears in the build you submit.
Publishing checklist
Your own AdMob, Google Play Console and Apple Developer accounts (see possible costs).
Your own package name / bundle identifier, product name, icon and version.
Your own AdMob App IDs (Google's settings) and ad unit ids (Game Config): Chess Crown comes without any. No Google sample ad units left in the Game Config.
A consent message published in AdMob (Privacy & messaging).
iOS: a User Tracking Usage Description, an IDFA explainer message published in AdMob, and the tracking prompt checked on an iPhone (see App Tracking Transparency).
Your product ids in the Game Config and the same products created in the stores.
Unity IAP on a 5.x version (no version warning in the Console).
Your Google Play license key in the Receipt Validation Obfuscator (see Receipt validation).
Your privacy policy, store links and support e-mail in the Game Config.
The Google Mobile Ads plugin imported from Google, if your game shows ads.
A release keystore (Android) and signing team (iOS).
Tested a release build on a real phone.
Code overview
The code lives in the ChessCrown namespace (the engine in ChessCrown.Chess, see Chess engine). The main game pieces:
Class
Role
GameController
Entry point on the Game object: starts services, starts games and puzzles, switches themes.
UIManager
Shows screens (loading, home, puzzles, game) and keeps track of open popups and the back button.
UIScreen, UIPopup
Base classes of every screen and popup, with their show and hide animations.
GameScreen
Plays one game or puzzle: turns, the computer, clocks, hints, undo, puzzle checking, the end of the game and its rewards, saving the unfinished game.
BoardView
Draws the board and the pieces, animates moves, shows highlights, legal moves and hint arrows, and turns taps and drags into moves.
PlayerPanel, MoveListView
The player strips (name, captured pieces, material, clock) and the move list with the opening name.
AiRunner, ChessClock, PuzzleRepository
The engine on a background thread, the chess clock, and the puzzle file.
SaveManager, PlayerData, Wallet
Progress saved as signed JSON in PlayerPrefs; coins, hints, undos and pending rewards with change events.
GameClock
The time daily rewards follow; it never goes back, see Save data.
AdsManager, IAPManager
One simple API for ads and purchases, whatever the provider. IAPManager also validates receipts and exposes ServerValidation.
AudioManager, Haptics, Loc
Sounds and music, vibration, texts.
Tween
A small tweening helper used by every animation, no extra package needed.
How rewards are handed out
Winning a game, solving a puzzle, opening the Star Chest or landing on a Lucky Spin prize saves the reward as pending right away, together with the progress. The popup then shows it and Wallet.ClaimPending() adds it to the wallet when the player collects it. If the app is closed in between, the reward popup comes back on the next launch.
Adding a popup
Create a class that inherits from UIPopup and override OnOpen.
Duplicate a popup prefab from Prefabs/UI, swap the component, place it under Canvas/Popups in the Main scene.
Add it to the Popups list of the UIManager on the Canvas, then open it from code with UIManager.Instance.Get<MyPopup>().Open().
Troubleshooting
No ads show on my phone
Check that the Google Mobile Ads plugin is imported and that your ad unit ids are in the Game Config (Tools → Chess Crown → Ads → AdMob Status shows both), that the phone has internet, that Enable Ads is on and that you haven't bought No Ads in that install. Live ad units can take hours to start serving after you create them; add your phone as a test device to check them right away (see Testing ads). In the EU the consent form must be answered first.
"Store not available right now"
The store doesn't sell your products yet: they aren't created, not active, or the build isn't uploaded to a testing track. Use a development build with Test Purchases on to test the flow meanwhile.
The computer is too slow or too fast in the editor
The engine runs several times faster in an IL2CPP build on a phone than in the editor, so judge the levels on a device. Search time is limited by Time Ms of each level, never by the device.
A puzzle doesn't accept my move
In a mate puzzle, every move that still forces mate in the remaining moves is accepted. In other puzzles only the moves of the file count. Open the puzzle in the Puzzle Editor and press Check.
Pink or missing images in a build
Edit → Project Settings → Graphics must list UI/Default in Always Included Shaders. It is set in this project; keep it if you change graphics settings.
Gradle or dependency errors on Android
With Google's Mobile Ads plugin imported, run Assets → External Dependency Manager → Android Resolver → Force Resolve, and make sure the Gradle templates it needs are enabled in the Player settings (Publishing Settings).
A dialog says the Unity IAP version is not supported
Another major version of Unity IAP is installed, so purchases are switched off. Install a 5.x version (5.4.3 or newer) in Window → Package Manager → In-App Purchasing; the message goes away after the next compile.
"Invalid receipt" in the log and the purchase isn't delivered
The license key in the Receipt Validation Obfuscator doesn't belong to this app, or the build's package name differs from the one in Google Play Console. Copy the key again from Monetization setup and obfuscate it again.
My progress was reset
The save was edited outside the game, or SaveManager.Secret changed since it was written. The old save is kept under the PlayerPrefs key chesscrown_save_broken. While developing, use the Cheats menu instead of editing PlayerPrefs.
My saved progress in the editor gets in the way
Use Tools → Chess Crown → Cheats → Reset All Progress.
Updating to a new version
New versions of Chess Crown are listed in the Changelog. Your game is already changed (your ids, your art, maybe your own code), so don't import a new version over your project blindly:
Back up your project first, or commit it to version control, so you can compare and go back.
Unzip the new version into a separate folder and open it once with Unity to see what changed (the changelog lists the files).
Copy over only the scripts and files the changelog names, then check your changes to them again.
Keep yours
Why
Resources/GameConfig.asset
Your AdMob ids, product ids, prices, links and economy. Compare it with the new one in the Inspector and add only the new fields.
Resources/Puzzles/puzzles.csv and Localization/strings.csv
Your puzzles and texts. Add the new text keys of the update to your file instead of replacing it.
Art, Audio, Fonts, Config, the prefabs and Main.unity
Your reskin. Take new prefabs or scene objects from the update only when the changelog says a feature needs them.
Project Settings (Player)
Your package name, bundle identifier, version, icons and signing.
Never change SaveManager.Secret in a game that is already published. Keep your own value when you copy a new SaveManager.cs: with another secret every player's save looks edited and their progress, coins and purchases start over (see Save data).
Usually safe to overwrite with the new version: the scripts in Scripts/Runtime/Chess (the engine) and Scripts/Editor (Puzzle Editor, menu, checks), as long as you didn't change them. After updating, run the game in the editor, play a game and a puzzle, test a purchase with the fake store, and make a test build before you publish.
Credits & licenses
The game, its code and chess engine, the pieces, boards, user interface art, the logo, the sounds and the 2,000 puzzles are original work created by the author. Some of it is shared with the author's earlier item Tile Crown: a few generic white UI shapes drawn by the same code (ui_circle, ui_rounded, ui_shadow, ui_glow, ui_rays, ui_triangle, fx_spark, fx_confetti and bar_fill), and the structure of the ads, purchase, save and daily reward code. The design, icons, logo, sounds and screens of Chess Crown are its own. The following assets are included; their licenses are in ChessCrown/ThirdPartyLicenses (or next to the asset) and allow commercial use:
Asset
License
Tabler Icons (the check and plus icons)
MIT
Cinzel font
SIL Open Font License 1.1
Lato font
SIL Open Font License 1.1
TextMesh Pro essential resources, including the Liberation Sans font
Unity Companion License; Liberation Sans: SIL Open Font License 1.1 (in TextMesh Pro/Fonts)
Unity IAP
Unity's package terms (installed from the Package Manager)
The 2,000 included puzzles are original, made with Chess Crown's own engine and solver; no Lichess data is included. Puzzles you import yourself from the Lichess puzzle database stay under the Lichess database license: if you ship them, you must credit Lichess as its attribution requirements (CC BY 4.0) ask, for example "Puzzles from the Lichess puzzle database (lichess.org)" (see Puzzles). Thanks to Lichess for making its database available. The Google Mobile Ads Unity plugin is not part of the download; when you import it from Google, Google's terms apply to it.
Changelog & support
1.0.0
First release.
Questions or problems? Contact us through the comments on the item page or the support form on our profile. Please include your Unity version and the platform you build for.