Link Crown

Link Crown – Color Connect Puzzle

Complete Unity project for Android and iOS. Draw pipes to connect the dots of the same colour, fill the whole board, and earn three crowns' worth of stars on every level.

Unity 6 (6000.0 LTS)Android & iOS450 levels + daily puzzleEndless mode (on-device generator)Level EditorAdMob-ready (Google test ids)Unity IAP 59 languages

Introduction

Thank you for purchasing Link Crown. This guide covers everything from opening the project to publishing your own version of the game. Every setting lives in one place (the Game Config), every screen and popup is a regular prefab, and every level is plain data you can edit in the built-in Level Editor.

Home
Home
Gameplay
Gameplay
Level packs
Level packs
Level complete
Level complete
Daily puzzle
Daily puzzle
Themes
Themes
Lucky Spin
Lucky Spin
Shop
Shop
Settings
Settings
The Level Editor in the Unity editor
The Level Editor, inside the Unity editor (see Levels & Level Editor)
450 checked levels9 packs: 8 of square boards from 4×4 to 12×12 and one of shaped boards (heart, crown, ring…). Every level is proven to have exactly one solution and each pack goes from easy to hard.
Daily puzzleA new puzzle every day, the same for every player, with a streak that raises the reward. Safe from clock tricks.
Endless modePick a board size from 5×5 to 12×12 and get a brand-new puzzle generated on the phone, always with exactly one solution.
Level EditorPaint dots and walls, check that a level has a single solution, solve it, generate new levels, rate the difficulty and sort a pack from easy to hard.
Smooth drawingGlossy pipes with rounded corners, a marker under the finger, pipes that cut and come back as you draw, undo, restart, a sound that climbs as the pipe grows.
Stars & hints3 stars for a perfect solve (one move per colour, no hint). Hints draw one pipe of the solution; get more with coins, a rewarded ad or in-app purchases.
Themes & accessibility5 dot palettes and 6 boards bought with coins, and optional colour-blind symbols on every dot.
RewardsCoins for every new star, a free daily Lucky Spin (coins and hints) plus extra spins for rewarded ads, free coins in the shop, packs you can open early with coins.
AdMob-readyBanner, interstitial and rewarded ads with Google's UMP consent form and the iOS tracking prompt. Ships with Google's official test ids only; import Google's plugin and test ads show right away, then put in your own ids.
In-app purchasesCoin packs, hint packs, No Ads and a starter bundle through Unity IAP 5 (Google Play Billing 9, StoreKit 2), with receipt validation and a hook for your own server.
Safe progressSigned save (HMAC-SHA256), purchases never delivered twice, rewards saved the moment they are won, levels in progress kept when the app closes.
9 languagesEnglish, French, Spanish, Portuguese, German, Italian, Indonesian, Swedish and Dutch, in one CSV file.

How the game plays

The rules

  1. Drag from a dot to draw a pipe to the other dot of the same colour.
  2. Pipes can't cross. Drawing over a pipe cuts it; move back and the cut pipe comes back.
  3. Connect every colour and fill every cell of the board to solve the level.

Touching a dot starts its pipe again from that dot; touching a pipe continues it from there. The counters above the board show the connected colours, the moves and how much of the board is filled. A move is counted each time the player changes the board with a different colour than the last move, so a perfect game uses one move per colour (tapping a dot without drawing is not a move).

Undo takes back the last change. Restart (toolbar or Pause menu) clears every pipe and the move counter, so a perfect game is still possible, and can itself be undone; hints used stay counted until the level is solved. Replay, after a level is solved, starts a fresh try.

Stars

StarsWhen
3Solved with no hint and one move per colour (perfect).
2Solved with no hint.
1Solved with hints.

Each new star gives coins (Coins Per Star); replaying a level for more stars gives the coins of the extra stars only.

Home

