I am having problems with my procedural generation script

The errors include:
Assets\LevelBuilder.cs(109,46): error CS1503: Argument 2: cannot convert from ‘System.Collections.Generic.List’ to ‘Doorway’

Assets\LevelBuilder.cs(122,22): error CS1061: ‘Doorway’ does not contain a definition for ‘GameObject’ and no accessible extension method ‘GameObject’ accepting a first argument of type ‘Doorway’ could be found (are you missing a using directive or an assembly reference?)

Assets\LevelBuilder.cs(125,25): error CS1061: ‘List’ does not contain a definition for ‘GameObject’ and no accessible extension method ‘GameObject’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)

Assets\LevelBuilder.cs(149,9): error CS1061: ‘Room’ does not contain a definition for ‘transfom’ and no accessible extension method ‘transfom’ accepting a first argument of type ‘Room’ could be found (are you missing a using directive or an assembly reference?)

Assets\LevelBuilder.cs(152,47): error CS1061: ‘Doorway’ does not contain a definition for ‘eulerAngles’ and no accessible extension method ‘eulerAngles’ accepting a first argument of type ‘Doorway’ could be found (are you missing a using directive or an assembly reference?)

Assets\LevelBuilder.cs(153,43): error CS1061: ‘Doorway’ does not contain a definition for ‘eulerAngles’ and no accessible extension method ‘eulerAngles’ accepting a first argument of type ‘Doorway’ could be found (are you missing a using directive or an assembly reference?)

Assets\LevelBuilder.cs(156,58): error CS1955: Non-invocable member ‘Quaternion’ cannot be used like a method.

Assets\LevelBuilder.cs(163,7): error CS0161: ‘LevelBuilder.CheckRoomOverlap(Room)’: not all code paths return a value

This is my script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LevelBuilder : MonoBehaviour
{
    public Room startRoomPrefab, endRoomPrefab;
    public List<Room> roomPrefabs = new List<Room> ();
    public Vector2 iterationRange = new Vector2 (3, 10);

    List<Doorway> availableDoorways = new List<Doorway> ();
   
    StartRoom startRoom;
    EndRoom endRoom;
    List<Room> placedRooms = new List<Room> ();

    LayerMask roomLayerMask;

    /// <summary>
    /// Start is called on the frame when a script is enabled just before
    /// any of the Update methods is called the first time.
    /// </summary>
    void Start()
    {
        roomLayerMask = LayerMask.GetMask ("Room");
        StartCoroutine ("GenerateLevel");
    }

    IEnumerator GenerateLevel ()
    {
        WaitForSeconds startup = new WaitForSeconds (1);
        WaitForFixedUpdate interval = new WaitForFixedUpdate();

        yield return startup;

        //place start room
        PlaceStartRoom();
        yield return interval;

        //Random iterations
        int iterations = Random.Range((int)iterationRange.x, (int)iterationRange.y);

        for(int i = 0; i < iterations; i++)
        {
           PlaceRoom();
           yield return interval;
        }

        //Place end room
        PlaceEndRoom();
        yield return interval;

        //Level generation finished
        Debug.Log("Level generation finished");

        yield return new WaitForSeconds (3);
        ResetLevelGenerator();
       
    }

    void PlaceStartRoom()
    {
       //Instantiate start room
       startRoom = Instantiate(startRoomPrefab) as StartRoom;
       startRoom.transform.parent = this.transform;

       //Get doorways from current room and add them randomly to the list of available doorways
       AddDoorwaysToList(startRoom, ref availableDoorways);

       //Position room
       startRoom.transform.position = Vector3.zero;
       startRoom.transform.rotation = Quaternion.identity;


    }

    void AddDoorwaysToList(Room room, ref List<Doorway> list)
    {
      foreach (Doorway doorway in room.doorways)
      {
          int r = Random.Range (0, list.Count);
          list.Insert (r, doorway);
      }
    }

    void PlaceRoom()
    {
        //Instantiate room
        Room currentRoom = Instantiate(roomPrefabs[Random.Range(0, roomPrefabs.Count)]) as Room;
        currentRoom.transform.parent = this.transform;

        //Create doorway lists to loop over
        List<Doorway> allAvailableDoorways = new List<Doorway> (availableDoorways);
        List<Doorway> currentDoorways = new List<Doorway> ();
        AddDoorwaysToList(currentRoom, ref currentDoorways);

        //Get doorways from current room and add them randomly to the list of available doorways
        AddDoorwaysToList(currentRoom, ref availableDoorways);

        bool roomPlaced = false;

        //try all available doorways
        foreach (Doorway availableDoorway in allAvailableDoorways)
        {
              //try all available doorways in current room
              foreach (Doorway currentDoorway in currentDoorways)
              {
                  //Position room
                  PositionRoomAtDoorway(ref currentRoom, currentDoorways, availableDoorway);

                  //Check room overlaps
                  if(CheckRoomOverlap(currentRoom))
                  {
                      continue;
                  }

                  roomPlaced = true;
                  //Add room to list
                  placedRooms.Add(currentRoom);

                  //Remove occupied doorways
                  currentDoorway.GameObject.SetActive(false);
                  availableDoorways.Remove(currentDoorway);

                  availableDoorways.GameObject.SetActive(false);
                  availableDoorways.Remove(availableDoorway);

                  //Exit loop if room has been placed
                  break;
              }
              //Exit loop if room has been placed
              if(roomPlaced)
              {
                  break;
              }
        }
        //Room couldn't be placed. Restart generator and try again
        if(!roomPlaced)
        {
            Destroy(currentRoom.gameObject);
            ResetLevelGenerator();
        }
    }
   
    void PositionRoomAtDoorway(ref Room room, Doorway roomDoorway, Doorway targetDoorway)
    {
      //Reset room position and rotation
      room.transform.position = Vector3.zero;
      room.transfom.rotation = Quaternion.identity;

      //Rotate room to match previous doorway orientation
      Vector3 targetDoorwayEuler = targetDoorway.eulerAngles;
      Vector3 roomDoorwayEuler = roomDoorway.eulerAngles;
      float deltaAngle = Mathf.DeltaAngle(roomDoorwayEuler.y, targetDoorwayEuler.y);
      Quaternion currentRoomTargetRotation = Quaternion.AngleAxis(deltaAngle, Vector3.up);
      room.transform.rotation = currentRoomTargetRotation * Quaternion(0, 180f, 0);

      //Position room
      Vector3 roomPositionOffset = roomDoorway.transform.position - room.transform.position;
      room.transform.position = targetDoorway.transform.position - roomPositionOffset;
    }

    bool CheckRoomOverlap(Room room)
    {
      Bounds bounds = room.RoomBounds;
      bounds.Expand (-0.1f);

      Collider[] colliders = Physics.OverlapBox(bounds.center, bounds.size/2, room.transform.rotation, roomLayerMask);
      if(colliders.Length > 0)
      {
          //ignore collisions with current room
          foreach (Collider c in colliders)
          {
             if(c.transform.parent.gameObject.Equals(room.gameObject))
             {
                 continue;
             } else {
                 Debug.LogError("Overlap detected");
                 return true;
             }
             return false;
          }
      }
    }
    //{

    //}
    void PlaceEndRoom()
    {
        Debug.Log("Place end room");
    }

    void ResetLevelGenerator()
    {
        Debug.LogError("Reset level generator");

        StopCoroutine ("GenerateLevel");

        //Delete all rooms
        if(startRoom)
        {
            Destroy (startRoom.gameObject);
        }

        if(endRoom)
        {
            Destroy (endRoom.gameObject);
        }

        foreach (Room room in placedRooms)
        {
            Destroy (room.gameObject);
        }

        //Clear lists
        placedRooms.Clear();
        availableDoorways.Clear();

        //Reset coroutine
        StartCoroutine ("GenerateLevel");
    }
}

