As we write this guide, it’s early February 2022. And the word game Wordle is seriously viral.
It’s challenging and creative, but extremely simple. It’s easy to learn, but hard to master. And the colorful way it shows your results (without giving away answers) is endlessly shareable.
So that’s why it’s proving so popular. And that’s why we decided to write this guide to creating Wordle puzzles in Unity 2020.3.25f1. As well as showing you how to make the game in Part 1 of this guide, we’ll also cover implementation, feedback, and polish.
After that, in Part 2 we will demonstrate how to use LootLocker to improve the Wordle experience with a few features that the original game did not have including persistent player accounts, friend lists, and global leaderboards.
But first, how do you play Wordle?
The challenge is to guess the mystery five-letter word in six tries.
Each guess must be a real word.
When you enter your guess, each letter is color coded:
So with each guess, you get a little closer. Get the word right within six guesses and you win.
It’s as simple as that.
In this first part, we’ll cover setting up the UI we need for the game. We’ll also add some UI along the way. But to start, we’ll need the onscreen keyboard and boxes where the players’ guessed letters will appear.
Making a new Unity Project.
We used these four images for the game. You can use these, or make your own.
This is where the players’ guessed letters will appear.
This process is similar to what we did with the word-boxes. But we’ll have three rows, and those rows will have different numbers of buttons.
The easiest way to set this up is to create three separate horizontal layout groups. (Instead of one Grid Layout group.)
Add a new GameObject and name it ‘Keyboard’. Under it, create a new game object and name it ‘Row 1’.
Add a new object with a button to Row 1. To do this, right click on it and select UI -> Button.
Set the sprite RectangleRounded.png as the sprite. Name the newly created Image object “Key”. Add a text object into it by right clicking on it and selecting UI -> Text.
Set the anchor scaling of the text to be stretched to fit. Drag this into the project window to make it a prefab.
Add a Horizontal layout group component to the Row 1 game object. Do this by clicking Add Component in the Inspector, with Row 1 selected, and typing Horizontal layout group.
Select these settings for the horizontal layout group:
Duplicate the Key game object in the hierarchy window (Ctrl+D/Command+D) until you have ten of them. This is the first row of your keyboard.
Press ‘T‘ with Row 1 selected and scale it until it’s roughly to the same size as here:
(To scale the object from the center, hold alt after you’ve pressed. You can also move it by pressing ‘W’, and then using the arrows on screen.)
Now we need to do the same for the next 2 rows.
Rows two and three will just have nine letters each.
Duplicate (Ctrl+D/Command+D) the first row, and remove one letter prefab from that row. Move and scale it until you have something similar to this:
Now we’ll remove the horizontal layout group from the bottom object. This is because we’ll want the enter button and backspace button to be a bit bigger. And we can’t do that now because the horizontal layout group is stopping us.
Select the last Row game object and right click on the horizontal layout group in the inspector. Select “Remove Component”.
Now select the first and last objects in the list. Scale them so they’re aligned with the top row.
We’ll add more UI as we go. But we’ve already got all the UI we need to get coding.
In this part we’ll get the keyboard working – so that pressing a button makes the correct letter appear in the console.
It would take a long time to manually write in all the letters and assign the functions. So instead we’ll do it automatically. (Well, it might not actually be any faster, but automating is definitely more fun.)
Create a new folder called ‘scripts’ and a new C# Script called PlayerController.
Enter this code:
Now, we’re taking all the buttons and adding letters to each of them from a list of characters.
We then assign a function to the Button Components OnClick field. With this function, whenever we click the function, ClickCharacter() will be called with a reference to that button's letter. This then outputs it to the console.
In unity, create a new Game Object in the scene. Name it PlayerController and assign our newly created script to it.
We’ll add all characters to the list we just created so we don’t need to do it manually.
Start by expanding all the keyboard rows in the project hierarchy. After that, lock the inspector with the PlayerController object selected.
Drag all Key objects, except for the first and last one in the last row – 'return’ and ‘backspace’. (It’s easier to do these manually.)
Quick test: Press Play and you should have something similar to this:
Press the keyboard buttons and you should see the characters appear in the Console.
This is where we start making the actual game. Wordle has very simple rules, based around two lists of words.
So let’s focus first on getting the keyboard inputs to function properly as word guesses.
Wordle uses 2 different lists of words:
Create a new folder in the assets folder in Unity called Resources. Put these two files there.
Now we’ll read these files and put all of them in two different lists.
Create a new GameObject in the scene. Attach a new C# script called GameController.
Insert this script:
Quick test: Now press play. If the console outputs two big lists of words, that means everything’s working.
This is where we choose a random word for the player to guess.
Quick test: Take a second to go back to Unity and press play. You should get a message in the console with a random word. This will be our correct answer.
We’ll let the player input five characters into the top row and press enter. Then for every letter the player’s entered, we’ll check two things:
In GameController.cs, add a reference to the list of wordboxes and an integer with the current wordbox:
Add a using statement (for the text components) in the top of the script for UnityEngine.UI:
Then add a public function to input a character into the current wordbox:
Now go back and call this function on the GameController.
In the top of PlayerController.cs, add this reference to GameController:
And in the function ClickCharacter, run the newly created function AddLetterToWordBox() and send the character to the GameController:
First, drag the GameController to the variable GameController in PlayerController:
Then we set up the references to the wordboxes in the GameController. Do this by locking the inspector window and dragging them into the list of WordBoxes:
Quick test: Now, when we press play, we should be able to insert characters into the wordboxes.
But at the moment, we can enter as many characters as we want, until we’ve filled out all six lines. At that point, we’ll get an error message.
So let’s fix that next.
Quick test: You should now be able to input only five characters into the first row. Once that row’s full, only the Backspace and Enter keys will work.
We’ll check if the current wordbox is empty. If it is, we’ll remove the character before that. If the current wordbox isn’t empty, we’ll remove the one we’re on.
In GameController.cs, add this function at the bottom of the script:
In Unity, click the button that’ll function as the Backspace (the last button of the last row). Call this function on the GameController by adding it to the OnClick() list on the button component:
Quick test: Press play and you should be able to input characters and remove them too.
To do this, we need to check the player’s guess against the correct word, and go straight to the next row.
We’ll add a function in GameController.cs that’ll convert the letters in the current row into a new string.
We’ll then check this string against the correctWord string. If it matches, we’ll make the console output the good news that the player’s guess is correct. (This would be incredibly unlikely with their first guess, but we'll get to that soon.)
Quick test: If everything’s working, you should be able to get to the next row by pressing the Enter button. And the console should tell you if your guess was correct or not.
Players do odd things sometimes. They might, for example, try to submit a word that has fewer than five characters. So let’s put a few guardrails in to stop the player doing unexpected things.
In the function SubmitWord(), we can stop the player submitting any word with fewer than five letters:
In the function AddLetterToWordBox, we need to check if the currentWordBox is the last one. If so, we’ll stop any more characters going in.
Add this variable to the top of the script in GameController.cs:
Next, add this to the start of the function AddLetterToWordBox()
We also need to add this to the SubmitWord() function:
And to the remove letter function as well:
Quick test: When you press play, you should now be unable to input any characters once you’ve filled out the last row.
You should also be unable to submit a word until all the word boxes on the current row are full.
Now we have a functioning game.
It’s an extremely hard game at the moment, because we don’t get any feedback on our guesses. But it’s a functioning game nonetheless.
Our game wouldn’t be much fun to play at the moment. When a player enters a word, all they get back is ‘right or wrong’ feedback.
What makes Wordle so tantalizingly addictive is the color code that tells players how close they are to the correct answer.
So here’s what we need to do:
Color the background of the wordbox (and on the keyboard) to:
We also need to stop the player entering nonsense words – use the dictionary list to check if the word exists or not.
We’ll start by adding a function to get the image of a specific letter in PlayerController.cs.
Quick test: The correct characters should now turn green on both the wordboxes and the keyboard.
This is a bit trickier than just checking if the correct word contains a certain character. If we do that for every character, we could give the player some misleading information.
Here’s a quick example:
Let’s say the correct word is STOPS, and the player guesses LOOPS. If we check every single character and mark them yellow, one letter ‘O’ will be yellow and the other one will be green, which could make the player think there’s more than one ‘O’ in the answer.
Here’s another quick example:
The answer is ARTSY and the player guesses SALAD. If we simply check if the character exists in the word, both A’s in SALAD will be yellow.
So to fix this issue, we need to create some checks and temporary values. These will update the information for every character.
This will be a lot to code in one block, but bear with us. We’ll go step by step and explain what’s happening.
Insert this code into the function CheckWord() that we just created:
In broad terms, we’re replacing correct letters with ‘0’ – and replacing letters that exist elsewhere in the word with ‘1’. When we get the same character a second time, we’ll replace that character with a ‘.’ (dot) to make sure we don’t find it more times than it exists in the answer.
Here is a walkthrough of what happens:
To finish this bit, let’s just summarize an example of the journey a player’s guess will take:
Without this system, there are quite a few places here where we could’ve given the player misleading information. For example, in 3e, the character would’ve become a 1, which would leave the player thinking there are two S’s in the correct word.
The game would still work without these checks, of course. In fact, you could even run it as a ‘hard mode’, because the player has less feedback to work with.
Now it’s time to rewrite some of the CheckWord() function, so it’ll check against these temporary variables and assign it a color:
We also need to make sure we don’t override any colors on the keyboard that we don’t want to. So the updated version of the CheckWord() function needs to look like this:
Quick test: Press play and have a go. If everything’s gone to plan, it should look like this:
The gray color doesn’t look great on the black background though, does it? Let’s change that next.
Let's change the keyboard to a light gray with white characters. This will make the letters on the keyboard more visible when they change to a darker color.
Go to any of the Key prefabs and change the color to a light gray, and the text color to white. Then apply the changes:
Quick tip: When you’re using colors like white or black, try to not go with full white or full black. Making white slightly darker and black slightly lighter can make a huge difference.
It’s all personal preference, but we think the bottom colors are a lot more pleasing to the eye than the top ones.
Now our game’s almost fully functional. But there’s one dead simple thing left to do:
We need to make sure the player’s guesses are valid words from the dictionary.
To do this, we simply iterate through all of the words in the dictionaryList. If nothing matches, we don’t continue.
Add this to the SubmitWord() function, after we’ve converted the player’s guess to lowercase characters:
We now have pretty much all the features Wordle has. But we’re still missing an important part of the game: feedback!
For a player to understand your game, you need to give them the right feedback. We already have some of the feedback in place – like the keyboard and word boxes switching colors. But we still need some more.
So for this part, we’ll add this feedback into the game:
For the types of feedback that we’re adding here, we’ll use the same popup.
In Unity, create a new Image inside the Canvas. Name it Popup and add a Text component to it.
On the Text component, hold down Alt and change the anchoring type to stretch the width and the height:
Let’s also change the text to center in the middle of the box as well:
While we’re here, we should give it a more pleasing shape too.
Add a function called ShowPopup(). This will show the popup for two seconds, and then disappear or stay depending on the type of message.
At the top of GameController.cs, add a reference to the popup – and a variable for the coroutine we’ll be using for the popup.
In the bottom of GameController.cs, we need to add two things:
Next, we add this function call to the places where we need to give the player feedback. These places all exist in the SubmitWord() function.
Let’s go back to Unity and set up the reference to the popup. We’ll also turn the popup GameObject off. This way, the game won’t start with the popup open.
Quick test: Press play and make sure your feedback messages are popping up in the right places at the right times.
We now have a fully complete game of Wordle, with all the feedback and features we need.
But it still lacks a bit of polish – or as we’d call it: ‘juice’.
So in part six, we’ll focus on the little details that make the game look and feel more pleasing.
Juice, polish, game feel – these all mean basically the same thing. After you have all your features and mechanics in place, you polish it and ‘juice it up’ to make it feel as good as possible. This is where the game stops feeling like a prototype, and starts feeling like a fully finished product.
There are lots of videos on the topic of ‘juicing’. Here’s are some we’d recommend:
Different types of juice work for different types of games.
For a casual puzzle game like Wordle, you don’t need anything spectacular. Things like screen-shake or explosions would feel very out of place.
For our Wordle game, we’ll focus on quick and snappy animations, like these:
Scaling the wordboxes will make them ‘pop’ a bit when the player enters a letter.
We want it to be very quick and snappy.
Our go-to solution is usually to use Animation Curves in Unity. They give you a lot of freedom to iterate and test out different types of animations really quickly. So that’s what we’ll do here.
We actually like to start it a bit below 0. This gives it a small build up that makes it ‘pop’ better. Here’s how we configure our Curve:
Here’s a picture of the curve we used:
Of course you can create whatever Curve you think looks best. But if you want to use our exact Curve, you can copy this code and paste it on top of the Animation Curve:
Quick test: Let’s press play and see how this looks in Unity.
Here’s a comparison between the version with feedback and without feedback:
Without feedback:
With feedback:
It looks a lot nicer, don’t you think?
This time, we won’t be using any animation curves. Instead, we’ll do it entirely in code.
Here is how it looks in the original Wordle::
Here’s what we’ll do:
We’ll scale down the word boxes, one by one, to a y-scale of 0. Then change the colors and sprites, and then scale them up again. We’ll do a bit of rewriting of the CheckWord() function to add this new behavior. We’ll make it into a coroutine instead of a regular function and then do this animation for every wordbox.
Quick test: Now, if you press play in Unity, you should hopefully have something similar to this:
If a player tries to submit a non-existent word (or one with too few characters), we need more feedback than simply nothing happening.
So we’ll wiggle the wordbox row to show it’s refusing the word the player’s trying to submit.
To do this, we’ll use a similar approach to what we just did. But we’ll do it completely in code.
First, we need to add some more variables. At the top part of GameController.cs, we’ll add a list of starting x-positions for the wordboxes and a reference to the grid layout group:
Let’s add a function that does that and fetches the starting positions of the wordboxes;
Then in the Start() function, we call this new function:
We’ll use cosine to get a value between -1 and 1. We’ll then multiply this value with a speed and multiply it by a radius to decide how big the wiggle should be. We’ll then lerp this value towards 0 so it’ll stop wiggling when the duration is up.
Add this function to the bottom of GameController.cs:
With this function added, we now just need to call this coroutine when a player enters too few characters, in SubmitWord():
…then in SubmitWord() when the word doesn’t exist in the dictionary:
Now in Unity, we need to set the reference to the Grid Layout group in GameController:
Quick test: Press play and submit a made-up word (or one with too few characters). You should now see the row wiggling in disapproval.
At the moment, the popup messages just appear abruptly out of nowhere. To make it smoother and more pleasing, we’ll scale it up from 0 to 1 with a smoothstep curve. A smoothstep curve is a curve that will start slowly and end slowly:
So we’ll do this curve. But instead of using an animation curve, we’ll code it from scratch.
We can use this function for both popping up and hiding the popup. We just need to send a bool in with the coroutine.
Quick test: Now let’s go back into Unity and check it out.
Much smoother.
And with that, we’re done.
You now have completed a fully featured polished version of Wordle! If you followed all of the steps correctly, it should play something like this. If you want to download the source files of this particular project, you can find them on our Github page or in the link below.
If you're ready to continue, make sure to check out Part 2 of our guide where we will show you how LootLocker can help make a great game even better using LootLocker's out-of-the-box backend features.
We do these guides because it’s always really good practice to understand how other games are made by reverse-engineering and recreating something that already exists.
But what we really want is for you to take what you’ve learned here and use it to bring your own ideas to life.
LootLocker makes it quick and easy to get through the more arduous, boring parts of game development – like leaderboards, player accounts, and friend lists, to name just a few.
We designed every aspect of Lootlocker to save you time. It works straight out of the box, no matter your game’s size, genre, platform, or engine. We’re always here to help and mentor you (if you need it), through our Discord channel. And it’s totally free each month, up until you hit 10,000 monthly active players.
Take a look at the features page of our website to see how LootLocker can help you make your dream game a reality.
Oh, and if you liked this guide, please share it on Twitter or LinkedIn!