这个作业属于哪个课程 软件工程2022年春-F班
这个作业要求在哪里 软件工程实践总结&个人技术博客
这个作业的目标 课程回顾、个人技术总结
其他参考文献 《构建之法》

目录

  • 一、技术概述
    • 1.1 技术使用场景
    • 1.2 技术难点
  • 二、技术详述
    • 2.1 素材导入
    • 2.2 编辑素材
    • 2.3 绘制地图
    • 2.4 关于图层
    • 2.5 简单的随机资源生成
  • 三、可能遇到的问题以及解决方案
    • 3.1 素材问题
    • 3.2 地图制作问题
    • 3.3 随机生成资源问题
  • 四、总结
  • 五、参考内容

一、技术概述

1.1 技术使用场景

  你不满足于别人提供的现成的地图,想要利用原有的素材来将你自己的想法实现吗?或者你不知道如何获取素材,不知道如何使用素材?在此发挥你天马行空的想象力,用你的鼠标和键盘来绘制自己的王国吧!

1.2 技术难点

  随机资源生成算法的实现。(注:本人unity版本为2021.3.2f1c1,不同版本可能组件位置有所不同)

二、技术详述

2.1 素材导入

  在项目中,点击左上角菜单栏的window,可以看到子选项中有一个Asset Store。

  点击它我们可以来到Unity资源商店寻找我们想要的资源,包括地图、角色、道具、材质等等,你几乎可以在这里找到所想要的东西。

  点击左上角的2D,并勾选上“环境”、“免费资源”(能不花钱就不花钱啊喂),我们来挑选一张心仪的地图,进入资源详情页后,点击“添加至我的资源”后选择“在unity中打开”即可。


  选择import,等待资源导入。


  可以看到左下角的项目文件已经把素材导入进来,现在我们可以开始创作了!

2.2 编辑素材

  首先我们更改一下素材的配置,主要要更改一下素材每单位的像素点。我们可以看到我们的Scene界面有很多网格,一个格子就是一个Unit,这个Pixels Per Unit就是指一个格子中的像素点,当这个值过大,会让每个单位格里面的东西变得很小,个人习惯将这个值调至16,当然你可以自由选择。Sprite Mode更改成Multiple,这会有利于我们后续对素材的切割和制作。更改后,记得点击Apply应用。

2.3 绘制地图

  绘制地图我们需要一个载体,右键左部空白位置,点击2D Object -> Tilemap ->Rectangular ,生成一个Tilemap,供我们在上面制作地图。

  我们还需要一个画板,就跟画家的调色板一样,他们会在上面放上各种颜料,而我们需要在上面放上我们的素材,我们的画板就是Tile Palette。点击左上角的window -> 2D -> Tile Paletee,这时候我们弹出了一个窗口,这个就是我们的画板,将素材(颜料)放在上面,我们才可以进行我们的创作。


  我们可以看到这个素材包里面有现成的帮我们“调制”好的颜料,不过呢有的素材包是没有的,为了能够掌握地图绘制的步骤,我们来重新“调制”一遍!点击画板中的Create New Palette,将新画板的名字重命名,然后点击Create,这时候会弹窗让我们选择一个保存位置,我们可以新建一个文件夹,随便命名一下(我这里命名为Map),选择该文件夹将该画板保存到这个位置。




  不过现在你可以看到,我们的画板上没有任何的东西,我们现在需要将我们的素材切割好并导入,也就是调制我们的颜料。在素材详情页面点击Sprite Editor,进入素材编辑界面,点击Type更改切割类型,选择Grid By Cell Size,更改Pixel Size中x和y使之和我们之前定义的Pixels Per Unit数值一致,之后点击slice,最后记得点击右上角的Apply保存。



  这时我们可以使用素材中每个单元格来进行地图的绘制了!将素材拖入我们的Tile Palette中,选择一个保存的文件夹(我们还是选择放在Map文件夹中),等待导入,之后我们就会发现,我们现在画板上就已经有了素材,而且它已经被划分成了一小格一小格的单位,这时候,我们便可以拿起我们的画笔,正式开始创作!


  让我们用流程图总结一下简单地图制作的过程!

