I have my canvases set up in my game, but I have no way of moving between them. For this, I need a player that the user is able to move about the screen and go into different areas of the map. I needed to create the images that will be used as a visual representation of that player.

This is a page I stumbled upon while looking up on how to import custom graphics into unity:

https://www.tutorialspoint.com/unity/unity_creating_sprites.htm

I will reference and expand on sprites more in the report.

For my sprite I needed to create an 2D image that would have a transparent background(otherwise with shapes that aren’t square, the background would be visible and not look good in the game).

The only software I had for this on my machine was potentially Paint3D, but after struggling to use this, I decided to get a better piece of software for image editing.

As I wouldn’t make much use of an image editor, I didn’t want to drop money into paying for one, so I looked up free options on google and came upon this site.

https://www.techradar.com/nz/best/free-photo-editor

Gimp is a widely used and free image editing software, which would be perfect if I got stuck and needed some tutorials. So, I decided to download and use gimp for creating the pngs that would be turned into Unity Sprites.

This site was useful for learning the basics of Gimp https://www.gimp.org/tutorials/

As I wanted customization of the character in my game, I needed to create a PNG (portable Network Graphics) for every Head, Body, and Foot sprite. The above image shows one of my heads, that I created using just a circular paintbrush in gimp.

The reason I chose to use PNG as the image format (despite PNG’s being large in file size) is due to reading posts like this on the forum

https://forum.unity.com/threads/png-vs-jpg.124264/

The other option unity accepts is JPEG/JPG (Joint Photographic Experts Group). As JPEG files use a lossy format(I might expand on this in my report), this can apparently cause artificing). To avoid future problems, I decided to go with PNG

Using a bit of foresight, I decided to keep the different sprites for each section of the body the same size, as I didn’t want scaling or hitbox issues later in unity. Also, I made each sprite quite small, as it would save on the size of the assets that need to be loaded in the game.

I also made all my sprites white, as this will be the default colour, and should help prevent confusion when I introduce changing the colour of the sprites.

I then saved as a PNG and moved these PNG into my assets folder in the unity game engine.

I struggled a bit with getting unity to show the sprites in game, and I couldn’t drag and drop the sprites into the game like I thought I could.

The eventual solution I found to this is to create a game object that has what’s called a Sprite Renderer. This will allow me to change the colour of the sprite later, as I discovered through this web page:

it also gives me extra options for editing the sprites if I wanted to implement features such as flipping, or expansion/shrinking, or layering later.

I created a Game object for the head, body, and feet, and assigned the default sprites to it. I also added a text box that would show the character’s name later on.

Now I had the problem of making the character move. I wanted to implement movement at this point, as hiding and activating canvases, and manually changing screens was annoying when I wanted to test different features of my game.

I grouped all of the created GameObjects and put them into a parent GameObject that I would use to move about the screen.

I had multiple ways of solving the problem of movement in unity. I could have the GameObjects move around the screen, or I could add what’s called a RigidBody to my GameObject, so I can add hitboxes which are essentially areas around the sprite that when touched an event would be triggered.

Rigid body is Unity’s physics engine, which allows adding physics to an object in the game. This is one of the bonuses of using a game engine, as the complex interacting between items and the physics of an item is mostly done for you.

This is the RigidBody2D(2d because it’s a 2d sprite) component that I added to the player group. I then created a script that would be used to move this rigid body.

As I now have a RigidBody attached to the object, it will now be affected by physics. I could potentially add jumping to my game, so I created a box collider around the player. I also created a box collider around the ground.

The green box represents the collider.

As for now, I have frozen the Y position(up and down movement) for the player in the RigidBody component, as I don’t have an intention of including jumping.

Resources that helped me figure out movement in unity are the unity documentation, and this youtube video.

https://docs.unity3d.com/ScriptReference/Rigidbody2D-velocity.html – setting the movement of the object.

https://docs.unity3d.com/ScriptReference/Vector2.html – vector 2 refers to the x and y co-ordinates that are used to move the characters.

https://www.youtube.com/watch?v=7t37XGYEw2M – run bunny run jumping tutorial.

There are multiple ways of moving the rigid body. The ways I have discovered are: you can move the figure along an axis, you can add force(which will essentially be like acceleration), or you can do it this way and set and set the velocity to a vector.

I decided to go with vectors. Vectors are a ratio between x and y co-ordinates, so if I wanted to later include jumping and moving, I would need to use a vector as shown which gets the y value.

The RigidBody variable is a Unity type that will be assigned to the player game object.

The speed variable is the speed at which the character will move across the screen. This is set to public so that I can easily change and modify it in the unity engine while testing. It is a float, which while using c# with unity you indicate with an f after the number.

https://answers.unity.com/questions/530939/why-do-i-need-the-f-when-using-a-float.html

The speed variable determines the number of units that will be moved by the object per second e.g. 2 speed = units per second.

This canvas scaler which was included when building the UI sets a unit to 100 pixels, so if the speed is 2, 100 pixels will be travelled by the object every second.

This documentation is useful for units and scale.

https://docs.unity3d.com/2019.3/Documentation/Manual/BestPracticeMakingBelievableVisuals1.html

Void Awake() is called when a script is loaded in unity. As the player game object is active from the beginning, this script will run and set the rigidbody variable to the player game object.

FixedUpdate() is used instead of Update(), as the fixedupdate will run consistently which is important for physics( you don’t want you character to keep arbitrarily going faster or slower depending on the frame rate).

Using unity’s input detection, I have two if statements that run in the fixed update.

My controls so far are the keyboards right and left arrow. The first if statement checks to see if the left arrow key is activated on the update (held down). If this is the case, the velocity of the rigid body is set to a new Vector2, which takes an x and y co-ordinate. The x co-ordinate is the speed * -1 as this makes the value negative (if holding left we want to go down the x axis), the y component of the vector is the current y velocity, which now should be 0. The opposite happens if the right arrow is detected as being held down, and the character will move along the x axis in a positive direction which will be right.

A problem with doing things this way, is that the vector is set one after each other as if conditions. This means that if both are held down, the character will move right. This is a problem that could be fixed by potentially adding another condition, or using another method, but I am not really bothered by this.

After testing this, the player can now move left to right. I found that 75 speed is a good sweet spot, and setting linear drag (how fast the object slows down) to 10 made it nice to use.

Switching Canvas

My problem now is that the player can now move off the screen. To prevent this, I need the player to move to the next canvas.

To do this I created an arrow sprite. I put these on each canvas and rotated the arrow so I can use one sprite for both arrows.

I then attached a box collider to this sprite that will trigger when the player object moves into them.

Each arrow has a script I have attached to them. This script contains the next canvas, and the previous canvas for that arrow. It also contains a method that will be called when it interacts with another box collider.

The next scene and previous scene variables will be connected to the canvas. The next scene will be the next intended canvas of that arrow, and the previous scene will be the canvas the arrow is on.

I have used the DeBug log for testing, as it shows me when I have collided with an arrow.

The next canvas is shown, and the current one is de-activated, which hides it.

This created the problem of an infinite changing loop, as the player object touches the arrow that has appeared from the new canvas and this method is immediately called again, changing the canvas.

To solve this, I added the object that touches the arrow as an argument, the integer which will be the x position the player will be moved to(if you enter from the left of a canvas, you want to appear on the right of the next canvas) and a transformation on the position of the colliding game object which will move it to the selected x co-ordinate, and y to 10(which is the ground height).

This solution works, but it’s a bit of a messy solution. Firstly, this means each arrow needs to be set up individually, positioned, and have the next scene, previous scene, and x co-ordinate added (whether the arrow moves left or right depends on the new x co-ordinate of the player) This means that if a new area is to be added, or I want to change the layout, I must manually enter everything again. Secondly, the y position isn’t taken from the player, and is instead just set to 10, which is the ground level, but doesn’t reference anything, so if the level of the ground is to change, I will have to come back and change this. The y also doesn’t account for the Player’s current y co-ordinate, but this could be useful to avoid the player glitching through the ground.

However, it is working smoothly for now, and I can now access all the canvases.

Typing Game

To set up the typing game, I needed random words to populate the text box that the user would then type. As I don’t have a database set up, I created a string array which contained a selection of words. Future work would be to implement a word bank into the database, so I’m not too worried about separating this all out into different classes for the moment.

I created a variable for what was going to be the displayed text the user would need to type. I also created a variable that would be text of the user’s current word they are typing on screen.

I created an integer variable called WordCount, that is used for changing the number of words that will be gathered for the user to type in a game. I also created a private list called wordList that would hold a random selection of words from the word bank. As I wanted to generate a random word from the list, I needed to import the Random system library in my name space. I then created a new Random variable named rnd, which creates a new instance of the Random Class.

I’m using the Next method, which is part of the random library and will return a random integer.

https://docs.microsoft.com/en-us/dotnet/api/system.random.next?view=net-5.0

I used a loop to fill the wordList using the WordCount number. As I wanted a random selection, I created a temporary integer variable called index, and assigned a random value from my calculation.

The calculation gets the length of the word bank, and then returns a random positive integer between 0 and the length of the wordBank array.

To my wordList, I then added the word from the wordBank array that corresponded to the position of the integer. For example, if there’s three words in the array [“one”, “two”, “three”], the randomly selected index would be either 0, 1, or 2 as the array has a length of 2(the first index in an array starts at 0). I then use that number and add the string that’s in that position in the wordBank to my wordList List as well as a space(this will separate the words out for the user). This is run as many times as the specified WordCount number, so the same word can occur multiple times which is what I wanted.

