在随机生成的 2D 地牢中的导航网格表面上生成敌人

问题描述 投票:0回答:0

在过去的几个月里,我从旧的塞尔达游戏中汲取了一些灵感,制作了一款类似《以撒的结合》的游戏。我之前在这里发过一篇文章(在运行时为二维半程序地牢爬虫(Unity)生成导航网格),我在使用场景生成房间时甚至都在努力烘焙 Navmesh。从那以后,我开始使用预制房间并在运行时实例化它们以随机放置在地牢中。我还获得了导航网格表面以应用于整个地牢中的每个房间,并且可以在它们应该在的房间中看到它们,它们应该看起来如何等等。在运行时的层次结构中,我能够在我的主要场景的一部分 RoomController 游戏对象中查看房间及其内容。它显示它们好像是由那个房间生成的,但都是在起始房间内生成的。下面我将提供一些我所看到的屏幕截图,以更好地说明问题。 Before pressing playAfter pressing playShowing the spawner

我希望敌人在他们自己的房间中生成,参见图 2,其中“Basmement-RoomBasic”有 3 个小恶魔和 4 个近战敌人。这些敌人会在导航网格上的那个房间里生成

我已经尝试重新烘焙导航网格,在运行时使用直接从 Unity 的运行时导航烘焙指南中获取的导航烘焙器对其进行烘焙,并删除它们不应在其上生成的 tilemap 部分并使其仅在房间内。我尝试修改我的 GridController、我的 DungeonGenerator 和我的 ObjectSpawner 脚本,但都无济于事。下面我也会提供这些脚本

首先是 GridController

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

public class GridController : MonoBehaviour
{
    public Room room;

    [System.Serializable]
    public struct Grid
    {
        public int columns, rows;
        public float verticalOffset, horizontalOffset;
    }

    public Grid grid;
    public GameObject gridTile;
    public List<Vector2> availablePoints = new List<Vector2>();

    void Awake()
    {
        room = GetComponentInParent<Room>();
       
        GenerateGrid();
    }

    public void GenerateGrid()
    {
        grid.verticalOffset += room.transform.localPosition.y;
        grid.horizontalOffset += room.transform.localPosition.x;

        for (int y = 0; y < grid.rows; y++)
        {
            for (int x = 0; x < grid.columns; x++)
            {
                GameObject go = Instantiate(gridTile, transform);
                go.GetComponent<Transform>().position = new Vector2(x - (grid.columns - grid.horizontalOffset), y - (grid.rows - grid.verticalOffset));
                go.name = "X: " + x + ", Y: " + y;
                availablePoints.Add(go.transform.position);
                go.SetActive(false);
            }
        }

        GetComponentInParent<ObjectRoomSpawner>().InitialiseObjectSpawning();
    }
    public List<Vector3> GetSources()
    {
        List<Vector3> sources = new List<Vector3>();
        foreach (Transform child in transform)
        {
            if (child.gameObject.activeSelf)
            {
                NavMeshHit hit;
                if (NavMesh.SamplePosition(child.position, out hit, 0.1f, NavMesh.AllAreas))
                {
                    sources.Add(hit.position);
                }
                else
                {
                    Debug.LogWarning("Could not find a valid position on the NavMesh for source spawn");
                }
            }
        }
        return sources;
    }



}

接下来是地牢生成器

using NavMeshPlus.Components;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class DungeonGenerator : MonoBehaviour
{
    public DungeonGenerationData dungeonGenerationData;
    
    private List<Vector2Int> dungeonRooms;
    public Room startingRoomPrefab;
    public Room bossRoomPrefab;
    public Room[] roomPrefabs;
    
    private void Start()
    {
        dungeonRooms = DungeonCrawlerController.GenerateDungeon(dungeonGenerationData);
        SpawnRooms(dungeonRooms);
        
        Debug.Log("Nav mesh should be rebuilt now");
    }

    private void SpawnRooms(IEnumerable<Vector2Int> rooms)
    {
        // Load the starting room
        RoomController.instance.LoadRoom(startingRoomPrefab, 0, 0);
        List<Room> loadedRooms = new List<Room>();
        loadedRooms.Add(startingRoomPrefab);

        foreach (Vector2Int roomLocation in rooms)
        {
            // Check if a room already exists at the specified location
            Room room = RoomController.instance.GetRoomAtPosition(roomLocation.x, roomLocation.y);
            if (room != null || loadedRooms.Any(loadedRoom => loadedRoom.X == roomLocation.x && loadedRoom.Y == roomLocation.y))
            {
                continue;
            }

            // Get a random room prefab from the list
            int randomIndex = Random.Range(0, roomPrefabs.Length);
            Room randomRoomPrefab = roomPrefabs[randomIndex];

            // Load the room prefab at the given location
            RoomController.instance.LoadRoom(randomRoomPrefab, roomLocation.x, roomLocation.y);
            loadedRooms.Add(randomRoomPrefab);
            Debug.Log("Room spawned at x = " + roomLocation.x + ", and at y = " + roomLocation.y);
        }
    }
}

最后是 ObjectSpawner

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

public class ObjectRoomSpawner : MonoBehaviour
{
    [System.Serializable]
    public struct RandomSpawner
    {
        public string name;
        public SpawnerData spawnerData;
    }

    public GridController grid;
    public RandomSpawner[] spawnerData;

    void Start()
    {
        //grid = GetComponentInChildren<GridController>();
    }

    public void InitialiseObjectSpawning()
    {
        foreach (RandomSpawner rs in spawnerData)
        {
            SpawnObjects(rs);
        }
    }

    void SpawnObjects(RandomSpawner data)
    {
        int randomIteration = Random.Range(data.spawnerData.minSpawn, data.spawnerData.maxSpawn + 1);

        for (int i = 0; i < randomIteration; i++)
        {
            int randomPos = Random.Range(0, grid.availablePoints.Count - 1);

            // Get a random point on the NavMesh
            NavMeshHit hit;
            if (NavMesh.SamplePosition(grid.availablePoints[randomPos], out hit, 10f, NavMesh.AllAreas))
            {
                // Instantiate the enemy prefab at the NavMesh position
                GameObject go = Instantiate(data.spawnerData.itemToSpawn, hit.position, Quaternion.identity, transform) as GameObject;
                grid.availablePoints.RemoveAt(randomPos);
                Debug.Log("Spawned Object at position " + hit.position);
            }
            else
            {
                Debug.LogWarning("Could not find a valid position on the NavMesh for enemy spawn");
            }
        }
    }


}

任何信息都将不胜感激,以指出我正确的方向。为了我的毕业设计,我整个学期都在研究这款游戏,完成这项工作将使游戏几乎完成。提前致谢!


编辑#1

我认为在运行时额外显示导航网格的示例可能很有用。

NavMesh example 1

NavMesh example 2

unity3d artificial-intelligence game-development navmesh
© www.soinside.com 2019 - 2024. All rights reserved.