Unity Arcade High Score Table
Xevious, like many arcade games, has a very basic high score table. The user has a fixed amount of time to enter their initials. Typically that was just 3 initials but whilst Xevious still says, “enter your initial” it allows you to enter your name — maybe something lost in translation in the original? The mechanism for it is to use the joystick to move the characters up and down the alphabet. Once you have the correct letter you press fire and it moves the virtual insertion point on by one.
The movement consists of two different gestures. A move and recenter would be a single character, whereas holding the stick in a direction would move through the character set at a faster rate.
Implementing in Unity
Given my version is implemented in Unity and there is fair chance a keyboard, either physically or virtually, can be involved I wanted to allow that as well as the traditional ‘navigation’ approach.
How to capture the changing values?
The game calculates the position of the new high score and creates a Unity Input Field at that location. This will happily capture user input from a keyboard. However, if a Game Pad is the main control then the Input Field will support the ‘navigation’ style of input too.
I should point out this is an early draft of my code, there are bugs and better ways to do this (I think) but I will show my nasty code, warts and all.
The basic idea is to recognize that a string is an array of chars and chars are just integers. Therefore if we know the navigational direction the user has entered we can increment/decrement the int of the char at the current position — in this case the current position is always the last character because it does not support corrections.
How to store the values?
Now we have a way to capture the values, how can we persist them so the high score table lives between games?
In this example there are only ever 5 high scores, therefore I can use a very simplistic solution. Remember I said it was very simple :)
Using a very basic class, HighScoreRow, I can store 5 instances to represent each of the 5 positions. Then, in a very hard-coded fashion, I create 5 associated PlayerPrefs. Using ‘by convention’ I can fetch or retrieve each position using jsonForScoreX. The only additional trick is to initialise the high-scores to a fixed set and detect if that is needed. The detection is just to check if we have a preference stored for the first score. It is not bullet proof but good enough for now :)
PS I recommend using PlayerPrefsEditor Asset, which is free from the Asset Store, to help visualize and diagnose the stored preferences.
Bugs & Improvements
When the user presses fire the virtual insertion point moves on but I have not moved the actual InputField insertion point.
The Input System has the concept of ‘Interactions’ and I believe the ‘Hold’ interaction will be a nicer replacement for the ‘Repeat Key Delay’ Coroutine.
Wrapping around the available character set — currently the navigation is clamped to the highest or lowest value, ideally it should wrap around rather than force the user to go in the opposite direction.
NB the font I am using does NOT support lower case characters — Xevious has them, bah!
With the minor bugs & improvements implemented I will have replicated the Xevious high score table. To move into the modern world I could use a shared high score table in a service like PlayFab. I think there are other features to implement before I get there, but it should not be a difficult transition.