想做一个类似以撒的肉鸽游戏,然后记录一下进度,也做个学习的总结笔记吧,目前想到的要素:随机地图生成,敌人AI,角色控制和攻击,一些动画,还有随机掉落物品,商店。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class RoomGenerator : MonoBehaviour
{public enum Direction{up,down,left,right};public Direction direction;[Header("房间信息")]public GameObject roomPrefab;public int roomNumber;public Color startColor, endColor;private GameObject endRoom;[Header("位置控制")]public Transform generatorPoint;public float xOffset;public float yOffset;public LayerMask roomLayer;//这边以后可以考虑用自定义类,储存Room的详细数据public List<GameObject> rooms = new List<GameObject>();void Start(){for (int i = 0; i < roomNumber; i++){rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity));//改变point位置ChangePointPos();}rooms[0].GetComponent<SpriteRenderer>().color = startColor;endRoom = rooms[0];foreach(var room in rooms){//如果当前的room的向量长度比endRoom大,则将endRoom重新赋值//sqrMagnitude是长度的平方,要比开方magnitude快很多if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude){endRoom = room;}endRoom.GetComponent<SpriteRenderer>().color = endColor;}}// Update is called once per framevoid Update(){if (Input.anyKeyDown){//随机键刷新新地图SceneManager.LoadScene(SceneManager.GetActiveScene().name);}}private 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));}
}

大致代码就如上所示,目前只是初步完成了房间的随机生成,以及初始和结束BOSS房的计算,目前是用List<GameObject>来储存生成的房间,之后可以考虑改成二维数组或者自定义类,可以储存更多信息,比如生成的房间类型、房间的Position、以及更细致的设定(比如当前房间生成怪物位置之类的)。

房间生成逻辑稍微简单总结一下:先生成一个起始点的初始房间,然后根据偏移量以及随机方向去寻找下一个房间,找到下一个房间生成点之后判断是否有房间,如果有的话就继续根据这个新点的上下左右继续寻找生成,如果没有的话就直接生成,这样可以避免一个房间四周都有房间时,导致无法生成新房间。

然后初始房间设定没问题,但是结束房间的判断可能还需要改进一下,目前这个性能比较好,但是有时候可能判断的不是最远房间。


上次说到要优化的内容,储存生成的房间改成了List<Room>,然后可以根据个人需要声明你想要用的变量,这边初步想要房间类型,以及判断房间上下左右是否有门的变量,最后四个bool值类型是用于BFS查找时,防止往来的方向查找的变量。

    public enum RoomType{normalRoom,startRoom,treasureRoom,bossRoom,shop}public RoomType roomType;public GameObject doorLeft, doorRight, doorUp, doorDown;//上下左右是否有房间public bool roomLeft, roomRight, roomUp, roomDown;//判断上一个房间来源方向,用于查找步数public bool fromLeft = false;public bool fromRight = false;public bool fromUp = false;public bool fromDown = false;

