Esempio n. 1
0
        /// <summary>
        /// Generate a new randomised level. This is an expensive method and
        /// should be called infrequently.
        /// </summary>
        /// <param name="startingRoomPrefab">
        /// A room prefab to use as the starting room.
        /// </param>
        /// <param name="parent">
        /// The transform of the parent gameobject, the instantiated rooms
        /// comprising the level will be a child of the given transform.
        /// </param>
        /// <param name="depth">
        /// The depth of the level to be generated. Depth should be a value
        /// larger than zero. A larger depth value will result in a larger
        /// level being generated.
        /// </param>
        /// <param name="disableChildRooms">
        /// Whether or not child-rooms (any room that is not the starting room)
        /// should be initially disabled. Normally rooms should only be enabled
        /// when the player enters them however it is sometimes useful for
        /// debugging to have all rooms enabled.
        /// </param>
        /// <returns>
        /// Returns the fully instantiated and initialized starting room. All
        /// rooms in the level are accessible via the starting room through the
        /// connected doors in each room which form a "level graph" of
        /// interconnected rooms.
        /// </returns>
        public static GameObject GenerateLevel(GameObject startingRoomPrefab, Transform parent, int depth, int?seed = null, bool disableChildRooms = true)
        {
            // NOTE: Due to how level generation is implemented, there is
            // always the small possibility that despite best efforts a
            // guaranteed room wont be able to find a viable position to spawn
            // while upholding all of the required constraints.
            //
            // To ensure the guaranteed rooms are included in the level, the
            // level will re-generate itself if it detects that not all the
            // guaranteed rooms were spawned.

            // set level generation seed
            if (!seed.HasValue)
            {
                seed = (int)DateTime.Now.Ticks;
            }
            UnityEngine.Random.InitState(seed.Value);
            Log.Info($"Generating level with depth {Log.Cyan(depth)} and seed {Log.Cyan(seed.Value)}", LogCategory.LevelGeneration);

            const int attempts = 25;

            for (int i = 0; i < attempts; i++)
            {
                RoomGrid   grid   = new RoomGrid(depth);
                Vector2Int centre = new Vector2Int(0, 0);
                GameObject startingRoomInstance      = InstanceFactory.InstantiateRoom(startingRoomPrefab, parent, centre);
                RoomConnectionBehaviour startingRoom = startingRoomInstance.GetComponent <RoomConnectionBehaviour>();
                grid.Add(startingRoom);
                SpawnChildRooms(startingRoom, parent, grid, depth, disableChildRooms);

                bool levelVerfied = grid.Verify();
                if (!levelVerfied)
                {
                    Log.Warning($"Generated level did not pass verification check. Regenerating... (attempt #{i+1})", LogCategory.LevelGeneration);
                    foreach (Transform childTransform in parent.transform)
                    {
                        GameObject.Destroy(childTransform.gameObject);
                    }
                    continue;
                }

                return(startingRoomInstance);
            }

            throw new Exception("GenerateLevel failed. This is likely due to an invalid SpawnProbability configuration.");
        }