The home screen shows the hints and coins (with shortcuts to get more), the logo, a solved level as illustration, a big PLAY button that continues with the next level to solve, and three modes: Levels (pack list), Daily (with a red dot until today's puzzle is solved) and Endless. The bottom bar opens the Shop, Themes, the Lucky Spin, How to play and the Settings.

Packs and levels

Each pack card shows a preview of one of its levels, its size, the levels solved and the stars. A pack opens when enough levels of the previous pack are solved (or early, with coins). Inside a pack, levels open one after the other (this can be switched off).

First level

On the very first level an animated hand shows how to draw, and a short text explains the goal; it turns into "fill every empty cell" when all colours are connected but cells are left. The How to Play popup also opens once on the first launch.

Requirements

  • Unity 6000.0 LTS. Made and tested with 6000.0.84f1. Use 6000.0.58f2 or newer: older editors produce builds affected by the CVE-2025-59489 security issue.
  • Android: Android Build Support with its SDK, NDK and OpenJDK, installed from Unity Hub. The game runs on Android 7.0 (API 24) and newer.
  • iOS: iOS Build Support, a Mac with Xcode (and CocoaPods once you add AdMob). The game runs on iOS 13 and newer.

Included: Unity IAP 5.4 (installed from the Package Manager through Packages/manifest.json) and TextMesh Pro (part of uGUI). Not included: the Google Mobile Ads plugin, which you download from Google when you are ready to show ads (see Ads). The game builds and runs without it.

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 need 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: a Google Play Console developer account, one-time registration fee (US$25 at the time of writing).
  • App Store: 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 before you publish.

Getting started

  1. Unzip the download. In Unity Hub choose Add → Add project from disk and select the LinkCrown folder.
  2. Open it with Unity 6000.0. The first import takes a few minutes (the Package Manager installs Unity IAP).
  3. Open the scene with Tools → Link Crown → Open Main Scene and press Play.
  4. Switch the platform to Android or iOS in File → Build Profiles.
  5. Open the settings with Tools → Link Crown → Game Config.

The game runs in the editor just like on a phone: set the Game view to a portrait resolution (for example 1080×1920) or use the Device Simulator. In the editor and in development builds, placeholder ads drawn by the game show where ads appear (rewarded ones give their reward), and purchases go through Unity's fake store, so every feature can be tried before you set anything up.

Project structure

Folder (Assets/LinkCrown)Content
ArtEvery picture: Board (dots, pipe textures, cells, frame, colour-blind symbols), Backgrounds, Icons, UI (buttons, panels, wheel…), the app icon.
AudioMusic and sound effects (WAV).
ConfigDot palettes and board themes (ScriptableObjects).
LevelsThe level packs and the daily pool (ScriptableObjects, edited with the Level Editor).
PrefabsEvery screen, popup and widget, and the logo.
ResourcesGameConfig.asset and Localization/strings.csv.
ScenesMain.unity.
Scripts/RuntimeThe game (assembly LinkCrown). Core holds the puzzle logic with no Unity code: level format, solver, generator, difficulty rater, rules of play.
Scripts/AdMobThe AdMob integration, compiled only when the Google Mobile Ads plugin is in the project.
Scripts/EditorMenu, Level Editor, import rules and build checks.
Fonts, Plugins, ThirdPartyLicenses, DocumentationFonts and their licenses, the iOS haptics plugin, this guide.

Outside that folder: Assets/Resources/BillingMode.json (Unity IAP store choice) and Assets/TextMesh Pro (TextMesh Pro essentials).

Game Config

All the settings, grouped by header. Hover a field in the Inspector to see its tooltip.

GroupFields
LevelsThe packs in order, the daily pool, Sequential Levels (levels open one after the other).
Endless modeBoard sizes offered, coins per endless puzzle.
RewardsCoins per star, daily puzzle coins, streak bonus per day and Daily Streak Bonus Days (how many days the bonus keeps growing, 7).
HintsHints at the start, hints per rewarded ad and ads per day, size and coin price of the hint pack.
EconomyCoins at the start, free coins for a rewarded ad in the shop and ads per day.
Lucky Spin8 slots, clockwise from the top (coins or hints, amount, weight; keep exactly 8, the wheel has 8 segments) and extra spins per day for rewarded ads.
ThemesThe dot palettes and board themes offered in the Themes popup.
AdsEnable Ads, Use Banner, interstitial frequency and cooldown, the AdMob App IDs and ad unit ids (Google's public test ids in the package: replace them with yours), your test device ids.
PurchasesTest Purchases and the product list.
LinksPrivacy policy, terms, store pages and support e-mail used by the Settings popup.

Levels & Level Editor

A level is stored as text, one character per cell, row by row from the top: . empty, # no cell (shaped boards), A–Z a dot (each colour exactly twice). The solution is stored next to it (one hex digit per cell giving the directions the pipe leaves the cell); hints use it.

width 5, height 5
cells  "A...BC.D.B..E.D.C..E.A..."   (5 rows of 5)
links  "64a2c5..."                     (filled by the editor)

The Level Editor

Tools → Link Crown → Level Editor. Pick a pack at the top (or select a Level Pack asset and press Open in Level Editor).

The Level Editor
The Level Editor: the pack's levels on the left, the brushes and the board in the middle, Check, Solve, Rate and Generate below
  • List (left): select a level; Add, Duplicate, Delete, Move Up / Down; Sort Pack Easy to Hard rates every level and orders the pack.
  • Size: change the width and height (2 to 15) and press Resize.
  • Brushes: 26 colours (A to Z), Eraser and Wall. Click or drag on the grid to paint. Each colour needs exactly 2 dots.
  • Check: proves whether the level has exactly one solution, more than one, or none. A level is ready when it has exactly one.
  • Solve: finds a solution and stores it (used by hints and previews). Show solution draws it on the grid.
  • Rate: how hard the level feels: solvable by logic alone, or the number of guesses a player needs.
  • Generate: replaces the level with a new random one of the same size and colour range, with exactly one solution. Walls you painted are kept, so you can draw a shape and generate levels for it.

Before each build, a warning in the Console lists the levels that have no valid solution stored (for example a level painted after its last Check): open them and press Check or Solve.

Players' stars are saved by level position. Reorder or remove levels of a pack before release; afterwards, only add new levels at the end, or add a new pack.

Adding a pack

  1. Assets → Create → Link Crown → Level Pack. Give it a unique Id (used in the save), a Name Key (add it to the CSV), a colour, the levels of the previous pack needed to open it and an optional coin price.
  2. Fill it in the Level Editor (Generate makes this quick), then sort it.
  3. Add it to Packs in the Game Config. The pack list builds itself from that array.

The daily puzzle

The daily pool (Levels/Daily_Pool, 366 levels from 6×6 to 9×9 and shapes) gives one level per calendar day, the same for every player. Edit or extend it like any pack.

Endless mode & the generator

The generator (Core/PuzzleGenerator.cs) covers the board with random pipes that never touch themselves, puts the dots at their ends and keeps the result only when the solver proves there is exactly one solution. The solver (Core/PuzzleSolver.cs) sweeps the grid cell by cell and counts every possible arrangement of pipes, so its answer is exact, not a guess. On a phone a 12×12 puzzle takes a fraction of a second; it runs on a background thread so the game never freezes.

The same code is used by the Level Editor and can be called from your own scripts:

var settings = new PuzzleGenerator.Settings { width = 8, height = 8, minColors = 7, maxColors = 8 };
LevelData level = PuzzleGenerator.Generate(settings, Rng.FromTime());      // null if none found
PuzzleSolver.Result r = PuzzleSolver.Check(level);                          // Unique, Multiple, NoSolution
PuzzleRater.Rating rating = PuzzleRater.Rate(level);                        // guesses needed

An endless puzzle left unfinished is saved with the game and offered again with Continue.

Economy & rewards

SourceDefault
New stars on a level5 coins per star (up to 15 per level).
Daily puzzle100 coins, + 20 per day of streak from day 2 (up to +140 from day 8). A puzzle started before midnight counts for the day it was started.
Endless puzzle5 coins.
Lucky Spin1 free spin per day + 3 more with rewarded ads; prizes are coins or hints.
Free coins (shop)50 coins per rewarded ad, 5 per day.
Hints3 at the start; +1 per rewarded ad (5 per day); 3 hints for 150 coins; hint packs and the starter bundle in the shop.
Double coinsAfter a level, a rewarded ad doubles the coins won.

Coins are spent on themes and on opening packs early. Every reward is saved as pending the moment it is won and added when the player collects it, so closing the app during an animation never loses it.

Themes

Dot palettes (Config/Palette_*): 16 colours each; colour A of every level uses the first one, B the second, and so on. Included: Classic (free), Candy, Neon, Jewels and Sunset. Board themes (Config/Board_*): background picture, preview, frame tint, empty cell colour and how strongly a cell takes the colour of its pipe. Included: Midnight (free), Ocean, Forest, Sunset, Graphite and Royal.

Create new ones with Assets → Create → Link Crown → Dot Palette / Board Theme and add them to the Game Config. Ids must stay unique (they are saved).

Colour-blind symbols (Settings): each colour gets its own symbol on its dots (circle, triangle, square, diamond, star…; Art/Board/Symbols).

Reskinning

  • Replace any PNG in LinkCrown/Art with your own of the same name: it gets the same import settings (sprite mode, 9-slice borders, compression) automatically.
  • Dots are drawn in grey and tinted with the palette colour (dot_base), with a white gloss on top (dot_shine). Pipes use pipe_profile (the shading across the pipe) and pipe_shine.
  • Colours of the palettes, backgrounds and boards are data: change them in the Config assets.
  • The app icon is in Art/UI/AppIcon (full icon, Android adaptive foreground and background, round icon).
  • Screens and popups are prefabs in Prefabs/UI; open them to move or restyle elements.
  • Fonts: Lilita One (titles, buttons) and Fredoka (texts), as TextMesh Pro font assets in Fonts.

Localization

The game comes in English, French, Spanish, Portuguese (Brazil), German, Italian, Indonesian, Swedish and Dutch. 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 LinkCrown/Resources/Localization/strings.csv: one row per text, the key first, then one column per language. Lines starting with # are comments.

key,en,fr,es,pt,de,it,id,sv,nl
level_n,Level {0},Niveau {0},Nivel {0},Nível {0},Level {0},Livello {0},Level {0},Nivå {0},Level {0}
  • Edit the file in any spreadsheet program and save it as CSV (UTF-8).
  • To add a language, add a column with its code and fill in language_name, then add the matching case in FromSystemLanguage and Culture in Loc.cs.
  • The fonts cover Latin alphabets with Western European accents. For other alphabets 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 by itself, the screens are not mirrored, and the included fonts have no Arabic or Hebrew letters. To add one, use an RTL / Arabic shaping solution for TextMesh Pro (for example the free, open-source RTLTMPro package), add a font that covers the alphabet as a fallback font, and check every screen in that language, as texts that mix numbers and words may need small changes.
  • In the scene, texts use the Localized Text component with a key. In code, use Loc.Get("key") or Loc.Format("key", value).

Ads (AdMob)

Only Google's official test ids are in this package. The Game Config ships with Google's public test App IDs and test ad units (publisher ca-app-pub-3940256099942544, listed on developers.google.com/admob/android/test-ads and /ios/test-ads). They only ever show Google's test ads and earn nothing. There is no other id in the package, and the Google Mobile Ads plugin is not included.
Replace the test ids with your own before publishing, from your own AdMob account. Google's terms and payment thresholds apply. A release build logs a warning while test ids are still in the Game Config.
Game Config fieldShipped value (Google test id)
Admob Android App Idca-app-pub-3940256099942544~3347511713
Admob Ios App Idca-app-pub-3940256099942544~1458002511
Admob Android: banner / interstitial / rewarded.../9214589741, .../1033173712, .../5224354917
Admob Ios: banner / interstitial / rewarded.../2435281174, .../4411468910, .../1712485313

The game reads ad ids only from these fields: nothing is hidden in code or downloaded.

Turning AdMob on

  1. Download the Google Mobile Ads Unity plugin from Google: github.com/googleads/googleads-mobile-unity/releases (written and tested with version 11.5). Import the .unitypackage with Assets → Import Package → Custom Package.
  2. Link Crown notices the plugin and switches its AdMob code on by itself (the LINKCROWN_ADMOB define, for Android and iOS), and copies the App IDs from the Game Config into Assets → Google Mobile Ads → Settings (also before every build). Check it with Tools → Link Crown → Ads → AdMob Status.
  3. Build for your phone: Google's test ads show right away.
  4. In AdMob, create your app and three ad units: banner, interstitial and rewarded.
  5. Replace the App IDs and ad unit ids in the Game Config with yours. An App ID of your own already in Google's settings is never replaced by a test one.
  6. To keep testing with your own ad units, add your phone to Test Device Ids (the device id is printed in the log by the Google SDK). Never click your own live ads.

Removing the plugin switches the AdMob code off again; the game always builds, with or without it.

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 requested only once consent allows it, and an Ad 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

FormatBehaviour (Game Config)
BannerAt the bottom of the screens when Use Banner is on; the layout moves up to make room.
InterstitialAfter a solved level, from level Interstitial From Level, every Interstitial Every levels, never within Interstitial Cooldown seconds of another full screen ad.
RewardedHints, free coins, double coins after a level, extra Lucky Spins. These buttons only work when an ad has loaded.

The No Ads purchase removes banners and interstitials. Rewarded ads stay, because the player chooses to watch them. To turn every ad off, untick Enable Ads.

Placeholder ads

Without an ad network, the editor and development builds show placeholder ads drawn by the game (a full screen card with a countdown and a banner bar), so you can see where ads appear and test every reward. Release builds never show them.

In-app purchases

Your own store accounts are required and the stores charge fees (see possible costs).

Purchases use Unity IAP 5 (com.unity.purchasing 5.4.4), with Google Play Billing Library 9 on Android and StoreKit 2 on iOS. The LINKCROWN_IAP define is set automatically for any 5.x version (asmdef version defines). If another major version is installed, the store code is switched off and a dialog, a Console warning and a build warning tell you right away; purchases are never switched off silently.

On Android the store is chosen by Assets/Resources/BillingMode.json, set to Google Play. Keep this file: without it Unity IAP uses its fake test store on Android. To change it, use Services → In-App Purchasing → Switch Store....

Product (default id)KindGives
com.yourcompany.linkcrown.coins_small / coins_medium / coins_largeConsumable1,000 / 6,000 / 15,000 coins
com.yourcompany.linkcrown.hints_small / hints_largeConsumable10 / 50 hints
com.yourcompany.linkcrown.noadsNon-consumableNo banner or interstitial ads
com.yourcompany.linkcrown.starterNon-consumable3,000 coins, 15 hints, No Ads and the Jewels palette
  1. Change the ids to your own in the Game Config (a build warning reminds you while they start with com.yourcompany).
  2. Create the same products in Google Play Console and App Store Connect. Google only returns products once a build is uploaded to a testing track.
  3. Add your Google account as a license tester to buy without being charged.

Each purchase is validated, delivered, saved, and only then confirmed to the store. Delivered transaction ids are kept in the save, so a purchase is never delivered twice. One-time products come back by themselves after a reinstall; payments confirmed later (cash, Ask to Buy) show "Purchase pending" and are delivered when they go through. On iOS, Settings and the shop have a Restore button, as Apple requires.

Testing: with Test Purchases ticked, purchases are simulated in the editor and development builds while the store has no products yet. Release builds always use the real store.

Receipt validation

Google Play: in Google Play Console copy your app's Licensing key (Monetize with Play → Monetization setup). In Unity choose Services → In-App Purchasing → Receipt Validation Obfuscator..., paste it and press Obfuscate. IAPManager finds the generated GooglePlayTangle by name (kept by link.xml) and checks every receipt and that it is for the product bought. Until then, Android builds log "Google Play receipts are not validated yet".

App Store: StoreKit 2 verifies every transaction itself.

Limits of on-device validation. These checks run on the player's phone. On a rooted or jailbroken device a determined player can patch the app and get around them. If your game needs strong protection (valuable purchases, an online economy), verify every purchase on your own server against the store: the Google Play Developer API (purchase status from the purchase token, found in the Google Play receipt) and the App Store Server API (transaction information from the transaction id, or the signed transaction appleSignedTransaction). Deliver only when your server confirms the purchase.

Your own server (optional): set IAPManager.ServerValidation; the game waits for your answer before delivering. PurchaseReceipt carries the product id, the transaction id, the store, the store receipt, the Google order id and the Apple signed transaction. In this example the server answers with JSON such as {"valid": true}:

using System;
using UnityEngine;
using UnityEngine.Networking;
using LinkCrown;

public class MyReceiptCheck : MonoBehaviour
{
    [Serializable]
    class VerifyResponse { public bool valid; }

    [SerializeField] string url = "https://example.com/verify-purchase";

    void Awake() => IAPManager.ServerValidation = Check;

    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<VerifyResponse>(request.downloadHandler.text)?.valid == true; }
                catch (ArgumentException) { valid = false; } // the answer wasn't JSON
            }
            request.Dispose();
            done(valid);
        };
    }
}

