[Unity] Dungeon Gunner (27) - Dungeon Builder Placing Rooms[2]

suhan0304·2024년 2월 20일
0

유니티 - Dungeon Gunner

목록 보기
27/30
post-thumbnail

Dungeon Builder Placing Rooms[1]에 이어서 작성한 코드 내용이다.

DungeonBuilder.cs

/// <summary>
/// Process rooms in the open room node queue, returning true if there are no room overlaps 
/// </summary>
private bool ProcessRoomsInOpenRoomNodeQueue(RoomNodeGraphSO roomNodeGraph, Queue<RoomNodeSO> openRoomNodeQueue, bool noRoomsOverlaps)
{
    //While room nodes in open room node queue & no room overlaps detected.
    while (openRoomNodeQueue.Count > 0 && noRoomsOverlaps == true)
    {
        // Get next room node from open room node queue.
        RoomNodeSO roomNode = openRoomNodeQueue.Dequeue();

        // Add child Nodes to queue from room node graph (with links to this parent Room) 
        foreach (RoomNodeSO childRoomNode in roomNodeGraph.GetChildRoomNodes(roomNode))
        {
            openRoomNodeQueue.Enqueue(childRoomNode);
        }

        // if the room is the entrance mark as positioned and add to room dictionary
        if (roomNode.roomNodeType.isEntrance)
        {
            RoomTemplateSO roomTemplate = GetRandomRoomTemplate(roomNode.roomNodeType);

            Room room = CreateRoomFromRoomTemplate(roomTemplate, roomNode);

            room.isPositioned = true;

            // Add room to room dictionary
            dungeonBuilderRoomDictionary.Add(room.id, room);
        }

        // else if the room type isn't an entrance
        else
        {
            // Else get parent room for node
            Room parentRoom = dungeonBuilderRoomDictionary[roomNode.parentRoomNodeIDList[0]];

            // See if room can be placed without overlaps
            noRoomsOverlaps = CanPlaceRoomWithNoOverlaps(roomNode, parentRoom);
        }
    }
}

/// <summary>
/// Get a random room template from the roomtemplatelist that matches the roomType and return it
/// (return null if no mathing room templates found).
/// </summary>
private RoomTemplateSO GetRandomRoomTemplate(RoomNodeTypeSO roomNodeType)
{
    List<RoomTemplateSO> matchingRoomTemplateList = new List<RoomTemplateSO>();

    // Loop through room template list
    foreach(RoomTemplateSO roomTemplate in roomTemplateList)
    {
        // Add matching room templates
        if (roomTemplate.roomNodeType == roomNodeType)
        {
            matchingRoomTemplateList.Add(roomTemplate);
        }
    }

    // Return null if list is zero
    if (matchingRoomTemplateList.Count == 0)
        return null;

    // Select random room template from list and return
    return matchingRoomTemplateList[UnityEngine.Random.Range(0, matchingRoomTemplateList.Count)];
}

/// <summary>
/// Attempt to place the room node in the dungeon - if room can be placed return the room, else return null
/// </summary>
private bool CanPlaceRoomWithNoOverlaps(RoomNodeSO roomNode, Room parentRoom)
{
    // initialise and assume overlap until proven otherwise.
    bool roomOverlaps = true;

    // Do while Room Overlaps - try to place against all available doorways of the parent until
    // the room is successfully placed without overlap.

    while (roomOverlaps)
    {
        // Select random unconnected available doorway for Parent
        List<Doorway> unconnectedAbailableParentDoorways = GetUnconnectedAvailableDoorways(parentRoom.doorWayList).ToList();

        if (unconnectedAbailableParentDoorways.Count == 0)
        {
            // If no more doorways to try then overlap failure.
            return false; // room overlaps
        }

        Doorway doorwayParent = unconnectedAbailableParentDoorways[UnityEngine.Random.Range(0, unconnectedAbailableParentDoorways.Count)];

        // Get a random room template for room node that is consistent with the parent door orientation
        RoomTemplateSO roomtemplate = GetRandomTemplateForRoomConsistentWithParent(roomNode, doorwayParent);
    }
}

/// <summary>
/// Get unconnected doorways
/// </summary>
private IEnumerable<Doorway> GetUnconnectedAvailableDoorways(List<Doorway> roomDoorwayList)
{
    // Loop through doorway list
    foreach (Doorway doorway in roomDoorwayList)
    {
        if (!doorway.isConnected && !doorway.isUnavailable)
        {
            yield return doorway;
        }
    }
}

/// <summary>
/// Create room based on roomTemplate and layoutNode, and return the created room
/// </summary>
private Room CreateRoomFromRoomTemplate(RoomTemplateSO roomTemplate, RoomNodeSO roomNode)
{
    // Initialise room from template
    Room room = new Room();

    room.templateID = roomTemplate.guid;
    room.id = roomNode.id;
    room.prefab = roomTemplate.prefab;
    room.lowerBounds = roomTemplate.lowerBounds;
    room.upperBounds = roomTemplate.upperBounds;
    room.spawnPositionArray = roomTemplate.spawnPositionArray;
    room.templateLowerBounds = roomTemplate.lowerBounds;
    room.templateUpperBounds = roomTemplate.upperBounds;
    room.childRoomIDList = CopyStringList(roomNode.childRoomNodeIDList);
    room.doorWayList = CopyDoorwayList(roomTemplate.doorwayList);

    // Set parnet ID for room
    if (roomNode.parentRoomNodeIDList.Count == 0) // Entrance
    {
        room.parentRoomID = "";
        room.isPreviouslyVisited = true;
    }
    else
    {
        room.parentRoomID = roomNode.parentRoomNodeIDList[0];
    }

    return room;
}

/// <summary>
/// Select a random room node graph from the list of room node graphs
/// </summary>
private RoomNodeGraphSO SelectRandomRoomNodeGraph(List<RoomNodeGraphSO> roomNodeGraphList)
{
    if (roomNodeGraphList.Count > 0)
    {
        return roomNodeGraphList[UnityEngine.Random.Range(0, roomNodeGraphList.Count)];
    }
    else
    {
        Debug.Log("No room node graphs in list");
        return null;
    }
}

private List<string> CopyStringList(List<string> oldStringList)
{
    List<string> newStringList = new List<string>();

    foreach(string stringVale in oldStringList)
    {
        newStringList.Add(stringVale);
    }

    return newStringList;
}

private List<Doorway> CopyDoorwayList(List<Doorway> oldDoorwayList)
{
    List<Doorway> newDoorwayList = new List<Doorway>();

    foreach (Doorway doorway in oldDoorwayList)
    {
        Doorway newDoorway = new Doorway();

        newDoorway.position = doorway.position;
        newDoorway.orientation = doorway.orientation;
        newDoorway.doorPrefab = doorway.doorPrefab;
        newDoorway.isConnected = doorway.isConnected;
        newDoorway.isUnavailable = doorway.isUnavailable;
        newDoorway.doorwayStartCopyPosition = doorway.doorwayStartCopyPosition;
        newDoorway.doorwayCopyTileWidth = doorway.doorwayCopyTileWidth;
        newDoorway.doorwayCopyTileHeight = doorway.doorwayCopyTileHeight;

        newDoorwayList.Add(newDoorway);
    }

    return newDoorwayList;
}

업데이트

  • 24.02.25. Code Update
profile
Be Honest, Be Harder, Be Stronger

0개의 댓글