Project Overview

DunGen is a unity asset tool that I was tasked with enhancing to increase its flexibility by expanding its options and refining its limitations.

Tool Info

Roles: Programmer

Date: May 2020 - June 2020

Team Size: 2 programmers

Engine: Unity

Version Control: Git

Code Language: C#

My Role

I worked on this project while interning at House of How. Me and another intern was tasked with generating Minecraft parkour maps by improving the Unity tool DunGen to give more creative freedom to the game designers using it.

Collider bounds

DunGen already had basic boundary restrictions in place, but I was tasked with enhancing this system by creating a new restriction rule. Scene colliders would now be able to define the restricted area, allowing the dungeon to generate tiles only within those bounds. This improvement enabled the generation of tiles within multiple boxes and more intricate shapes by simply adjusting the colliders.

dungencolliderbounds

The restriction can find any collider but will only use the bounds for said collider. Since unitys bounds is always represented as a box that means the tiles can be generated outside of the collider if the tile is still within the collider bounds.

dungencolliderboundscirlce
dungencolliderboundscirlcesquare

//Find all the colliders that are meant to be the restriction area.
//These have to be on a certain layer.
List FindGameObjectsWithLayer(int layer) 
  { 
    GameObject[] goArray = GameObject.FindObjectsOfType(typeof(GameObject)) as GameObject[];
    List goList = new List(); 
    for (int i = 0; i < goArray.Length; i++) 
    { 
        if (goArray[i].layer == layer) 
        goList.Add(goArray[i]); 
    } 
    if (goList.Count == 0) 
        return null; 

    return goList; 
}

//Do collision check here with all colliders on layer RestrictColliderBounds
if (RestrictDungeonToColliderBounds && DungeonRestrictColliders != null && DungeonRestrictColliders.Count > 0 && TempRestrictToColliderBounds)
{
    int containedIn = 0;
    foreach (GameObject collider in DungeonRestrictColliders)
    {
        Collider restrictCollider = collider.GetComponent();
        Bounds newProxyBounds = restrictCollider.bounds;
        if (newProxyBounds.Contains(proxyBounds))
            containedIn++;
    }

    if(containedIn <= 0)
    {
        Debug.LogWarning("Tile was placed outside of restriction. Removing and retrying");
        return TilePlacementResult.OutOfBounds;
    }
}
            

Repeat modes

Repeat modes in DunGen is the rules for how a tile is allowed to generate e.g "Allow tiles to be placed in a row". To extend these options I implemented two more repeat modes for tiles.

Allow X tiles in a row

Allow X tiles in a row makes sure that only x tiles can be placed in a row.

Allow X tiles maximum to generate in a dungeon

Allow X tiles maximum does not generate any more of that tile once X amount has been placed.

X can be set separetely for each tile using repeat modes where relevant by using the custom tile inspector fields that was added.

dungencolliderbounds

In the picture above, the red tiles are set to "allow maximum 3 tiles in a row" the yellow to "allow 4 maximum in dungeon" and the green ones follow the standard "allow anywhere". Both tile types can still be generated less than the rules say.

switch (repeatMode)
{
    //Standard
    case TileRepeatMode.Allow:							
        allowTile = true;
        break;
    //Allow X tiles in a row
    case TileRepeatMode.AllowXInRow:
        if (potentialNextTile.PrefabTile.AllowedAmount <= 0)
            allowTile = false;
        else if (UsedAmounts < potentialNextTile.PrefabTile.AllowedAmount)
            allowTile = true;
        else
            allowTile = false;
        break;
    //Allow X total of tile in dungeon
    case TileRepeatMode.AllowXTotalOfTile:
        if (potentialNextTile.PrefabTile.AllowedAmount <= 0)
            allowTile = false;
        else if (potentialNextTile.PrefabTile.TotalAmountPlaced < potentialNextTile.PrefabTile.AllowedAmount)
            allowTile = true;
        else
            allowTile = false;
        break;
    //Standard
    case TileRepeatMode.DisallowImmediate:
        allowTile = !isImmediateRepeat;
        break;
     //Standard
    case TileRepeatMode.Disallow:
        allowTile = !proxyDungeon.AllTiles.Where(t => t.Prefab == potentialNextTile.Prefab).Any();
        break;
    default:
        throw new NotImplementedException("TileRepeatMode " + repeatMode + " is not implemented");
}

//Reset UsedAmounts & ForceXInRow if new tile != last tile
if (lastTile != null && (createdTile.Prefab != lastTile.Prefab))
    UsedAmounts = 0;

//Add to counters if neccessary
switch (createdTile.PrefabTile.RepeatMode)
{
    case TileRepeatMode.AllowXInRow:
        UsedAmounts++;
        break;
    case TileRepeatMode.AllowXTotalOfTile:
        createdTile.PrefabTile.TotalAmountPlaced++;
        break;
    default:
        break;
}