Save data & cheating

Progress, stars, coins, hints, themes, purchases, settings and the levels in progress (one per mode: pack, daily and endless, so playing one never loses another) are saved in PlayerPrefs (key linkcrown_save) as JSON signed with HMAC-SHA256 and lightly scrambled. A save that was edited or damaged starts over, and the rejected one is kept under linkcrown_save_broken.

Set your own secret before your first release. Replace SaveManager.Secret in Scripts/Runtime/Services/SaveManager.cs with your own random text (for example a new GUID). A warning appears when you build while it is still the original. Never change it after release.

This stops casual cheating; a determined player with a decompiler could still rebuild a save. If your economy needs more, keep the wallet on a server.

Daily rewards and the device clock

The Lucky Spin, the daily puzzle and its streak, and the daily ad limits follow GameClock, which never goes back: setting the clock back gives nothing (the spin and the daily puzzle say so), and a reward is free only on a later calendar day than the last one. Changing the time zone back and forth gives no extra day either; moving the clock forward can only move the next reward closer by the time zone difference.

Building

Android

  1. In Edit → Project Settings → Player set your company name, product name, Package Name and version.
  2. Create a keystore under Publishing Settings.
  3. With AdMob installed: if Gradle complains about missing dependencies, run Assets → External Dependency Manager → Android Resolver → Force Resolve.
  4. 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, portrait only, and uses ASTC texture compression.