My problem is that the final word will now have a space at the end. To solve this, I extracted the selection into a method, and one final word is selected after the loop is finished. As the loop is i < Wordcount, I changed the i to start at 1, so the additional word would fit in the WordCount.

Now this new method selects a random word and concatenates it with the selected ending when the method is called. This concatenation is now added to the wordlist.

Now I needed to set the textbox on the type of game screen to the word list.

As unity can’t display a list, I worked around it and converted the list to an array and setting the text to the array.

I now needed to show the current word the user would be typing. Using a new Text variable called DisplayedWord, which was assigned to a text object under the text box in the game engine.

I needed to keep track of the word the user was on, so I created a private integer called wordIndex that would start at 0.

This method gets the current word the user is on. The currentWord is the first item in the list(0), and the text displayed on the screen is the character |, which is supposed to serve as a cursor to guide the user, and this cursor is followed by the current word.

When the scene is now loaded, these methods I have just defined are called, so the code should work now.

This was successful in testing and gave me what I wanted. Now I needed to code the user inputs.

I now needed to add functionality to the game. As I was trying to code this game from scratch without using tutorials, I came upon a lot of problems, and working this out using Unity’s game engine took a lot of time.

One of these problems, was how the user was going to input text. I decided not to use an input field, as I didn’t want focus to be lost on the canvas or input field which would stop the user progressing. But using Unity’s WebGL meant that getting the inputted keys was a lot more difficult than I had previously anticipated. For WebGL, unity uses the HTML5 Gamepad API(https://docs.unity3d.com/Manual/webgl-input.html) that I would need to explore.

https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnGUI.html

The ONGUI event runs multiple times per second, and I can use this to check for any updates to the GUI, which would be user inputs.

The Event e picks up the current event that is happening on the GUIUpdate. I need to check if this event is a KeyDown event, which means that a key has been inputted by the user.

The KeyCode that the GUIUpdate had detected now needs to be passed into the system. Firstly, if the character pressed equals the next character that needs to be pressed, the game should progress on to the next character.

This if statement checks if the event character pressed is equal to the character the user is up to in the current word. wordChar is a private integer variable that starts at 0, so in the code above, it checks to see if the character pressed is equal to the first character in the currently displayed word. If the characters are equal, then the wordChar adds one to itself. So, if the user enters the right character, and this code is run again on the next character, the user will now have to match the second character.

As these is no way to visualize this now, I needed to move the | cursor forward if successful and show the user they were incorrect if the character doesn’t match. To achieve this, I decided to change the colour of the on screen text where they had gotten it wrong.

From looking aroundthe forums, there didn’t seem to be an easy way to change this in the editor, so I had to find a solution using code. After failing and spending a lot of the time on the forums, I came across the unity documentation for styled text

https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html

if (e.character == currentWord[wordChar])

{

wordChar++;

DisplayedWord.text = (“<color=#00FF00>” + currentWord.Substring(0, wordChar) +                    “</color>” + “<color=#FFFFFF>” + “|” + “</color>” + currentWord.Substring(wordChar, currentWord.Length – wordChar));

}

else

{

DisplayedWord.text = (“<color=#00FF00>” + currentWord.Substring(0, wordChar) + “</color>” + “<color=#FF0000>” + “|” + “</color>” + currentWord.Substring(wordChar, currentWord.Length – wordChar));

}

Note: I used text instead of a screen shot here, because otherwise it would be too hard to read.

Now I will try to explain this solution.  It is using markdown, which unity will display as customized text on the screen. As I wanted the part of the word that the user got right to be green, the colour code #00FF00 is green for the first block. Included in the first block is a Substring of the currentWord, which is a method to select part of the string, and the part selected is from the beginning of the word up until the current character the user is up to in the word using 0 to represent the start, and the wordChar for the current character.

Added to this text, is white coloured text that is the | cursor used to indicate the user’s place. The remainder is just the plain black text showing the rest of the word from the point the user is up to. This works by selecting from the character index the user is up to, and then adding the remainder of the word. This caused me problems with the index being out of range, because the currentWorld length would be longer than what remained in the word. To solve this, I then subtracted the current character index from the Word length to get the remainder of the word. So for example, if the user is at character 2(index 1), and the word is 5 characters long, characters 0 to 2 would be highlighted green, and characters 3-5 would be white.

I then wanted to add feedback for if the user got the current character wrong. This is the else statement that is the same as the original if statement, but the cursor turns red instead of white, and the word character index isn’t increased, so the user does not progress.

This works while testing it, but I have a problem that occurs when I get to the end of the word and hit space, because the character index selected is bigger than the selected word’s length. To solve this, I needed to add an if statement to check for the space bar being inputted. This check will need to come before the character check.

Now if the key pressed is the space bar, the program checks to see if they are currently on the last character of the word. If they are, the word character the user is on is set to 0, and the word index gets 1 added to it. Now when the setCurrentWord method is run, the next word will be selected. The character check is now only run if it’s not the space key, so I shouldn’t get any more out of range errors.

The typedWords.text is my solution to indicating to the user how many of the words they’ve finished. Instead of putting it in code, the typedWords text is a unity Game Object that is positioned Infront of the Displayed Words and is coloured green. So, when a word is completed and added to that text, it shows up as the word having a green glow.

I felt like this solution worked well and I was happy with it.

Now I had the problem of ending the game.

As the full stop would only appear once in the game, I decided that if it was the current character and the user typed it, the game would end. This created an issue where if the user pressed space instead of the full stop on the last letter the game would throw an error as there would be no more words.

This was my quick solution. It means the period isn’t the last character, the user won’t see it, and the game will still end when the user types the full stop character when it’s active.

Now to go about finishing the game, I needed to have a timer that would calculate the words the user typed per minute

I created a timer in c# that would activate as soon as the first key was pressed. This timer consisted of a Boolean value that would turn true.

On update, if the timer is enabled, unity will start to track the time.

When the game is finished (run when the full stop character is typed), the GUIUpdate is disabled, so no more input will re-activate the timer. The displayed words and the glow I added to them via TypedWords will then display how fast the user typed. The words per minute are calculated from the number of words typed divided by the time elapsed in minutes (calculated using seconds elapsed divided by 60). I used the Format command to get a whole figure instead of decimal places.

This is the game finished in Single Player mode.

A bug I went back and changed was the | cursor being red at the start of every new word.

I changed the colour of the cursor when a new word is displayed to be white.

I changed the keycode to just recognize a space character, as there seemed to be a bug in unity where the space would register, and then the GUIUpdate would play again this time activating the else statement.

In the future I could also make the text at the top track at the same time as the word being typed, but I like it how it is now.

Using so many If and else statements also makes me feel like I could have used a case statement and made the code a little tidier.

Matching Game

For the matching game, to solve my multi choice problem, I generated a case statement.

This is the current single player solution. The question number will be the question number the user is on, which will be by default set to 1(so case 1 will be selected). The Question.text will display in the text box on the game showing the question. The btnA.Text  etc. are the multiple choice buttons text component for buttons A, B, C, and D. Each case also includes the correct answer to the question which is the button number.  All of these variables are linked to Game Objects via attaching the script in the Unity Game Engine.

When the game is started, the PickQuestion method is run, which will select and display the question form the case statement.

Each button has a letter which will be sent as an argument to the AnswerClicked method above. If the player answer is the same as the question answer, the user will have one score added, and they text will turn green. If the user is wrong, the colour of their score will turn red.

The question number is then increased, and the pickQuestion method is run again, selecting the next question.

When the number of questions answered is the number of questions per game, the game ends for now.

ErrorGame

This game gave me a lot of problems. Originally the idea was to have essentially a C# interpreter that will run the user’s inputted code. Unfortunately, after a lot of research, and trying to get it to work with unity WebGL proved unsuccessful. It could be a project in itself to code my own interpreter not to mention the all the errors, and bugs that arise. I will be able to expand more on this in my report, however.

There is an interesting interpreter called MoonSharp, which uses LUA.

https://www.moonsharp.org/about.html

and I found someone who had spent months coding their own interpreter into unity, but it was a paid for option in the unity asset store.

https://forum.unity.com/threads/miniscript-lightweight-scripting-language-for-your-game.373853/

For now, the solution to my problem is just going to be having simple errors the user can fix. The way the code will work is to trim all the spaces out of the code, and if it matches the answer text, the game will count it as a correct solution.

This is a variance to the plan and not ideal, but if I have more time later on in the project, I will try to get it working within my game.

These are my variables that I am going to test. The qText is the question text, aText will be user’s answer, qAnswer is the question’s answer, and qOutput will be the result of inputting the question. These questions will be randomly selected from a database in the future.

This is essentially how it will work for now. The trim command will remove spaces from the beginning and end of the text. The regular expression will turn multiple spaces into a single space. The text will then use that to get ride of new lines, and space at the beginning/end of lines. The code the replaces double quotes with single quotes. Doing all this should clean the inputted text enough to allow the user some freedom with their answer. I could potentially make all the text lower case, but I will decide on that later.

When I get questions and answers from the database eventually, they will need to look like this for now. If the user’s text matches, the output will show what the code should output in C#, and if it doesn’t match, it well tells them it’s not correct.

The game is finished when the user wins.

Next week I want to work on the database system that my game is going to use, along with the design and modelling of that system. I also want to work on reducing my future journals word counts. I end up writing thousands of words and it takes a lot of time. I feel as if I could put in less description and expand on anything in my report and take notes for expansion in the report.