还有最远房间判断优化,这里可以用xy偏移量大小来查找,但是由于Room的X为18,y为8,所以需要将X除以2在进行查找会更好,然后标出距离原点房间的step,但是如果遇到U型地图,我们需要的最末端应该是另一端的U,但是实际偏移量最大的可能不是另一端,因此需要优化一下查找算法,这边使用了BFS算法,计算了实际需要经过最多房间的房间设置为最终房间。

    private GameObject GetFarthestRoom(){GameObject lastRoom = rooms[0].gameObject;Room currentRoom = rooms[0];currentRoomQue.Enqueue(rooms[0]);//一层一层查找符合条件的房间while (currentRoomQue.Count > 0){currentRoom = currentRoomQue.Dequeue();FindNextRoom(currentRoom.fromUp, currentRoom.roomUp, currentRoom.transform.position, Direction.up);FindNextRoom(currentRoom.fromDown, currentRoom.roomDown, currentRoom.transform.position, Direction.down);FindNextRoom(currentRoom.fromLeft, currentRoom.roomLeft, currentRoom.transform.position, Direction.left);FindNextRoom(currentRoom.fromRight, currentRoom.roomRight, currentRoom.transform.position, Direction.right);}lastRoom = currentRoom.gameObject;return lastRoom;        }private void FindNextRoom(bool fromBool, bool dirBool, Vector3 currentPos, Direction dir){Vector3 offset = new Vector3(0, 0, 0);switch (dir){case Direction.up:offset = new Vector3(0, yOffset, 0);break;case Direction.down:offset = new Vector3(0, -yOffset, 0);break;case Direction.left:offset = new Vector3(-xOffset, 0, 0);break;case Direction.right:offset = new Vector3(xOffset, 0, 0);break;}//方向上有房间时,且排除上一个房间if (dirBool && !fromBool){for (int i = 0; i < rooms.Count; i++){//找到下一个的房间if (rooms[i].transform.position == currentPos + offset){currentRoomQue.Enqueue(rooms[i]);switch (dir){case Direction.up:rooms[i].fromDown = true;break;case Direction.down:rooms[i].fromUp = true;break;case Direction.left:rooms[i].fromRight = true;break;case Direction.right:rooms[i].fromLeft = true;break;default:break;}break;}}}}

然后关于BOSS房我想的游戏逻辑是:最终房间再上下左右生成一个新房间,作为最后的BOSS房,这样BOSS房就可以保证只有一个通路通向它。

这边不复用之前的生成房间的逻辑有两个理由,第一是因为最终房间不一定是rooms列表中的最后一个,因此此时的generatorPoint还在最后生成的那个房间处,此时如果将generatorPoint=endroom.transform的话,再方法中更改generatorPoint时,endroom.transform也会随之更改,因为这是引用类型,他们都引用了内存堆上的地址,需要使用深拷贝来解决。但还有第二个问题,就是如果新生成的房间方向上有房间,那他会从此处再寻找上下左右,此时新生成的房间就会离最终房间有>2的房间距离了,因此新写一个单独生成单个房间的方法,如果以后还要加隐藏房间的话可以用他来实现。

    private GameObject CreateOneWayRoom(Room currentRoom){Vector3 nextRoom;if (!currentRoom.roomRight){nextRoom = new Vector3(currentRoom.transform.position.x + xOffset, currentRoom.transform.position.y, currentRoom.transform.position.z);rooms.Add(Instantiate(roomPrefab, nextRoom, Quaternion.identity).GetComponent<Room>());currentRoom.roomRight = true;rooms[rooms.Count - 1].roomLeft = true;}else if (!currentRoom.roomLeft){nextRoom = new Vector3(currentRoom.transform.position.x - xOffset, currentRoom.transform.position.y, currentRoom.transform.position.z);rooms.Add(Instantiate(roomPrefab, nextRoom, Quaternion.identity).GetComponent<Room>());currentRoom.roomLeft = true;rooms[rooms.Count - 1].roomRight = true;}else if (!currentRoom.roomDown){nextRoom = new Vector3(currentRoom.transform.position.x, currentRoom.transform.position.y - yOffset, currentRoom.transform.position.z);rooms.Add(Instantiate(roomPrefab, nextRoom, Quaternion.identity).GetComponent<Room>());currentRoom.roomDown = true;rooms[rooms.Count - 1].roomUp = true;}else if (!currentRoom.roomUp){nextRoom = new Vector3(currentRoom.transform.position.x, currentRoom.transform.position.y + yOffset, currentRoom.transform.position.z);rooms.Add(Instantiate(roomPrefab, nextRoom, Quaternion.identity).GetComponent<Room>());currentRoom.roomUp = true;rooms[rooms.Count - 1].roomDown = true;}return rooms[rooms.Count - 1].gameObject;}

然后宝箱房也可以按照这个逻辑生成,但是传过来的currentRoom需要判断一下是否有至少一个的方向上没有房间 ,Boss房不用考虑最终房间四个方向都占满的情况,是因为既然是最远的房间,那不可能四个方向都有房间。可以在Room类型中提供一个方法获取本房间一共有多少门。

我还设置了商店,商店的生成逻辑是直接从rooms列表中随机一个房间,只要他是normalRoom的房间类型,就将它修改成shop类型,这样避免覆盖其他的特殊类型房间。

按照目前的生成逻辑的话,三种特殊类型房间生成顺序可以随意,因为他们互相不干扰,即使宝箱房和BOSS房都选中了最后一个房间衍生,因为最远房间的特性至少会让他空出两个方向,因此也没有大碍。

随机生成几个:(红色为BOSS房,绿色为起点,黄色为宝箱房,蓝色为商店)

Unity 游戏Demo制作——地下城 一相关推荐

  1. Unity 游戏Demo制作 地下城 二

    这篇大致是优化了一下房间门和墙壁的逻辑,接着增加了人物逻辑,然后增加了切换房间的同时切换摄像机位置.部分逻辑也参考了其他前辈的资料. 首先是房间门,因为免费素材比较难找,游戏本身也是致敬以撒的,因此就 ...

  2. 天上的街市Unity游戏场景制作案例(一)

    目录 Downtown Street of Heaven 场景 Unity实现过程 新建项目 场景布置 场景制作参考 移动媒介的添加 Downtown Street of Heaven 场景 Unit ...

  3. Unity游戏快速制作特效

    专家进阶教学之一 先立个flag吧,反正我也还不懂 估计也很难完成,先定亿个小目标

  4. 【unity】快速了解游戏制作流程-制作九宫格简单游戏demo

    前言 hi~大家好呀!欢迎来到我的unity学习笔记系列~,本篇我会简单的记录一下游戏流程并且简单上手一个通过九宫格移动到指定位置的小游戏,话不多说,我们直接开始吧~ 本篇源自我看B站一位up主的视频 ...

  5. Unity游戏排行榜的制作与优化

    前言 游戏排行榜是一个很重要的功能,在弱联网的单机游戏与网络游戏中排行榜都是非常重要的,今天我们来详细的讲解游戏排行榜的制作方案,主要有4个点: 对啦!这里有个游戏开发交流小组 里面聚集了一帮热爱学习 ...

  6. Unity常用模块设计 : Unity游戏排行榜的制作与优化

    游戏排行榜是一个很重要的功能,在弱联网的单机游戏与网络游戏中排行榜都是非常重要的,今天我们来详细的讲解游戏排行榜的制作方案,主要有4个点: 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交 ...

  7. Unity小地图Minimap制作全面功能介绍篇

    本系列文章将讲述如何制作小地图. 功能如下: 小地图制作和美化       https://blog.csdn.net/alayeshi/article/details/115914212 小地图展示 ...

  8. Unity模拟经营类游戏Demo部分代码及技术总结

    7月份自己做了一个模拟经营类的游戏Demo,在此总结UI.库存系统.交易系统.游戏循环等相关内容的代码和实现. 实现效果预览 目录 UI 库存系统 交易系统 游戏循环 UI 本项目的UI通过Unity ...

  9. 我用unity开发的第一款游戏demo心得

    本人目前大一,双非一本,谨以此博客,记录日后的unity学习过程与算法训练.希望能同大家一起进步!也希望三年后回过头来能看到一个优秀而拼搏的自己! 话不多说,上我的第一个demo(虽然是跟着视频做的) ...

最新文章

  1. Linux下MONO执行C#程序
  2. Linux系统中如何关闭触摸鼠标
  3. 如何改造UE4用于赛璐璐3D卡渲?这里有一份日本大厂的实操分享
  4. Date类+DateFormat
  5. Xcode中的-ObjC和-all_load
  6. 查看docker内部路径_web应用在Docker容器中部署(Windows)
  7. 【ElasticSearch 学习笔记】Java API
  8. Ubuntu20安装gcc11
  9. Java9 基于异步响应式流的发布-订阅框架
  10. C#--图表控件(Chart)
  11. Codechef:Walk on Tree/TREEWALK(Berlekamp-Massey算法)
  12. 所见即所得的 Markdown 编辑器
  13. 关于GPIO的内部结构及编程步骤
  14. pcap头文件位置 Linux,pcap文件头的组织格式
  15. 物联网智慧物流平台开发
  16. Android-APP隐私合规检测
  17. 为什么都在选择学习Java
  18. delphi(XE2)实现图片异形窗体,支持摆放控件
  19. Java中特殊字符处理(转义字符)
  20. 用iMovie制作app store预览视频

热门文章

  1. [Java]finalized方法
  2. Linux date +%H%M%S与date +%H%m%S的区别
  3. linux 视频 hint,求问:hint后的mp4和没hint前mp4文件有什么不同?
  4. 跟我学flutter:细细品Widget(一)WidgetElement初识
  5. 控件 ListView1 的类 MSComctlLib.ListView 不是一个已加载的控件类
  6. 著名的 南京长江大桥 南引桥发生火灾
  7. C语言random6,Random怎么用(c语言random怎么用)
  8. 爬虫 豆瓣音乐 top250
  9. matlab贝叶斯判别后验概率,统计学习方法——朴素贝叶斯法、先验概率、后验概率(示例代码)...
  10. 最简单的U盘安装windows 7的方法