iOS

  1. Set the Bundle Identifier and signing team in the Player settings. The minimum iOS version is 13.
  2. Build. With AdMob installed, open the generated .xcworkspace (not the .xcodeproj): CocoaPods installs the Google Mobile Ads SDK during the build.
  3. Set up the tracking prompt as explained below.

App Tracking Transparency (iOS)

When AdMob is installed, the prompt is shown by Google's UMP SDK as part of the consent flow that runs at launch. Without an IDFA explainer message in AdMob, iOS never shows it and ads are served without the IDFA.

  1. In Assets → Google Mobile Ads → Settings, fill in User Tracking Usage Description (for example "Your data will be used to show you ads that are more relevant to you.").
  2. In AdMob open Privacy & messaging, create an IDFA explainer message for your iOS app and publish it, together with your GDPR message.
  3. Check it on a real iPhone: Settings → Privacy & Security → Tracking must allow apps to ask. iOS asks only once per install (delete the app to see it again).
  4. In App Store Connect, answer the App Privacy questions to match (Device ID and Advertising Data used for third-party advertising).

Publishing checklist

  • Your own AdMob, Google Play Console and Apple Developer accounts.
  • Your own package name / bundle identifier, product name, icon and version.
  • If you show ads: the Google Mobile Ads plugin imported, and your own App IDs and ad unit ids in the Game Config instead of Google's test ids (no warning when you build).
  • A consent message published in AdMob (and an IDFA explainer for iOS).
  • Your product ids in the Game Config and the same products in the stores.
  • Unity IAP on a 5.x version (no warning in the Console) and Assets/Resources/BillingMode.json set to Google Play.
  • Your Google Play license key in the Receipt Validation Obfuscator.
  • Your own SaveManager.Secret.
  • Your privacy policy, terms, store links and support e-mail in the Game Config.
  • A release keystore (Android) and signing team (iOS).
  • A release build tested on a real phone.

