#UI #QA #UIArtwork #Audio
My dream team and I put together this project within two weeks. Originally, the assignment was to implement one design pattern per person if working in a group. We decided to implement all of them, since we were the largest group, and it would help us understand how all the implementations came together.
Not So Super Mario is a data structures programming assignment where you create a simulated Mario game. My group wanted to bring that to life through Unity.
We started by creating our design/project document, which you can view here. We then had Keira create the level designs, which you can see in the following links:
Through amazing communication and having extra time over Thanksgiving break, our game was polished and born!
Check Out The Game!
UI
I was responsible for creating all of the UI elements, implementing the audio, and building the achievement system. While the project was primarily about showcasing our design pattern skills and their application in games, I learned so much more—particularly in UI engineering. In my previous UI projects, I tended to lean on traditional instruction manuals filled with text. However, through this project, I realized that players often overlook instructions if they’re overwhelmed with information. I saw this firsthand for Corgi's Day Off, the summer educational game I worked on. The kids didn't seem at all interested in the walls of text, preferring to have someone show them what each feature did.
So I did just that for the instructions page of this game. I worked hard to condense the necessary information into something visually appealing and easy to digest, using minimal text. Although we weren’t able to implement instruction videos as initially planned, I enjoyed the challenge of creating an accessible and player-friendly experience. It was fun to incorporate knowledge from the human factors course regarding accessibility for people of all ages and those with disabilities.
As for the menu screen, in pre-production, I had the buttons without any text, looking like what you see below:
I quickly realized that this didn't explain anything. Although it might be a little fun to try and find the buttons and figure out what they do, I had to think as if I had never played a game in my life. It hit me that this wasn't clarity at all.
Art
What you see as my UI art is very much what people in the game development programming minor call "programming art," which basically means that a programmer tried to do art, haha. The main menu screen was a drawing created by SoulStryder210. In the pre-production phase, I had come up with some goofy menu screens. To go with the title name, the team wanted to be a bit goofy about it.
I came across SoulStryder210's artwork and thought it was the perfect canvas to integrate a style I had always wanted to try. So everything you see is a simple trace and coloring. I didn’t try to do anything fancy. In regards to the other UI, I wanted to keep the "drawn" feeling of it all, except for the title cards. So I used Procreate to design the rest of the screens along with the text. The titles are all made by a Mario 64 text generator. Initially, I had written out the titles as shown below, but in the end, I decided to scrap it and go with the titles you see now.
Code
My code is extremely straightforward. I tried to be as organized as possible with it. In previous projects, my code was filled with setActive
true and false, but I found that I can do that all in the inspector (which is life-changing!). Instead, the UI manager controls the buttons on the menu screen, and depending on whether they are playing or not, states get changed. This also controls the pause menu buttons and all of the back buttons.
Audio Manager
Most of my scripts look a little like this, very short and to the point. My UI Manager is the only one that isn't a singleton although it could have been as it is used throughout different scenes.
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
public AudioSource musicSource;
public AudioClip backgroundMusic;
public AudioClip winSound;
public AudioClip loseSound;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
//keep this object between scene so the background stays
}
private void Start()
{
PlayBackgroundMusic();
}
private IEnumerator StopMusicCoroutine(float seconds)
{
//stop the music
musicSource.Stop();
yield return new WaitForSeconds(seconds);
// Resume the music
musicSource.Play();
}
public void PlayBackgroundMusic()
{
if (musicSource != null && backgroundMusic != null)
{
musicSource.clip = backgroundMusic;
musicSource.loop = true;
musicSource.Play();
}
}
public void StopBackgroundMusic()
{
if (musicSource != null && musicSource.isPlaying)
{
StartCoroutine(StopMusicCoroutine(4f));
}
}
public void PlayWinSound()
{
if (musicSource != null && winSound != null)
{
musicSource.PlayOneShot(winSound);
}
}
public void PlayLoseSound()
{
if (musicSource != null && loseSound != null)
{
musicSource.PlayOneShot(loseSound);
}
}
}