Capstone Project

Engine | Unity

Team Size | Ten

Duration | 32 weeks

We created a game called Muckraker for our Capstone Project. The game is a top-down survival horror game where the player has to escape a procedurally generated warehouse containing a Hindu cult.

This 2 semester project, a culmination of all of my college coursework, improved my skills in:

  • Communication
  • Source control
  • Staying in my lane to be a good team member
  • Working with a mid-sized team

In this project I was designated the lead programmer. I am responsible for the enemy AI, the procedural generation of the levels. That and helping the other programmer when the need arises.

The game is fairly simple in design, yet difficult in implementation. The AI uses the A* pathfinding toolkit made by Arongranberg, along with my own codebase to create a simplistic yet efficient AI.

The base of the Proc Gen is a Unity Package I have created in my own time. My capstone version uses the package as a base, with changes I have made along the way.

Some of these changes include:

  • Having the first room always be the starting room.
GameObject R;
        if (room != STARTING_ROOM)
        {
            R = Instantiate(RoomTemplates[Random.Range(0, RoomTemplates.Length)], new Vector3(W / 5 + cellW * (x - 5), H / 5 + cellH * (y - 4)), Quaternion.identity, GameObject.Find("Rooms").transform);

        }
        else
        {
            R = Instantiate(StartingRoom, new Vector3(W / 5 + cellW * (x - 5), H / 5 + cellH * (y - 4)), Quaternion.identity, GameObject.Find("Rooms").transform);
        }

  • Making wall and doors programmatically.
private void MakeWalls_Doors(int room)
    {
        //X-Axis placement of rooms
        var x = room % 10;
        //Y-Axis placement of rooms
        var y = (room - x) / 10;
        //Create a new room at the certain position, i'm not sure what the paramaters actually do, but they work...
        string nearbyRooms = GetNeigbors(room);

        switch (nearbyRooms)
        {
            case "UP ":
                GameObject WallU1 = Instantiate(Wall, new Vector3(RoomsHolder[room].transform.position.x, RoomsHolder[room].transform.position.y - wallOffset), Quaternion.identity, RoomsHolder[room].transform);

                GameObject WallU2 = Instantiate(Wall, new Vector3(RoomsHolder[room].transform.position.x - wallOffset, RoomsHolder[room].transform.position.y), Quaternion.identity, RoomsHolder[room].transform);
                WallU2.transform.Rotate(new Vector3(0, 0, 90));

                GameObject WallU3 = Instantiate(Wall, new Vector3(RoomsHolder[room].transform.position.x + wallOffset, RoomsHolder[room].transform.position.y), Quaternion.identity, RoomsHolder[room].transform);
                WallU3.transform.Rotate(new Vector3(0, 0, 90));

                GameObject DU = Instantiate(Door, new Vector3(RoomsHolder[room].transform.position.x, RoomsHolder[room].transform.position.y + doorOffset), Quaternion.identity, RoomsHolder[room].transform);
                break;

//Continued for each room variation


  • Adding an exit room at the furthest room from the start.
private void MakeExitRoom()
    {
        for (int i = 0; i < RoomsHolder.Length - 1; i++)
        {
            if (RoomsHolder[i] != null)
            {
                print(RoomsHolder[i].name);
                var x = i % 10;
                var y = (i - x) % 10;

                Destroy(RoomsHolder[i]);

                RoomsHolder[i] = Instantiate(Office, new Vector3(W / 5 + cellW * (x - 5), H / 5 + cellH * (y - 4)), Quaternion.identity, GameObject.Find("Rooms").transform);

                MakeWalls_Doors(i);
                break;
            }
        }
    }

  • Adding a loading screen to hide the room generation
private IEnumerator DisableLoadingScreen()
    {
        // loop over 1 second backwards
        for (float i = 1; i >= 0; i -= Time.deltaTime)
        {
            // set color with i as alpha
            LoadingScreen.GetComponent<Image>().color = new Color(1, LoadingScreen.GetComponent<Image>().color.g,
                                                                  LoadingScreen.GetComponent<Image>().color.b, i);
            yield return null;
        }

        LoadingScreen.SetActive(false);
        GameObject.Find("Player").GetComponent<placeholder_movement>().canMove = true;
    }