Code overview

ClassRole
GameControllerEntry point: loads the save and language, starts ads and purchases behind the loading screen, opens Home.
UIManager, UIScreen, UIPopupScreens (Loading, Home, Packs, Levels, Game), popups, the Android back button, toasts.
LevelData, LevelPackThe level format and a pack of levels.
BoardModelThe rules while playing: drawing, cutting, undo, hints, moves, fill and the win check (no Unity code, unit-testable).
PuzzleSolver, PuzzleGenerator, PuzzleRaterExact solution counting, level generation, difficulty rating.
BoardView, PipeGraphicShows the board and handles the finger; the pipes are one mesh with rounded corners.
GameScreen, GameSessionThe playing screen and what is being played (pack level, daily, endless).
Progress, Wallet, GameClock, SaveManagerStars and unlocking, coins and hints, the safe clock, the signed save.
AdsManager, AdMobProviderAds API and the AdMob implementation (Scripts/AdMob).
IAPManagerPurchases, validation and delivery.
Loc, LocalizedTextTexts and numbers in every language.
TweenThe small built-in tweening library used by every animation.

Adding a popup

  1. Create a class deriving from UIPopup (override OnOpen / OnClose).
  2. Make a prefab with a CanvasGroup, a dim background button and a Panel; assign them on your component.
  3. Put it under Canvas/Popups in the Main scene and add it to the UIManager's Popups list.
  4. Open it with UIManager.Instance.Get<MyPopup>().Open().

