Improving Upon Selection Highlighting in Our Game — Part 3
This article is about the development process of our first game. During the process, we are learning how to use Unity & Blender from scratch to create everything you see in the article, enjoy!
Introduction
Welcome back to the third and final installment of improving the selection system. In the last article we looked at some minor improvements and bug fixes and in this article, I will finish the implementation so that we can continue with the vehicle system in the next part.
This time I will focus on the following 3 things:
- Updating the arrow model to a new one that looks more clear to the viewer
- Implement functionality to switch which item is selected with the
Tab
key - Bugfixes
Updating the Arrow Model
We have updated the arrow model to a new one that should look more clear to the viewer.
To implement it, I’m going to select the game object as the value for the appropiate variable in the ItemSelector
script.
Switching the Selected Item
I want to update the functionality of the selection system so that when you have a bunch of items in front of you, you should be able to pick which one is selected by pressing Tab
so that you don’t have to move all other items out of the way first.
The Current Functionality
When you get in range of an item that can be interacted with, that item is added to a list of items that can be interacted with.
If you come into contact with more items, they are placed at the bottom of the list.
Should an item go out of range, they will automatically be removed from the list, and if the item at the top of the list is removed, all other items will move one step up in the list, item #2 will be number #1 and the selection arrow will hover above the new #1 instead.
Let’s see how this works in action:
Implementing Changes
The functionality that I want to enable should rotate the list by one step so that the item at the top of the list is added to the bottom, and everything else moves up a step when you press Tab
, and vice versa in the other direction when you press Shift + Tab
.
For the first step, I will create a function that is called when pressing Tab
. I’m going to place it in the class CharacterInteractions
since all the other functions that are called by using the keyboard and mouse controls are in there already.
Next, let’s write a function in the ItemDetector
class that will rotate the list of colliding items and see if that works:
My strategy for rotating the list forwards goes as follows;
- Copy the last item in the list to the top of the list.
- The 1st item in the list should be automatically moved to the 2nd position, the 2nd item will be moved to the 3rd position, and so on.
- Remove the original item from step 1 at the bottom of the list from the list.
These steps will be the same, except in reverse when rotating the list backward.
Let’s try implement my theory in code and see if it works.
After rotating the list, the next step will be to set the variable selectedItem
to the first item in the list the and spawn the arrow above it.
Before I do that, I will refactor RotateList
a bit and rename it to RotateListAndReturnFirstItem
.
After refactoring, I will update the function call of RotateListAndReturnFirstItem
to set selectedItem
to the first item in the list.
Let’s try out the code and see if it works!
It didn’t work exactly as I wanted on the first attempt, here are some issues that has to be fixed:
- When pressing
E
at the end of the video, the watering can is picked up even though the spade is selected. Therefore, I have to make sure that the selected item actually is the one that will be picked up. - Sometimes when pressing
Tab
, the arrow just disappears. This is because the objectDock island grass
is selected and that object does not have theItemSelector
script attached to it, but it is still necessary to be in the list for the sake of other functionality. To fix this problem, the script will have to skip items that cannot be interacted with and move them to the bottom of the list.
The Wrong Item Gets Picked Up
Let’s look at what the function for selecting which item to pick up looks like before we try and fix the problem.
If we look at line 7
, it says selectedItem = itemDetector.ReturnClosestItemByTagOrLayer("tag", itemType);
.
This means that when I select something by pressing Tab
, and then try to pick it up, the line of code above is called which disregards which item is already selected and just picks the closest item to the player.
I commented out the line that I mentioned above and now it picks up the one that is selected, easy peasy!
Ignoring Items That Cannot Be Picked Up
As you have probably seen in the videos above, the game object for the island itself is also selected when pressing Tab
to switch the selected item, which is a problem. I want the function to put the items that cannot be picked up at the bottom of the list automatically.
I will begin by writing a function to move items of certain layers to the top of the list so that all other layers are not selectable;
I updated the functionRotateListAndReturnFirstItem
to call MoveLayersToTheTopOfTheList
, and I also created a new list that only contain layers 6
(items) and 10
(vehicles) to pass to that function.
I also made sure that the function call for RotateListAndReturnFirstItem
can’t be run when an item is equipped so that you have to drop whatever you are carrying before selecting something new to interact with.
As you can see, the game now only selects items that can be picked up and ignores the rest.
Doing it in reverse
Now that we have successfully implemented a way to switch which item is selected in one direction, let’s also make it possible to press Shift
+ Tab
and go in the other direction.
The reason for wanting to be able to go through the list in the other direction is to allow players to go back in the case that they go too far and don’t want to go through all other items in the list that are (for the moment) irrelevant.
I will begin by implementing the trigger for pressing Shift
+ Tab
;
When going from the back of the list to the front, we have to remember that we are already placing all items that do not belong to layers 6
(items) or 10
(vehicles) at the back of the list.
This means that I cannot just pick the last item of the list and put them first to rotate the list without running into the same problem as before. Instead, I will try to loop through the list in reverse and find the last item in the list that can be interacted with and put that first. Before I begin, I’ll see if I can get the loop to go through the list in reverse.
Let’s modify the code to print out the last item in the list that is selectable, to make sure that the correct item will be selected;
Finally, let’s implement changes to select that item and put it first in the list.
Fixing bugs
Now that all the feature are implemented, let’s fix the bugs before we call it a day.
The Water Pump Is Selected When Dropping the Spade
For some reason, the water pump is selected when you drop the spade, but it should only be selectable when you are carrying a watering can.
The problem is caused by the following line in the function OnTriggerEnter
in the ItemDetector
class:
When I select an item that comes within range, I need to write an if case
to make sure not to select the water pump unless the player is carrying the watering can.
I added the if case
to ReturnClosestItemByTagOrLayer
;
The Arrow Gets Stuck When Rotating Backwards
The code for rotating forward seem to work, but not the code for rotating backward. Let’s take another look at how the code is written;
If we look closer at the code, there are a couple of mistakes that might help explain the problem.
Not Rotating the List
If you look at line 20
above, it looks like I am inserting the first item in the list… in the same position it’s already in.
It should of course be collidingItems.Insert(0, collidingItems[i])
, not collidingItems.Insert(0, collidingItems[0])
, I will go ahead and fix that so that the list actually rotates as it should.
Rotating Forward and Backward at the Same Time
Both SwitchSelectedItem("forward")
and SwitchSelectedItem("backward")
are called when I press Shift
+ Tab
because the only condition for SwitchSelectedItem("forward")
is that Tab
is pressed.
I changed the code and now it is only possible to call either SwitchSelectedItem("forward")
or SwitchSelectedItem("backward")
, but not both;
Removing the Wrong Item When Rotating the List
If you look at line 9
, it says collidingItems.RemoveAt(i - 1);
. This line determines which item to remove after adding it to the top of the list so that there are no duplicates in the list.
Unfortunately, I thought about the index to be removed incorrectly, and the index of the item to be removed should be i + 1
instead. This is because the index of the original item has moved down 1 position(i + 1
) because we add 1 item(+ 1
) to the top of the list.
Final Result
Now the system for switching back and forth between objects seem to work exactly as it should!
Conclusion
Thank you so much for reading all the way to the end, this article got way longer than I thought it would.
Now I am finally done with item selection and can continue with implementing the vehicle system in the next part.
Let me know if you have any thoughts or questions about our game in the comments!