2.4 关于图层

  图层问题是一个需要长篇幅来叙述的功能,你可以利用图层决定角色、水域、草地等元素的显示优先级以及碰撞等等一些细节的体现,本博客止于地图的简单创建,接下来随机生成物体的内容需要你对诸如Tilemap的创建、预制体的创建等内容有所了解,如果想对这些部分进行学习,可以查看本博客的参考内容中的教程。

2.5 简单的随机资源生成

  我们首先创建一张地图,将可生成资源的地块划分到一个图层,剩下的划分到另一个图层。例如我这里将不可生成资源的地块划分到了unrandomground,可生成资源的地块在randomground中。我们还需要准备一些预制体,将这些预制体作为生成的资源。

  新建一个脚本,开始编写代码。思路如下流程图所示:

  首先做好前期准备,保存我们需要随机的资源:

  //需要随机的资源public List<GameObject> resourceGrass = new List<GameObject>(); // 草public List<GameObject> resourceGravel = new List<GameObject>(); // 石头public List<GameObject> resourceTree = new List<GameObject>(); // 树木、灌木public List<GameObject> resourceWoodenConstruction = new List<GameObject>(); // 木制结构public List<GameObject> resourceLithicalConstruction = new List<GameObject>(); // 石制结构private Tilemap tilemap;private List<Vector3> randomGroundTileWorldPos = new List<Vector3>(); // 获取可随机的地块private bool[] randomGroundTileHasEmptySlot; // 判断地块是否已占用,需要初始化private int randomGroundTileCount; // 随机地块数量private int resourcesGrassCount; // 草 数量private int resourcesGravelCount; // 碎石 数量private int resourcesTreeCount; // 树木、灌木private int resourcesWoodConstructionCount; // 木制结构数量private int resourcesLithicalConstructionCount; // 石制结构数量

  初始化函数,由于我们可以将脚本挂接在randomground下,因此保存所有地块就相当于保存了所有可随机地块:

 void InitializeTileMap() // 保存地图的所有地块{tilemap = GetComponent<Tilemap>();Vector3Int tmOrg = tilemap.origin;Vector3Int tmSz = tilemap.size;for (int x = tmOrg.x; x < tmSz.x; x++){for (int y = tmOrg.y; y < tmSz.y; y++){if (tilemap.GetTile(new Vector3Int(x, y, 0)) != null){Vector3 cellToWorldPos = tilemap.GetCellCenterWorld(new Vector3Int(x, y, 0));randomGroundTileWorldPos.Add(cellToWorldPos);}}}}

  接着就开始生成资源,这里举例生成草的函数:

  void GenerateGrass(System.Random rm) // 生成草{int aRandomTile;for (int i = 0; i < 150; i++) {while(!randomGroundTileHasEmptySlot[aRandomTile]){aRandomTile= rm.Next(0, randomGroundTileCount);}Vector3 spawnPos = randomGroundTileWorldPos[aRandomTile];int aRandomRes = rm.Next(0,resourcesGrassCount);GameObject spawnRes = resourceGrass[aRandomRes];Instantiate(spawnRes, spawnPos, Quaternion.identity);randomGroundTileHasEmptySlot[aRandomTile] = false;}}

  编写完代码后,将脚本挂在randomground下,将需要生成的资源以预制体的形式拖入,点击运行,就可以得到我们想要的效果


  不过我们发现,当物体较多时,生成的速率会变慢,这是因为我们用一个数组去存储地块的生成资源情况会使得在地块稀少时寻找可利用地块耗时增加,我们可以改进一下,将生成过资源的地块直接从我们保存地块的列表之中移出,代码如下:

void GenerateTree(System.Random rm) // 生成树木、灌木{for (int i = 0; i < 100; i++) // 生成树木和灌木{randomGroundTileCount = randomGroundTileWorldPos.Count; // 随机地块数量int aRandomTile = rm.Next(0, randomGroundTileCount);Vector3 spawnPos = randomGroundTileWorldPos[aRandomTile];int aRandomRes = rm.Next(0, resourcesTreeCount);GameObject spawnRes = resourceTree[aRandomRes];Instantiate(spawnRes, spawnPos, Quaternion.identity);randomGroundTileWorldPos.Remove(spawnPos);}}

  可以发现效率较上一种方法高的多。