Troubleshooting

No ads show on my phone

Check that the Google Mobile Ads plugin is imported (Ads → AdMob Status), that your App IDs and ad unit ids are in the Game Config, the internet connection, that Enable Ads is on and that No Ads wasn't bought. New ad units can take hours to start serving. In the EU the consent form must be answered first.

The Android build fails after importing AdMob

Google's plugin stops the build when its Android App ID is empty. Link Crown copies the one from the Game Config before each build; if the field in the Game Config is empty, fill it in. For dependency errors run Assets → External Dependency Manager → Android Resolver → Force Resolve.

"Store not available right now"

The store doesn't sell your products yet: they aren't created, not active, or the build isn't on a testing track. Use a development build with Test Purchases on meanwhile.

Every price shows $0.01 on Android

Unity IAP is using its fake store because Assets/Resources/BillingMode.json is missing or not set to Google Play. Choose Services → In-App Purchasing → Switch Store... and pick Google Play.

A level I made says "More than one solution"

Players could solve it another way than the hint shows. Move or add dots until Check says "Exactly one solution", or press Generate.

Pink or missing pictures in a build

Edit → Project Settings → Graphics must list UI/Default in Always Included Shaders. It is set in this project.

Files named "... 2.png" or "... 2.meta" appear

The project is inside a folder synced by iCloud Drive, OneDrive or Dropbox. Keep Unity projects in a folder that isn't synced, delete the duplicates and reopen the project.

