After 9
After 9
My Role - Lead Designer and Puzzle Designer
Evaluated every designer's ideas based on feasibility, novelty and connection to the required theme for the project (i.e. "Beneath the surface").
Organised tasks between every designer based on their strengths and preferences.
Developed the entire code base, including a code input taking system and a system to flicker lights and TV screens. (We were a group of 5 designers, and only I knew programming.)
Designed the puzzles for the game in conjunction with the environment designer so as to leave clues for the puzzles in their design.
Key Features -
Intriguing premise about what's hidden in the mundane and piques the player's curiosity.
Atmospheric sounds and effects to further immerse the player in the eerie environment.
Cryptic passages on the walls that not only work as hints for the puzzles but also contribute to the story and the atmosphere of the game.
Code Input System UI
Design Highlights -
The office location is designed to be as mundane as possible while slowly revealing more hidden elements to intrigue the player, akin to games like "Stanley Parable".
The hidden locations in the map reveal satanic cult like practices followed by the office employees "after 9" (pun intended) as the player slowly explores the office building.
Intuitive and well-integrated into the environment, puzzles that require the players to read the cryptic clues and observe their environment for details to figure out the puzzle.
Code Snippets -
The following code snippets showcase some of my programming work in Unity, showcasing problem-solving skills and the importance of efficiency and simplicity.
Flickering Lights -
[SerializeField]
Light currentLight;
private float currentLightIntensity;
private float waitForSeconds = 0.1f;
[SerializeField]
float flickerLowLimit = 0.1f;
[SerializeField]
float flickerHightLimit = 0.4f;
[SerializeField]
float timeBetweenFickersLowerLimit = 2f;
[SerializeField]
float timeBetweenFickersUpperLimit = 5f;
[SerializeField]
int numberOfFlickersLowLimit = 3;
[SerializeField]
int numberOfFlickersHighLimit = 6;
int numberOfFlickers = 4;
// Awake is called when MonoBehaviour script is first loaded
void Awake()
{
currentLightIntensity = currentLight.intensity;
waitForSeconds = 0.1f;
StartCoroutine(FlickerLight());
}
IEnumerator FlickerLight()
{
// Determining the number of flickers in one flicker cycle
numberOfFlickers = (int) Random.Range(numberOfFlickersLowLimit, numberOfFlickersHighLimit);
for (int i = 0; i< numberOfFlickers; i++)
{
// Creating small variations between the timing of each flicker's on and off states
currentLight.intensity = 0;
waitForSeconds = Random.Range(flickerLowLimit, flickerHightLimit);
yield return new WaitForSeconds(waitForSeconds);
currentLight.intensity = currentLightIntensity;
waitForSeconds = Random.Range(flickerLowLimit, flickerHightLimit);
yield return new WaitForSeconds(waitForSeconds);
}
// Determining the wait time between each flicker cycle
waitForSeconds = Random.Range(timeBetweenFickersLowerLimit, timeBetweenFickersUpperLimit);
yield return new WaitForSeconds(2);
StartCoroutine(FlickerLight());
}
Code Input System -
[SerializeField]
GameObject interactInputText;
bool playerInVacinity;
bool currentlyTakingInput;
[SerializeField]
GameObject imageToShow;
// Awake is called when MonoBehaviour script is first loaded
private void Awake()
{
playerInVacinity = false;
currentlyTakingInput = false;
}
// Triggered when colliding with a trigger
private void OnTriggerEnter(Collider collisionInfo)
{
// Makes the interact button available
if (collisionInfo.name == "Player")
{
interactInputText.SetActive(true);
playerInVacinity = true;
}
}
// Triggered while exiting a trigger
private void OnTriggerExit(Collider collisionInfo)
{
// Makes the interact button unavailable
if (collisionInfo.name == "Player")
{
interactInputText.SetActive(false);
playerInVacinity = false;
}
}
// Update is called once per frame
void Update()
{
if (playerInVacinity)
{
// Show player the pop-up window to write the code
if (Input.GetKeyDown(KeyCode.E))
{
if (currentlyTakingInput)
{
currentlyTakingInput = false;
interactInputText.SetActive(true);
imageToShow.SetActive(false);
Cursor.lockState = CursorLockMode.Locked;
Time.timeScale = 1;
}
else
{
currentlyTakingInput = true;
interactInputText.SetActive(false);
imageToShow.SetActive(true);
Cursor.lockState = CursorLockMode.Confined;
Time.timeScale = 0;
}
}
}
}
Learning Outcomes -
The most important thing I learned is how to combine different skills of various people into a product that utilises everyone's strengths while also incorporating the required theme (Beneath the surface) into the project.
Importance of lighting and sound design to the overall atmosphere of the game.
Incorporating puzzle design with narrative design and environment design since this game's puzzles utilise all those elements.
How to come up with a catchy game title :D.
Link to After 9's Game Design Document - After 9 GDD