三、可能遇到的问题以及解决方案

3.1 素材问题

Q:Unity商店里有我很喜欢的素材,但是卖的很贵怎么办?
A:
  如果只是新手练手使用,可以由tb或者pdd等渠道获取,但如果要用于商业,必须由本人在版权方所提供的渠道购买(Unity商店),否则会有侵权的问题。不过Unity商店提供的素材经常有大力度的打折,你可以收藏下你喜欢的素材等打折时购买。这里推荐一个B站Up主Lee哥的游戏开发加油站,他经常发一些优质且有很大折扣的Unity素材,可供参考。

Q:我在切割素材时,有些按Grid By Cell Size类型切割并不能得到我想要的效果?
A:
  可以尝试着选择其他类型的切割方式,或者是调整一下每个单元格的像素量,素材质量有高有低,有时还需要自己微调。

3.2 地图制作问题

Q:我明明给地图某些部分添加了碰撞体积,但是子弹能穿过去?
A:
  地图的碰撞体积一般由如下图三部分构成,选择Composite Collider 2D中的Geometry Type(指定复合碰撞体生成的几何体的类型),将其设为Polygons(设置符合碰撞体,以便为由凸多边形组成的合并碰撞体集合体生成封闭轮廓),然后在子弹的碰撞体积中,设置Rigidbody 2D的Collision Detection为Continuous(连续检测,防止对象穿过所有静态碰撞体)


  可参考Unity-Rigidbody组件、Unity官方文档-GeometryType。

3.3 随机生成资源问题

Q:生成的物体位置与我设想的不一致?
   正常情况下树木如果在它脚下这块石板上生成,应该会是如下图所示,但实际会往下偏移

A: 这是预制体的锚点问题,在sprite Editor中将对应物体的锚点往下移动即可。

Q:生成的物体图层有问题,例如树木后面的物体应该是被遮蔽的,事实却不是如此?
A:
  点击Edit选择ProjectSettings,在Graphics中选择Transparency Sort Mode,将其置为Custom Axis,此时在同一图层上,物体会根据所处的Y值排序,即Y值越高,显示优先级越靠后,便解决了该问题


四、总结

  Unity的地图制作是新手入门Unity的必学操作之一,其难度并不高,主要依靠学者的细心和耐心。关于资源的随机生成本博客只是提供了一个简单的办法,实际上关于随机地图的生成有其他更深入的研究,包括限制资源生成范围、地形的生成,甚至可以做到地图全随机而不用自己先搭建出一个框架,涉及到了各种模型分析和数值计算。学无止境,不可止步于此。

五、参考内容

1、如何在Tilemap上随机生成资源——bilibili
2、Unity2018教程2D入门——bilibili
3、Unity官方用户手册