My progress was reset

The save was edited outside the game, or SaveManager.Secret changed. The old save is kept under linkcrown_save_broken. While developing, use the Cheats menu instead of editing PlayerPrefs.

Updating to a new version

Each update is a complete project with a changelog that lists what changed. Your own content lives in a few places, so you can bring it into a new version without losing anything:

  1. Back up first. Commit your project to version control or copy its folder.
  2. Open the new version as a separate project and copy your own content into it. Always copy a file together with its .meta file: Unity keeps the links between assets through them.
  3. Your settings: LinkCrown/Resources/GameConfig.asset (ad ids, products, economy, links). If the changelog lists new Game Config fields, they appear with their default values; set them as you like.
  4. Your levels: the Level Pack assets in LinkCrown/Levels, with their ids and the order of their levels unchanged (players' stars are saved by pack id and level position).
  5. Your look: the palettes and boards in LinkCrown/Config, and the images, sounds and fonts you replaced. Keep the file names, or assign your files again in the prefabs.
  6. Your texts: take the new strings.csv and paste your own translations and edited rows into it, so the keys added by the update are kept.
  7. Your code changes: compare your scripts with the new ones (a diff or merge tool helps) and apply your changes again.

Safe to overwrite: anything you never changed (scripts, prefabs, the scene, the documentation). If you edited prefabs or the scene, apply your edits again on the new ones.

Players' saves: keep the same SaveManager.Secret in every version (copy your secret into the new SaveManager.cs): a different secret makes every existing save look edited, and players start over. Updates only add save fields, which start with their default values, so existing players keep their coins, stars, purchases and settings. Never rename a pack id, palette id, board id or product id after release.

Before publishing the update, raise the version and the build number in Player Settings, then play the game once from a previous version's save to check that progress is kept.

Credits & licenses

The game, its code, every level, the dots, pipes, boards, backgrounds, icons, the logo, the app icon, the sounds and the music are original work created by the author, drawn and synthesized with the author's own tools. Some UI graphics (buttons, panels, icons and the Lucky Spin wheel) and five sound effects are shared with the author's other product, Ludo Crown. No stock images, emoji sets, clip art or sound libraries are used. The following third-party assets are included; their licenses are in LinkCrown/ThirdPartyLicenses and allow commercial use:

AssetLicense
Fredoka fontSIL Open Font License 1.1
Lilita One fontSIL Open Font License 1.1
TextMesh Pro essential resourcesUnity Companion License (part of Unity's uGUI package)
Unity IAPUnity's package terms (installed from the Package Manager)

The Google Mobile Ads plugin is not included; if you add it, Google's license (Apache 2.0) applies.

Changelog & support

1.0.0

First release: 450 levels in 9 packs, daily puzzle, endless mode, Level Editor, 5 palettes and 6 boards, colour-blind symbols, AdMob-ready ads layer, Unity IAP 5 purchases, 9 languages.

Questions or problems? Leave a comment on the item page or use the support form on our profile, and include your Unity version and the platform you build for.