Project name: OriGo

Genre: Construction, Artillery, Turn-based multiplayer

Platform: PC (designed for mobile)

Engine: Unity 3D

Other software or services used: Pivottracker (Project management)

Team size: 7; 3 designers, 4 artists.

Responsibilities/Role: Scripter, Documentation, QA manager

Project status: Complete.

Gameplay video

"OriGo is a Construction/Artillery game that focuses on building by shooting out blocks from cannon. The players build on a mysterious floating object, called OriGo. The OriGo makes blocks attach to itself, as well as to other blocks already landed on it. The game welcomes the players' own creativity to build by using blocks and collect scores in a challenging way, by making the player think on how to work from different angles."

OriGo was a schoolproject in which we were assigned to groups, each containing three designers and four artists. We were given a concept by Fatshark, and a total of 9 weeks, (2 weeks of preproduction and 7 weeks of production).

A list of requirements was given to us by Fatshark.

The requirements for the game, as given by Fatshark, were:

  • Target audience should be casual gamers

  • Free 2 Play - sales model based on in-game purchases

  • Age Rating: Free of choice

  • Platforms - PC and mobile

  • Learning Curve - Intuitive gameplay that caters to the casual gamer

  • Genre - Construction/Artillery game

  • Game modes: Two player hot-seat

  • My responsibilities as a scripter during this project were:

  • Turn-based system (Phases)

  • Pause function

  • Rule work (Timer, Locking and activating functions)

  • Multiplayer system

  • GUI (Visual countdown, Player announcement, mousepointer)

  • Misc functions (Stabilize camera, round counter)

  • Menus

  • In addition to scripting, I was also responsible for writing the Changelog every week, updating the GDD and QA management.



    Turn-based system (Phases)

    Since one of the requirements from Fatshark was that the game should be for mobile and hot-seated, we decided to make the game turn-based. An early requirement from Fatshark was that the game should have different phases, where the players will be doing different things, which is why the word phases is used here. The phasecontroller (see script below), manages all phases in the game. Only one phase can be active at one time.

    using UnityEngine;
    using System.Collections;
    /* Creator: Bianca Savazzi 
     * Author: Bianca Savazzi */
    public class PhaseController : MonoBehaviour
    	public bool								constructionPhase;
    	public bool								attackPhase;
    	public bool								changePhasesPhase;
    	public bool								pausePhase;
    	public bool								endGame;
    	public GamePhasesEnum	 				previousPhase = GamePhasesEnum.ChangePhases; //Used to track which phase was the one before pausing the game
    	public GamePhasesEnum					previousPhaseSwitch = GamePhasesEnum.ChangePhases; //Used to track which phase was active before reaching ChangePhase
    	public GamePhasesEnum					m_CurrentPhase = GamePhasesEnum.ChangePhases;
    	private GamePhase[]						m_Phases;
    	private bool							m_IsDirty;
    	private bool							m_Return = false;
    	private InputController					m_InputControllerScript;
    	private CameraMultiplayer				m_CameraMultiplayer;
    	private RoundCounter					m_RoundCounter;
    	private AudioController					m_AudioController;
    	void Start ()
    		//Gets data, resets phases and sets IsDirty.
    		m_Phases = GetComponentsInChildren ();
    		ResetPhases ();
    		m_IsDirty = true;
    		m_AudioController = (AudioController)FindObjectOfType (typeof(AudioController));
    	void Update ()
    		//Switches to pause phase if space is pressed.		
    		m_InputControllerScript = (InputController)FindObjectOfType (typeof(InputController));
    		if (m_InputControllerScript.escapeClick && m_CurrentPhase != GamePhasesEnum.Pause) 
    			//What happens when the pause menu is first brought up.
    			SwitchPhase (GamePhasesEnum.Pause);	
    			m_AudioController.PauseClick ();
    		} else if (m_InputControllerScript.escapeClick && m_CurrentPhase == GamePhasesEnum.Pause) 
    			//What happens when you press escape again with the pause menu up.
    			ReturnFromPause ();
    		//To win game
    		m_RoundCounter = (RoundCounter)FindObjectOfType (typeof(RoundCounter));
    		if ((m_RoundCounter.amountOfRounds) <= (m_RoundCounter.RoundNumber*2)) 
    			SwitchPhase (GamePhasesEnum.EndGame);			
    		if (m_IsDirty) {
    			ResetPhases ();
    			for (int phase = 0;
       			phase < m_Phases.Length;
       			++phase) {
    				//Here goes phases
    				if (m_CurrentPhase == GamePhasesEnum.ChangePhases &&
         		m_Phases [phase] is ChangePhasesPhase) 
    					m_Phases [phase].enabled = true;
    					previousPhase = GamePhasesEnum.ChangePhases;
    					changePhasesPhase = true;
    					m_Return = changePhasesPhase;
    					PauseGame ();
    				if (m_CurrentPhase == GamePhasesEnum.Construction &&
         		m_Phases [phase] is ConstructionPhase) 
    					m_Phases [phase].enabled = true;
    					previousPhase = GamePhasesEnum.Construction;
    					previousPhaseSwitch = GamePhasesEnum.Construction;
    					constructionPhase = true;
    					m_Return = constructionPhase;
    					PauseGame ();
    				if (m_CurrentPhase == GamePhasesEnum.Attack &&
         		m_Phases [phase] is AttackPhase) 
    					m_Phases [phase].enabled = true;
    					previousPhase = GamePhasesEnum.Attack;
    					previousPhaseSwitch = GamePhasesEnum.Attack;
    					attackPhase = true;
    					m_Return = attackPhase;
    					PauseGame ();
    				if (m_CurrentPhase == GamePhasesEnum.EndGame &&
         		m_Phases [phase] is EndGameScreen) 
    					m_Phases [phase].enabled = true;
    					previousPhase = GamePhasesEnum.EndGame;
    					previousPhaseSwitch = GamePhasesEnum.EndGame;
    					endGame = true;
    				if (m_CurrentPhase == GamePhasesEnum.Pause &&
         		m_Phases [phase] is PausePhase) 
    					m_Phases [phase].enabled = true;
    					pausePhase = true;
    					PauseGame ();
    		m_IsDirty = false;
    //	void OnGUI ()
    //	{
    //		//Shows in the corner what phase is active. Use only in editor.
    //		GUI.Label (new Rect (32, 32, 256, 32), m_CurrentPhase.ToString ());
    //	}
    	public void SwitchPhase (GamePhasesEnum _NewPhase)
    		//What happens when a new phase is activated.
    		m_CurrentPhase = _NewPhase;
    		m_IsDirty = true; 
    		if (m_IsDirty) 
    			constructionPhase = false;
    			attackPhase = false;
    			changePhasesPhase = false;
    			endGame = false;
    	private void ResetPhases ()
    		//Resets the phase count.
    		for (int phase = 0;
      			 phase < m_Phases.Length;
    			m_Phases [phase].enabled = false;

    The phases follow each other in a specific order, ChangePhases, to Building, (to Attack) and then back to ChangePhases. Only if certain conditions are fulfilled, which are specified and each phase specific script, will the phase change to the next phase. Those specifics can be viewed below in the description of each phases. Below is a script for a phase () as and example of how phases are built.


    ChangePhases is the initial phase at the start of the game. Each new turn also starts in this phase. It resets the camera, switches over to the next player, and will stay in this phase until the player presses the "Start turn" button.


    When the Building phase starts, there will be a visual countdown, "O-ri-Go!", before the timer starts ticking down. The player has 20 seconds to shoot out all of the available ammo, or to stash it for the Attackphase. If the player runs out of time, the game will automatically switch over to ChangePhases, and it will be the other player's turn. If the player manages to shoot out all of the blocks within the timelimit, and if the player has stashed blocks, the game will switch over to the AttackPhase. If the player has not stashed anything, his/her turn will end after shooting out the last block.


    Only accessible if the gamer stashed blocks away during the BuildPhase and emptied the cannon. The only difference between the BuildingPhase and AttackPhase is that during the AttackPhase the player cannot stash, and has to shoot the blocks that he/she stashed earlier.


    This is only displayed after the last turn is finished. It works in a similar way as the pause screen.


    The pause screen itself is built as a separate phase, much like other phases. But the pause phase itself does only display the buttons of the pausemenu. The pause function itself is in the phasecontroller script,
    as it keeps track on all phases and thereby stops all functions running in the game. The time stops ticking down and all normal game functions, like shooting blocks, are disabled.
    The pause screen can be brought up at any time while playing.

    	public void ReturnFromPause ()
    		//Un-pausing returns back to the right phase. 
    		m_AudioController.MenuClick ();
    		SwitchPhase (previousPhase);
    		ResetPhases ();
    		m_Return = true;
    		pausePhase = false;
    	public void PauseGame ()
    		//Pausing the time if pausePhase is active.
    		if (pausePhase) 
    			pausePhase = true;
    			SwitchPhase (0);
    			Time.timeScale = 0;
    			Time.timeScale = 1;
    			pausePhase = false;


    Phases are the main frame of the rulework, but since the phase-system is such a large part of the game I decided to write the phase-system separately. I wrote additional functions in the game that were only activated during certain phases, but were not a part of the phases. These functions are displayed in the video below.

    Functions I wrote:

  • Player announcement + animation

  • Start turn button

  • Visual countdown ("O-ri-Go!")

  • Timer (Script)

  • Script that will change phases

  • Locking functions (Cannons)

  • Counting the amount of how many turns have been played, and how many turns are left until the game ends.

  • A more detailed walkthrough of what happens and in which order all functions for the rulework I wrote can be seen during the gameplay.

    A player announcement is seen at the top of the screen in order to show whose turn it is. At the start of a new turn, the text will enlarge to get attention, and then minimize so it won't be in the way of the player. This is handled by adjusting the size of the GUI and adjusting the X and Y values for the location.

    After a slight delay, the button to start the timer appears. The game won't continue until the button has been pressed. Certain functions for the game will be locked, like shooting the cannon. When it's pressed the button will disappear.

    "O-ri-Go!" will then appear, one syllable after another as a countdown before the timer starts. Once the last syllable is shown, the timer will start.

    At the same time, a script that reads variables from other scripts in order to determine when it should switch phase will activate. These conditions can be viewed in the flowchart below.

    When one of these conditions are fullfilled, the turn will end. The camera and timer will reset their values. A new turn begins.


    The GUI elements I wrote are meant to always appear in the same place on the screen, no matter what resolution the player chooses to play in. The same applies to all the buttons in the menus. All elements were written in such a way that I could edit their positions in the editing. Below is part of the menu script that displays some elements, to show how I wrote it.

    		titleWidth = OrigoTitleLogoTexture.width * (Screen.height*scaleOrigoLogoWidth);
    		titleHeight = OrigoTitleLogoTexture.height * (Screen.height*scaleOrigoLogo);
    		Rect m_TitleRect = new Rect(0, 0, titleWidth, titleHeight);
    		m_TitleRect.center = new Vector2(Screen.width*0.5f, Screen.height/horizontalLocation);
    		GUI.DrawTexture (m_TitleRect, OrigoTitleLogoTexture, ScaleMode.StretchToFill);
    		//GUI and button function.
    		//The four ints are X, Y, Texture width, Texture height
    		buttonWidth = QuitButtonTexture.width * (Screen.height*scaleButtonWidth);
    		buttonHeight = QuitButtonTexture.height * (Screen.height*scaleButtonHeight);
    		Rect guiRect = new Rect(0, 0, buttonWidth, buttonHeight);
    		guiRect.center = new Vector2(Screen.width*0.5f, Screen.height/verticalLocation2);


    The menus work in the same way as the Phasecontroller does, minus all the extra rulework. All screens have their own script, which has an OnGUI function that displays all the buttons and information for that particular screen. Which screens a particular screen can go to is also written in the script, and the screen will not change unless a button on the screen is pressed.

    Documentation and QA

    Besides working on the prototype, we were also required to write weekly documents, like a changelog and schedule, during the production weeks. We also had documents that were constantly updated during the entire project, like the GDD. I was in charge of writing the changelogs every week, and co-writer of the GGD.

    The changelog requirements were that it would be max two pages long and contain information on all new mechanics that were implemented during the week.

    Downloadable example of a changelog:

     Changelog week 4

    For the GDD, we used Baldwin's Game Design Document template as a form on how to structure our GDD. The text was written in such a way that another person would be able to use it as either a requirement list or as a guide and be able to reconstruct out game based on the descriptions.

    The testing of the game was mostly done by me and another person outside of school, whom I sent a build of the game and a form to fill out for every bug he found at least once a week. I wrote the forms for him to fill in, and he would play the game and fill it in whenever he found any bugs.

    This was because we knew that we wouldn't have much time to test our own game for bugs and that since we were making the game, we would mostly check for bugs in functions that we made. With the time restriction set on 7 weeks, we decided to hold a focustest at the end of the fifth week. That way we would be able to have enough polish on the mechanics and time to change and add visual feedback for the player.

    Downloadable instructions on how to fill out a report and a filled out one:

     QA template

    Video of a bug in an early build submitted by QA.