Most of this is really easy stuff if you read the error message.

For example, in line 109 you pass ‘currentDoorways’, which is a List to a method ‘PositionRoomAtDoorway’, which expects a Doorway, instead of a List, as an argument there. So obviously it does not know what to do with that.

Some other things are simply typos. Like in the second error, you mean gameObject (the shortkey to the GameObject instance a component is attached to), instead of GameObject (the type).

Did you write this code yourself? If you did, i highly doubt you could not handle these errors. If you did not, simply look at whereever you got the code from and copy it more accurately.

1 Like

Okay, how did you get so far with such grievous errors? Are you just typing this in from somewhere else? Did you get all of it?? It’s not something where a few extra keystrokes will fix it all!!!

I’ll just address a few of them:

You’re passing a list of doorways into something that wants ONE doorway. What are you trying to do?

In Unity, accessing the .eulerAngles property usually means you want the Transform Component. Does your Doorway have a Transform? If so, you need to access the .transform shortcut to get at eulerAngles.

This is just basic C#. Return a value.

For the first one, I believe you should be passing in ‘currentDoorway’ rather than ‘currentDoorways’.

At least some of the rest of them are probably due to a problem with the Doorway class. It looks like this code expects Doorway to be a MonoBehaviour, and evidently it isn’t. (You may be missing the : MonoBehaviour part of the line near the top of the Doorway class file)

The line 156 one should be Quaternion.Euler(…), not just Quaternion(…)

Line 163: As it says, not all code paths return a value, and they all have to. Imagine that “colliders” is empty - the code would reach the end of the function without returning anything, which the compiler isn’t able to make sense out of. You probably just want a return false; at the end of that function.

1 Like

The doorway script does have : MonoBehaviour but I’m pretty sure that the tutorial I followed left it empty so I did the same