Roguelike随机地下城 | 一、生成随机房间

Roguelike随机地下城

生成随机房间



前言

上一个简单的UI框架基本完结,后续可能会有所更新,接下来我会更新我在学习的随机地下城,我会一边学习一边更新。


一、什么是随机地下城?

随机地下城就是我们Unity会通过我们的代码,自动的生成地下城的地图,并且里面的物品场景也会随机生成。

二、生成随机房间

首先我们先建一个Unity工程。
我们一开始先不着急使用地图场景资源,先定义随机生成房间的方法。
养成好习惯先建立两个空的文件夹,一个为Prefabs存放预制体,一个为Scripts存放脚本。
这里我建立了一个空的GameObject命名为BasicRoom,作为我们的房间,并生成预制体,因为我们后续要通过这个预制体随机生成房间。
在这里插入图片描述
我们再生成一个空的GameObject命名为RoomGenerator,用来暂时当我们的主场景,在上面生成我们的随机位置的BasicRoom
接下来我们在RoomGenerator下再创建一个GameObject命名为Point,用来判断我们每一个生成的房间的位置。
在这里插入图片描述
接下来我们就要开始编写我们的代码,再RoomGenerator下建立脚本。
首先我们定义一下我们的预制体,还有我们要生成的房间数,我们还设置一下开始房间和最后房间的颜色方便我们判断,获得我们每一个房间的位置的点,和x轴y轴的偏移量。

    [Header("房间信息")]
    public GameObject roomPrefab;
    public int rooNumber;
    public Color startColor,endColor;

    [Header("位置控制")]
    public Transform generatorPoint;
    public float xOffset;
    public float yOffset;

这里的Header没有实际意义就是一个标签。
为什么我们要设置偏移量,因为我们要生成房间就要有房间的位置,那么房间的位置就是通过从起始房间x,y偏移多少获得的。
接下来我们回的Unity来设置一下他们。
在这里插入图片描述
x、y轴的偏移量我们可以通过自己去拖拽我们的房间物体,来大概的获得一个我们觉得满意的位移距离。
这里我们以生成十个房间为例。
接下来我们处理生成预制体,即生成我们的房间,使用Instantiate方法即可,因为我们是一开始就生成房间,所以我们再Start方法里实现。
因为我们根据生成的房间数量来生成我们的房间,所以通过for语句循环生成。

    void Start()
    {
    
    
        for (int i = 0; i < rooNumber; i++)
        {
    
    
            Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity);
        }

这里为了方便我们后续直接使用我们的每一个房间,我们定义一个数组,将我们生成的房间放入数组里面,就可以直接使用了,所以我们做以下的更改。

    public List<GameObject> rooms = new List<GameObject>();
    // Start is called before the first frame update
    void Start()
    {
    
    
        for (int i = 0; i < rooNumber; i++)
        {
    
    
            rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity));
        }
    }

房间生成了,我们要改变我们每个房间的位置,但是问题来了,我们怎么随机的控制我们的房间生成再起始房间的上下左右呢?
这里就可以用到我们的枚举方法,我们可以将上下左右定义成一个枚举方法,枚举方法返回值是对应的数字,再通过Random来随机生成数字,即生成对应的方向,这里我们再通过Switch方法调用我们的四个方向分别定义我们的四个方法对位置的改变就可以了。

    public enum Direction {
    
     up,down,left,right };
    public Direction direction;
    public void ChangePointPos()
    {
    
    
            direction = (Direction)Random.Range(0, 4);

            switch (direction)
            {
    
    
                case Direction.up:
                    generatorPoint.position += new Vector3(0, yOffset, 0);
                    break;
                case Direction.down:
                    generatorPoint.position += new Vector3(0, -yOffset, 0);
                    break;
                case Direction.left:
                    generatorPoint.position += new Vector3(-xOffset, 0, 0);
                    break;
                case Direction.right:
                    generatorPoint.position += new Vector3(-xOffset, 0, 0);
                    break;
            }
    }

然后我们再Start方法中调用这个方法,回到Unity中运行一下看看效果。
运行之后我们发现生成的房间数没有十个,这是为什么?
因为我们很多生成的房间都重合在一起了,我们怎么才可以避免这个问题的发生呢?
这里就要用到我们的Unity中的碰撞,并且新加一个碰撞层Layer,判断两个房间是否接触了。
首先给我们的预制体添加一个组件Rigidboby 2D,这个组件是为我们的物体添加刚体效果。
在这里插入图片描述
这里我们的刚体类型默认为Dynamic,他会给物体施加一个重力效果,物体会自由落体。
这里我们用到Static,将它设置成静态的刚体。
再加一个组件Box Collider 2D,一个盒型碰撞框,还有很多其他的碰撞框可以自行探索一下。
在这里插入图片描述
点击箭头所指的地方可以调整我们的碰撞框。
最后我们再新加一个碰撞层。
在这里插入图片描述
在这里插入图片描述
完成之后将我们的BasicRoom的碰撞层设置为Room
接下来我们就可以在脚本中判断一下两个房间是否发生碰撞,如果没有就生成新的房间,这里我们用到dowhile方法,因为我们一开始是要生成一个房间的。
我们首先要接收到这个层,并且在我们的Unity中把这个层赋值上去。
改进如下
在这里插入图片描述

    public LayerMask roomLayer;
    public void ChangePointPos()
    {
    
    
        do
        {
    
    
            direction = (Direction)Random.Range(0, 4);

            switch (direction)
            {
    
    
                case Direction.up:
                    generatorPoint.position += new Vector3(0, yOffset, 0);
                    break;
                case Direction.down:
                    generatorPoint.position += new Vector3(0, -yOffset, 0);
                    break;
                case Direction.left:
                    generatorPoint.position += new Vector3(-xOffset, 0, 0);
                    break;
                case Direction.right:
                    generatorPoint.position += new Vector3(-xOffset, 0, 0);
                    break;
            }
        }while (Physics2D.OverlapCircle(generatorPoint.position,0.2f,roomLayer));
    }

这里我们使用了Physics2D.OverlapCircle方法,表示为第一个参数的位置,再第二个参数的范围内,是否碰撞了第三个参数所指的层。
接下来我们在运行一下游戏,发现这样就生成了十个随机位置的房间。
接下来我们要找到我们的开始房间和结束房间并且附上颜色,这里的结束房间并不是最后一个生成的房间,而是距离开始房间最远的那个房间,那我们要怎么找到它呢?
通过sqrMagnitude方法,这个方法是把一个三维向量的三个轴的值分别平方相加取到这个值,那么这样我们就可以得到我们的距离最远的那个房间了,找到之后给它我们一开始定义的endColor就可以了。

        private GameObject endRoom;
        rooms[0].GetComponent<SpriteRenderer>().color = startColor;

        endRoom = rooms[0];
        foreach (var room in rooms)
        {
    
    
            if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude)
            {
    
    
                endRoom = room;
            }
        }
        endRoom.GetComponent<SpriteRenderer>().color = endColor;

我们通过获得SpriteRenderer组件来控制颜色。
使用Foreach语句来遍历我们的数组。
这样我们的随机房间算是大功告成了,我们来看一下效果。
在这里插入图片描述
这样我们之后就可以对房间里面的东西进行设置了!


总结

今天我们主要完成我们房间的随机生成,以及找到我们的开始房间和结束房间,这样方便我们后续对整个游戏的完成和地图的设置。

猜你喜欢

转载自blog.csdn.net/m0_64058685/article/details/124743793