Losowe tworzenie labiryntu

Programowanie w Unity.

Losowe tworzenie labiryntu

Postprzez WiksterRvN » 24 Lis 2019, 15:37

Cześć, otóż mój problem wygląda w ten spobób:
Mam 3 prefaby: Start, Lcorridor i Tcorridor.
Skrypt od generowania ich powinien zapobiegać stawianiu kolejnego pokoju w miejscu gdzie jeden już jest, z jakiegoś powodu i tak się tak dzieje.
Na zdjęciu powinno być to widoczne

Kod: Zaznacz wszystko
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace HideAndSeek
{
    public class LevelGenerator : MonoBehaviour
    {
        #region Variables

        public Room startRoomPref, endRoomPrefab;
        public List<Room> roomsPrefs = 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;

        #endregion

        #region Monobehaviour Callbacks

        void Start()
        {
            roomLayerMask = LayerMask.GetMask("Room");
            StartCoroutine("GenerateLevel");
        }

        #endregion

        #region Methods

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

            yield return startup;


            //Placing StartRoom
            PlaceStartRoom();
            yield return interval;

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

            for (int i = 0; i < iterations; i++)
            {
                //Place Random room from list
                PlaceRoom();
                yield return interval;
            }

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

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

            //Test
            yield return new WaitForSeconds(5);
            ResetLevelGenerator();
        }
       
        void PlaceStartRoom()
        {
            //Debug.Log("StartRoom Placed");
            //Instantiate
            startRoom = Instantiate(startRoomPref) as StartRoom;
            startRoom.transform.parent = this.transform;

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

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

        }

        void PlaceRoom()
        {
            //Debug.Log("Placed Random Room from list");
            //Instantiating
            Room currentRoom = Instantiate(roomsPrefs[Random.Range(0, roomsPrefs.Count)]) as Room;
            currentRoom.transform.parent = this.transform;

            //Create Doorways list to loop over

            List<DoorWay> allAvailableDoorways = new List<DoorWay>(availableDoorWays);
            List<DoorWay> currentRoomDoorways = new List<DoorWay>();
            AddDoorwaysToList(currentRoom, ref currentRoomDoorways);

            //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 currentRoomDoorways)
                {
                    //Position Room
                    PositionRoomAtDoorway(ref currentRoom, currentDoorway, 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);

                    availableDoorway.gameObject.SetActive(false);
                    availableDoorWays.Remove(availableDoorway);
                    //Exit loop if room has been placed
                    break;
                }
                //Exit loop if room has been placed
                if (roomPlaced == true)
                    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 postion
            room.transform.position = Vector3.zero;
            room.transform.rotation = Quaternion.identity;

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

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

        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("EndRoom Placed");
        }

        void AddDoorwaysToList(Room room, ref List<DoorWay> list)
        {
            foreach (DoorWay doorway in room.doorways)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    DoorWay temp = list[i];
                    int randomIndex = Random.Range(i, list.Count);
                    list[i] = list[randomIndex];
                    list[randomIndex] = temp;
                }


                int r = Random.Range(0, list.Count);
                list.Insert(r, doorway);
            }
        }

        void ResetLevelGenerator()
        {
            Debug.Log("Reset Lvl");

            StopCoroutine("GenerateLevel");

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

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

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

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

            //Restart Corountine
            StartCoroutine("GenerateLevel");
        }

        #endregion

    }
}
WiksterRvN
 
Posty: 8
Rejestracja: 23 Lis 2018, 17:49
Has thanked: 0 time
Been thanked: 0 time

Re: Losowe tworzenie labiryntu

Postprzez Hostur » 24 Lis 2019, 17:11

Analizowanie tego kodu na sucho to słaby pomysł. Czegoś nie rozumiem, po kodzie wydaje się, że wiesz co robisz więc czemu po prostu nie przedebugujesz tego step by step w visualu? Znasz warunki w których pokój się stworzy, oraz gdzie się stworzy postaw kilka debug pointów i w 5 minut to rozwikłasz
Hostur
 
Posty: 758
Rejestracja: 05 Sie 2015, 07:36
Has thanked: 0 time
Been thanked: 0 time


Wróć do Skrypty

Kto jest na forum

Użytkownicy przeglądający to forum: Brak zarejestrowanych użytkowników oraz 3 gości

cron