在Unity中简单地制作一张2D地图并随机生成资源相关推荐

  1. Cinemachine教程 | Unity中如何快速制作镜头晃动?

    摘要:经常在游戏.影视中会看到镜头晃动的镜头,比如枪的后坐力.爆炸.碰撞.巨人踩踏地面等等,镜头晃动如何快速制作呢? 洪流学堂,让你快人几步.你好,我是跟着大智学Unity的萌新,我叫小新,这是我本周 ...

  2. Cinemachine教程 | Unity中如何快速制作相机切换动画?

    摘要:使用Cinemachine可以快速制作相机切换动画,来看看我是怎么做的吧. 洪流学堂,让你快人几步.你好,我是跟着大智学Unity的萌新,我叫小新,这是我本周的学习总结报告哦. 好久不见.我最近 ...

  3. Unity中ugui如何制作不规则按键的两种方法

    Unity中ugui如何制作不规则按键的两种方法 两种不同的方案 目前,关于这个问题如何,解决通过搜索引擎我们能找到两种不同的方案: 多边形碰撞器: 该方法是指给精灵(Sprite)添加一个多边形碰撞 ...

  4. 如何制作一张标准地图样式的地图(附数据)

    概述 大家有没有想过这样一个问题,我们在标准地图网站上看到的标准地图的样式(形状)和我们平时用到的地图不一样,那么是什么原因导致的呢,我们能够制作这样样式(形状)的标准地图吗,答案是肯定的,这里为大家 ...

  5. 如何制作一张户外地图

    概述 如果你经常参加户外登山等运动,那么可能需要一张户外的地图,虽然现在手机APP已经很方便,但是难免会出现没网等状况,所以传统的纸质地图当然还是个不错的选择,那么这里就给大家介绍一下如何自制一张户外 ...

  6. 【百度地图API】如何制作一张魔兽地图!!——CS地图也可以,哈哈哈

    [百度地图API]如何制作一张魔兽地图!!--CS地图也可以,哈哈哈 原文:[百度地图API]如何制作一张魔兽地图!!--CS地图也可以,哈哈哈 摘要: 你玩魔兽不?你知道如何做一张魔兽地图不?! 快 ...

  7. unity中监听文件夹并且创建文件夹后做资源更新

    unity中监听文件夹并且创建文件夹后做资源更新 有时候我们在设计的时候,可能对项目的文件内容进行监听,也可能需要在监听某个文件夹的操作,并且做出相对应的处理,例如项目资源的大小监听等,以下就提供两种 ...

  8. 【unity游戏开发教程】Unity+Umotion Pro+VRoid+Blender制作人物模型和动画,在unity中简单制作二次元人物动画

    前言 大家好!本期教程教大家在unity中制作二次元人物模型和动画 文章目录 前言 0.环境准备 1.下载VRoid Studio 2.Umotion Pro下载 3.Mixamo网站 4.blend ...

  9. 个人技术总结——Unity中角色动画制作及动画切换逻辑的实现

    这个作业属于哪个课程 软件工程实践2022春-F班 这个作业要求在哪里 软件工程实践总结&个人技术博客 这个作业的目标 课程回顾与总结+个人技术总结 其他参考文献 <Unity2018教 ...

最新文章

  1. 理解ABR及其工作原理
  2. python怎么退出help_(转)python中如何使用help命令?
  3. aes算法实现c语言_以C语言实现归并排序为例,谈谈五大常用算法之一的“分治法”...
  4. 开源社区合入patch的步骤
  5. Cesium中级教程6 - 3D Models 三维模型
  6. 【续上篇】推荐一款液晶电视测试软件
  7. windows无法访问指定设备_恢复 你的电脑/设备需要修改 未连接或无法访问所需设备。...
  8. 马云不要当首富;ofo 否认裁员;苹果剔除 iPhone Xs Max 组件 | 极客头条
  9. 互联网+传统硬件,乐视与酷派要构建全新生态链?
  10. Cadence OrCAD Capture交叉参考报表生成方法图文教程
  11. 安全测试者偏爱的安全测试工具
  12. 如何在电脑上将PDF文件转换成word?
  13. 【面试个人成长】2021年过半,社招和校招的经验之谈
  14. 中国风来袭!如何用ArcGIS制作水墨风山水画?
  15. MATLAB绘图(一)
  16. 【SAP-CO】CO模块主要子模块相关概念
  17. java word 颜色设置_如何为Word文档在Java中的背景颜色
  18. vue中px 转 vh/vw
  19. 基于Django的照相馆预约系统的设计与实现
  20. 中国水资源现状分析,水资源人均占有率不足「图」

热门文章

  1. Unity TMP超链接和图文混排
  2. 预处理加速干货:大幅加速数据预处理、轻松定制高性能ML算子
  3. Taichi的学习笔记
  4. 运营商大数据对用户的个人隐私的影响?
  5. SSM SpringBoot vue服装厂管理系统
  6. TCP重传与确认机制
  7. 什么是上网行为管理?
  8. 打造自己的极点拼音五笔
  9. ICLR 2022—你不应该错过的 10 篇论文(下)
  10. 云计算和大数据的区别