Forum begins after the advertisement:


[Part 6] Trying to spawn the player in a randomly generated map

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 6] Trying to spawn the player in a randomly generated map

Viewing 13 posts - 16 through 28 (of 28 total)
  • Author
    Posts
  • #15856
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you print the current wave count in SpawnEnemies() and show me what you get in the Console?

    void SpawnEnemies()
    {
        print("current wave count: " + currentWaveCount);
        // Check if the minimum number of enemies in the wave have been spawned
        if (waves[currentWaveCount].spawnCount < waves[currentWaveCount].waveQuota && !maxEnemiesReached)
        {
            // Spawn each type of enemy until the quota is filled
            foreach (var enemyGroup in waves[currentWaveCount].enemyGroups)
            {
                // Check if the minimum number of this type have been spawned
                if (enemyGroup.spawnCount < enemyGroup.enemyCount)
                {
                    // Limit the number of enemies that can be spawned at once
                    if (enemiesAlive >= maxEnemiesAllowed)
                    {
                        maxEnemiesReached = true;
                        return;
                    }
    
                // Get a random position from the spawnPositions list for spawning the enemy
                Vector3 randomSpawnPoint = spawnPositions[Random.Range(0, spawnPositions.Count)];
                Instantiate(enemyGroup.enemyPrefab, randomSpawnPoint, Quaternion.identity);
    
                enemyGroup.spawnCount++;
                waves[currentWaveCount].spawnCount++;
                enemiesAlive++;
            }
        }
    }
    
    if (enemiesAlive < maxEnemiesAllowed)
    {
        maxEnemiesReached = false;
    }

    }

    #15858
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    doesn’t look like it even prints that,

    View post on imgur.com

    i also put in a screenshot of the wavespawner while the game is running

    #15860
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    It seems like your error is caused by a WalkerGenerator script. That isn’t a script in our series, but you can post it here and I’ll have a look.

    #15861
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    yea that is from another youtuber, i worked on this game with another friend and he got that from another youtuber.
    its a long script, i’m sorry for that.
    thankyou for the help you’re a lifesaver

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

    public class WalkerGenerator : MonoBehaviour { public enum TileType { Empty, Floor, Wall }

    public int mapWidth = 60;
    public int mapHeight = 60;
    public int roomCount = 10;
    public int minRoomSize = 5;
    public int maxRoomSize = 15;
    
    public Tilemap tileMap;
    public Tilemap coldiertile;
    public Tile floorTile;
    public Tile wallTile;
    
    public Tile topBotRight;
    public Tile topBotLeft;
    public Tile botLeftRight;
    public Tile topLeftRight;
    public Tile botWallTile;
    public Tile topWallTile;
    public Tile rightWallTile;
    public Tile leftWallTile;
    public Tile topBotTile;
    public Tile leftRightTile;
    public Tile rightBot;
    public Tile rightTop;
    public Tile leftBot;
    public Tile leftTop;
    
    public GameObject playerPrefab;
    public GameObject chestPrefab;
    public GameObject portalPrefab;
    public GameObject[] decorationPrefabs;
    
    public CameraMovement cameraMovement;
    
    public List<RectInt> rooms;
    private TileType[,] map;
    private bool portalSpawned = false;
    
    public EnemySpawner enemySpawner;
    
    void Start()
    {
        InitializeGrid();
    }
    
    public void InitializeGrid()
    {
        map = new TileType[mapWidth, mapHeight];
        rooms = new List<RectInt>();
    
        CreateRooms();
        CreateCorridors();
        CreateWalls();
        ClearExistingObjects();
        StartCoroutine(SpawnObjectsCoroutine());
    }
    
    private void CreateRooms()
    {
        for (int i = 0; i < roomCount; i++)
        {
            int width = Random.Range(minRoomSize, maxRoomSize);
            int height = Random.Range(minRoomSize, maxRoomSize);
            int x = Random.Range(1, mapWidth - width - 1);
            int y = Random.Range(1, mapHeight - height - 1);
    
            RectInt newRoom = new RectInt(x, y, width, height);
    
            bool roomIntersects = false;
            foreach (RectInt room in rooms)
            {
                if (newRoom.Overlaps(room))
                {
                    roomIntersects = true;
                    break;
                }
            }
    
            if (!roomIntersects)
            {
                rooms.Add(newRoom);
                for (int j = x; j < x + width; j++)
                {
                    for (int k = y; k < y + height; k++)
                    {
                        map[j, k] = TileType.Floor;
                    }
                }
            }
        }
    }
    
    private void CreateCorridors()
    {
        for (int i = 0; i < rooms.Count - 1; i++)
        {
            Vector2Int pointA = new Vector2Int(rooms[i].x + rooms[i].width / 2, rooms[i].y + rooms[i].height / 2);
            Vector2Int pointB = new Vector2Int(rooms[i + 1].x + rooms[i + 1].width / 2, rooms[i + 1].height / 2);
    
            while (pointA != pointB)
            {
                if (pointA.x != pointB.x)
                {
                    if (pointA.x < pointB.x) pointA.x++;
                    else pointA.x--;
                }
                else if (pointA.y != pointB.y)
                {
                    if (pointA.y < pointB.y) pointA.y++;
                    else pointA.y--;
                }
    
                map[pointA.x, pointA.y] = TileType.Floor;
            }
        }
    }
    
    private void CreateWalls()
    {
        coldiertile.ClearAllTiles();
        tileMap.ClearAllTiles();
    
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (map[x, y] == TileType.Floor)
                {
                    for (int dx = -1; dx <= 1; dx++)
                    {
                        for (int dy = -1; dy <= 1; dy++)
                        {
                            int newX = x + dx;
                            int newY = y + dy;
    
                            if (newX >= 0 && newY >= 0 && newX < mapWidth && newY < mapHeight && map[newX, newY] == TileType.Empty)
                            {
                                map[newX, newY] = TileType.Wall;
                            }
                        }
                    }
                }
            }
        }
    
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (map[x, y] == TileType.Wall)
                {
                    Tile tileToPlace = DetermineWallTile(x, y);
                    coldiertile.SetTile(new Vector3Int(x, y, 0), tileToPlace);
                }
                else if (map[x, y] == TileType.Floor)
                {
                    tileMap.SetTile(new Vector3Int(x, y, 0), floorTile);
                }
            }
        }
    }
    
    private Tile DetermineWallTile(int x, int y)
    {
        bool left = x > 0 && map[x - 1, y] == TileType.Floor;
        bool right = x < mapWidth - 1 && map[x + 1, y] == TileType.Floor;
        bool top = y < mapHeight - 1 && map[x, y + 1] == TileType.Floor;
        bool bottom = y > 0 && map[x, y - 1] == TileType.Floor;
    
        bool leftWall = x > 0 && map[x - 1, y] == TileType.Wall;
        bool rightWall = x < mapWidth - 1 && map[x + 1, y] == TileType.Wall;
        bool bottomWall = y > 0 && map[x, y - 1] == TileType.Wall;
        bool topWall = y < mapHeight - 1 && map[x, y + 1] == TileType.Wall;
    
        if (left && top && bottom) return topBotRight;
        if (left && top && right) return topBotLeft;
        if (bottom && left && right) return botLeftRight;
        if (top && left && right) return topLeftRight;
    
        if (right && bottom) return rightTop;
        if (right && top) return rightBot;
        if (left && bottom) return leftTop;
        if (left && top) return leftBot;
    
        if (right && left) return leftRightTile;
        if (top && bottom) return topBotTile;
    
        if (top) return botWallTile;
        if (bottom) return topWallTile;
    
        if (right) return rightWallTile;
        if (left) return leftWallTile;
    
        if (rightWall && bottomWall) return null;
        if (leftWall && bottomWall) return null;
        if (leftWall && topWall) return null;
        if (rightWall && topWall) return null;
    
        return wallTile;
    }
    
    private void ClearExistingObjects()
    {
        Debug.Log("Clearing existing objects...");
        foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Player"))
        {
            Destroy(obj);
            Debug.Log("Destroyed a player object.");
        }
    
        foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Chest"))
        {
            Destroy(obj);
        }
    
        foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Portal"))
        {
            Destroy(obj);
        }
    
        foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Decoration"))
        {
            Destroy(obj);
        }
    }
    
    public IEnumerator SpawnObjectsCoroutine()
    {
        Debug.Log("Starting SpawnObjectsCoroutine...");
        ClearExistingObjects();
        yield return new WaitForSeconds(0.5f);
        yield return StartCoroutine(SpawnPortal());
        yield return new WaitForSeconds(0.5f);
        yield return StartCoroutine(SpawnChests());
        yield return new WaitForSeconds(0.5f);
        InitializeEnemySpawner();
    
        yield return new WaitForSeconds(0.5f);
        yield return StartCoroutine(SpawnDecorations());
    }
    
    public void SpawnPlayer() 
    {
        if (playerPrefab == null)
        {
            Debug.LogError("Player prefab is not assigned.");
            return;
        }
    
        print("SpawnPlayer() called");
        List<Vector3Int> floorTiles = new List<Vector3Int>();
    
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (map[x, y] == TileType.Floor)
                {
                    floorTiles.Add(new Vector3Int(x, y, 0));
                }
            }
        }
    
        if (floorTiles.Count == 0)
        {
            Debug.LogError("No floor tiles available for spawning objects.");
            return;
        }
    
        Vector3Int playerSpawnPos = floorTiles[Random.Range(0, floorTiles.Count)];
        Debug.Log($"Player spawn position: {playerSpawnPos}");
    
        // Instantiate the player prefab
        GameObject playerObj = Instantiate(playerPrefab, new Vector3(playerSpawnPos.x + 0.5f, playerSpawnPos.y + 0.5f, 0), Quaternion.identity);
        Debug.Log($"Player instance created at position: {playerObj.transform.position}");
    
        // Attach camera to the new player instance
        if (cameraMovement != null)
        {
            cameraMovement.target = playerObj.transform;
            cameraMovement.SnapToTarget();
        }
        else
        {
            Debug.LogError("CameraMovement script is not assigned in the WalkerGenerator.");
        }
    }
    
    private void InitializeEnemySpawner()
    {
        if (enemySpawner == null)
        {
            Debug.LogError("EnemySpawner is not assigned!");
            return;
        }
    
        List<Vector3> floorPositions = new List<Vector3>();
    
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; x < mapHeight; y++)
            {
                if (map[x, y] == TileType.Floor)
                {
                    floorPositions.Add(new Vector3(x + 0.5f, y + 0.5f, 0));
                }
            }
        }
    
        if (floorPositions.Count == 0)
        {
            Debug.LogError("No floor tiles available for spawning enemies.");
            return;
        }
    
        enemySpawner.SetSpawnPoints(floorPositions);
        enemySpawner.InitializeSpawner();
    }
    
    private IEnumerator SpawnPortal()
    {
        Debug.Log("Spawning portal...");
        if (portalSpawned)
        {
            Debug.LogWarning("A portal already exists in the scene.");
            yield break;
        }
    
        List<Vector3Int> floorTiles = new List<Vector3Int>();
    
        // Get all floor tiles within rooms
        foreach (RectInt room in rooms)
        {
            for (int x = room.x; x < room.x + room.width; x++)
            {
                for (int y = room.y; y < room.y + room.height; y++)
                {
                    floorTiles.Add(new Vector3Int(x, y, 0));
                }
            }
        }
    
        if (floorTiles.Count == 0)
        {
            Debug.LogError("No suitable floor tiles available for spawning portal.");
            yield break;
        }
    
        Vector3Int portalSpawnPos = floorTiles[Random.Range(0, floorTiles.Count)];
        Instantiate(portalPrefab, new Vector3(portalSpawnPos.x + 0.5f, portalSpawnPos.y + 0.5f, 0), Quaternion.identity);
        portalSpawned = true;
        Debug.Log($"Portal spawn position: {portalSpawnPos}");
    }
    
    private IEnumerator SpawnChests()
    {
        Debug.Log("Spawning chests...");
        List<Vector3Int> floorTiles = new List<Vector3Int>();
    
        // Get all floor tiles within rooms
        foreach (RectInt room in rooms)
        {
            for (int x = room.x; x < room.x + room.width; x++)
            {
                for (int y = room.y; y < room.y + room.height; y++)
                {
                    floorTiles.Add(new Vector3Int(x, y, 0));
                }
            }
        }
    
        if (floorTiles.Count == 0)
        {
            Debug.LogError("No suitable floor tiles available for spawning chests.");
            yield break;
        }
    
        // Adjust the range to 2-4 chests
        int chestCount = Random.Range(2, 5);
        List<Vector3Int> usedPositions = new List<Vector3Int>();
    
        for (int i = 0; i < chestCount; i++)
        {
            Vector3Int chestSpawnPos;
            int attempts = 0;
    
            do
            {
                chestSpawnPos = floorTiles[Random.Range(0, floorTiles.Count)];
                attempts++;
            } while (usedPositions.Exists(pos => Vector3Int.Distance(pos, chestSpawnPos) < 3) && attempts < 100);
    
            if (attempts < 100)
            {
                Instantiate(chestPrefab, new Vector3(chestSpawnPos.x + 0.5f, chestSpawnPos.y + 0.5f, 0), Quaternion.identity);
                usedPositions.Add(chestSpawnPos);
                Debug.Log($"Chest spawn position: {chestSpawnPos}");
            }
            else
            {
                Debug.LogWarning("Could not find a suitable position for a chest after 100 attempts.");
            }
        }
    }
    
    private IEnumerator SpawnDecorations()
    {
        Debug.Log("Spawning decorations...");
        List<Vector3Int> floorTiles = new List<Vector3Int>();
    
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if (map[x, y] == TileType.Floor)
                {
                    floorTiles.Add(new Vector3Int(x, y, 0));
                }
            }
        }
    
        if (floorTiles.Count == 0)
        {
            Debug.LogError("No floor tiles available for spawning objects.");
            yield break;
        }
    
        int decorationCount = Random.Range(5, 16);
    
        for (int i = 0; i < decorationCount; i++)
        {
            Vector3Int decorationSpawnPos = floorTiles[Random.Range(0, floorTiles.Count)];
            GameObject decorationPrefab = decorationPrefabs[Random.Range(0, decorationPrefabs.Length)];
            Instantiate(decorationPrefab, new Vector3(decorationSpawnPos.x + 0.5f, decorationSpawnPos.y + 0.5f, 0), Quaternion.identity);
            Debug.Log($"Decoration spawn position: {decorationSpawnPos}");
        }
    }

    }

    #15865
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you show me which line of the WalkerGenerator script has the issue? You can find it on the Console message.

    #15867
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    yes ofcourse,

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        Debug.Log("OnSceneLoaded called for scene: " + scene.name);
    
    WalkerGenerator walkerGenerator = FindFirstObjectByType<WalkerGenerator>();
    if (walkerGenerator != null)
    {
        walkerGenerator.SpawnPlayer();
        Debug.Log("WalkerGenerator found and SpawnPlayer called.");
    }
    else
    {
        Debug.LogError("WalkerGenerator not found in the scene.");
    }
    
    EnemySpawner enemySpawner = FindFirstObjectByType<EnemySpawner>();
    if (enemySpawner != null)
    {
        enemySpawner.InitializeSpawner();
    }
    else
    {
        Debug.LogError("EnemySpawner not found in the scene.");
    }

    }

    #15868
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    This doesn’t seem like the code that has the error.

    #15902
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    when i click on the highlighted error message it takes me too my sceneloader script instead of the walkergenerator script

    all the other errors also take me to other scripts than walkergenerator

    View post on imgur.com

    #15903
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    The first error says to add a WalkerGenerator component to your Scene. Maybe you can try that first.

    #15912
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    my walker generator object is already in the scene

    View post on imgur.com

    #15913
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    You can try delaying OnSceneLoaded() by a single frame and see if the WalkerGenerator can be found like this. The function may be running before your GameObjects are properly initialised:

    private IEnumerator OnSceneLoadedDelayed(Scene scene, LoadSceneMode mode)
    {
        Debug.Log("OnSceneLoaded called for scene: " + scene.name);
    
    WalkerGenerator walkerGenerator = FindFirstObjectByType<WalkerGenerator>();
    if (walkerGenerator != null)
    {
        walkerGenerator.SpawnPlayer();
        Debug.Log("WalkerGenerator found and SpawnPlayer called.");
    }
    else
    {
        Debug.LogError("WalkerGenerator not found in the scene.");
    }
    
    EnemySpawner enemySpawner = FindFirstObjectByType<EnemySpawner>();
    if (enemySpawner != null)
    {
        enemySpawner.InitializeSpawner();
    }
    else
    {
        Debug.LogError("EnemySpawner not found in the scene.");
    }

    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
    StartCoroutine(OnSceneLoadedDelayed(scene, mode));
    }

    The reason why I’m focusing on fixing the WalkerGenerator first is because it may be causing the other errors.

    #15915
    C Vagdalt
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    the walkergenerator error is now gone.
    i still have a lot of errors though

    i’ll also post a video of the layout of the scenes i have in the game so you can see when the errors appear

    View post on imgur.com

    #15923
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    You will need to find the lines that are causing the error, and figure out what is causing the message to trigger. Usually, one of your variables are either not set or set wrongly.

Viewing 13 posts - 16 through 28 (of 28 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: