top of page

Majorem

About the game

Engine: Unity

Language: C#

Majorem is a resource-gathering village builder, that sees players cater and care for their community.


Majorem was created during the 2021 Tranzfuser Enterprise Pathway by me and my team (Cosy Umbrella), for which I was the Team Leader and one of two programmers.

The Tranzfuser Enterprise Pathway ran over 12 weeks, and development of Majorem started during the first week of Tranzfuser. It was a fun and challenging process that tested my skills as a games developer and team leader. Although a challenging 12 weeks, Tranzfuser increased my desire to work in the games industry tenfold.

Majorem: Bio

Team Management

As team leader, part of my role was to organise each member of the team, ensure that everyone was keeping to deadlines and finishing work efficiently and to a sufficient standard.

ClickUp and Perforce made it easy for myself and Josh (Project Manager) to create sprints and evaluate the teams performance. Tracking each members performance was an essential part of the project and team management and was the information was used to plan future sprints more effectively and ensure that each team members workload matched their ability.

Majorem: Text

Programming

During development I worked on a number of areas of the game, these include but are not limited to:

  • Day/Night Cycle

  • Plot/Building System

  • Quest System

  • Resource Harvesting

  • Scene Switcher

  • Decoration Editor

  • UI

    • Main Menu​

    • Settings

    • Main game HUD

  • Audio manager

    • Ambient​

    • Sound Effect

    • Music​

Editor tools: 

  • Object rotator + scaler

  • TextMeshPro helper

  • Scroll view helper

The object rotator and scaler were created to speed up the level creation process, giving all the children of an object a random rotation (on selected axes).

The TextMeshPro helper was used to update all TextMeshPro component simultaneously, saving time with assigning fonts and materials. Similarly, the scroll view helper updated all scroll views to use the same values (scroll sensitivity being the main reason for the scripts creation)

Majorem: Text

Day/Night Cycle

The day/night cycle was a very important aspect to Majorem, both aesthetically and practically. Aesthetically the day/night cycle goal was to immerse the player into the world of Majorem, functionally this was important as they were able to look at the sun's/moon's position to estimate the time of day. If the player was out harvesting resources in the wilderness past 10pm, they would faint and lose the resources they had gathered in that session, so knowing the time of day was important.

Below is a code snippet showing the way the day/night cycle handles the sun and moon positions in the sky. By rotating an Transform with a directional light component, a celestial body will move across the sky.

When both light sources are at the horizon, the game world is pitch black (I boosted gamma values to allow the player to see the game), at this point the shadows of the setting and rising celestial bodies are turned off and on respectively (Unity is built to handle one directional light to be casting shadows at a maximum).

Majorem: Text
DayCycleExample_SunAndMoonRotation.png
Majorem: Image
Majorem_DayNightCycle_Example.gif
Majorem: Image

Quest System

To create the quest system, I created a scriptable object called "Quest". Changing a scriptable object at runtime will directly change the file data, not an instance of the file. This was used to store quest progress across game sessions. 

The code snippets below show 2 functions with the same name, but different signatures. Both functions handle quest progress for different quest types.

The first function handles fetch quests "Get X amount of Y", this function was used for: Gather, Craft, Cook and Grow quests. The other function handles Build quests "Build a crop farm".

Majorem: Text
QuestManager_QuestObjectiveProgress_GatherQuest.png
Majorem: Image
QuestManager_QuestObjectiveProgress_BuildQuest.png
Majorem: Image

Resource Harvesting

Wanting to keep this process as simple for the player as possible, I implemented a system that would choose the tool the player needed based on the resource they were targeting (based on a bounding box, distance to the player, dot product and resource state). 

The harvesting animations held an event to spawn a crit marker on screen at a random offset from the objects transform. A UI element would be shown at the screen position of the Transorm position, if the crit marker was within X units when the OnHit() function was called, the resources gained is multiplied by the crit multiplier for this object.

Originally, I had the crit spot spawn at a random vertex taken from the resources mesh. Player feedback showed us that this was frustrating and made harvesting tedious. To rectify this, I generated a list of Vector3's (used as offsets) within a bounding box unique to each resource, caching these in the start function ensured fast access at runtime.

The code snippet below shows the code used to generate and select a crit spot location.

Majorem: Text
Harvesting_SpawnCritSpot.png
Majorem: Image
Majorem_ResourceHarvesting.gif
Majorem: Image

Scene Switcher

Knowing the time pressure of the Tranzfuser programme, Josh and I decided the simplest solution to changing scenes would be to have everything in a single scene and to activate/deactivate components depending on which area you were entering (Village or Wilderness), this made loading almost seamless and allowed us to keep scripts active. To avoid any potential issues, I also moved the parent object out of render/collision distance, just in case any components were missed during the process. 

To achieve this, all objects in the wilderness and village were parented to a different object (Either "WildernessParent" or "VillageParent"). In the start function, all required component references were cached into a list, when the player changed scene, each component list was looped over and either activated or deactivated. 

The components I needed to change the state of were:​ Terrain, Renderer, Collider, Light, sPlot and AudioSource.

The code snippet below shows the code used to change the state of the village objects, each for loop cycles over a different list, the same is done for the wilderness lists. The video below the code shows a slowed down version of the scene switching code.

Majorem: Text
SceneSwitcher_ChangeVillageState.png
Majorem: Image
Majorem_SceneSwappingSlow.gif
Majorem: Image

Audio Manager

The audio manager handled all of the audio sources in the game. To make sure the code was easily accessible, I created static functions combined with a singleton. Knowing this would be called a lot during each play session, I decided the best method of spawning the audio sources into the world would be to pool them, so I only instantiated a new object if I absolutely needed to, otherwise they were just reused.

The audio manager also controlled the playlist of the game. A scriptable object was created which held a song name, audio clip and the times of day that the song could be played. In the start function, 24 lists (1 for each hour of the day) were populated with the songs available to their corresponding hour. When a track had finished a random song was chosen from the current hour's list.

Below is the code used to spawn SFX objects into the world, passing in the SFX scriptable object to load all the relevant data.

Majorem: Text
AudioManager_CreateSFX.png
Majorem: Image

Source code

To view all of the above scripts, along with many unmentioned ones, that I created during Majorem's development, click the button below to go a GitHub repository with all of the .cs files.

Majorem: Text
bottom of page