赞
踩
量过大
本教程涉及协程,如果不懂协程请点击上方总目录6,7节课查看协程
为什么要用携程呢?因为协程可以使得整个函数在过程运行,而不用一帧中完成所有的函数,不然只得计算量过大,让机器卡住。
我所查到的教程几乎全是伪3DRPG类型的随机地图生成,大多数通过噪声和通路算法完成,但我们的目标是横版类型的地图,不能在那样生成含高度的岛屿形状,就如同泰拉瑞亚游戏的那种,并放大一些冒险跑酷要素会更好。
1.基础TileMap教程
首先在层级目录下,右键->2D对象->瓦片地图,会新建Grid物体自带一个Tilemap子物体
注意使用复合碰撞器 composite collider 2D可以压缩优化瓦片碰撞盒,将连接在一起的瓦片碰撞盒视为一个整体
为什么要用这个插件?因为这个插件可以自动的根据你生成生成对应不同的瓦片地图(即规则瓦片Rule Tile),让减少了我们来进行判断这个地图是在边缘还是内部的算法,他也可以做到随机生成预制体之类的,很多功能。咱们只用到这两个功能就行。
(1)下载和导入
---如何创建平铺调色板
---如何创建规则瓦片
我自己创建的部分规则,中间灰色为你右边导入的精灵sprite图位置,绿色(点一次)为可连接此处的方块,红色(点俩次)为没有方块
将规则瓦片拖入到自己创建的平铺调色板上,就可以画了。会根据瓦片周围的情况自己变。
(3)常用API介绍
3.横版随机地图生成
思路就是先生成瓦片,再进行创建能通过的通道。
生成瓦片的时候先随机生成瓦片起始点,再通过一个协程从瓦片起始点开始延长不等长度(因为是横版游戏,在横向上的延伸要求高)
首先创建TileMapManager空物体,在空物体下面加入脚本GroundTIleMap
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Tilemaps;
- public class GroundTIleMap : MonoBehaviour
- {
- public Tilemap tilemap;//拖动获取瓦片地图
- public TileBase groundTile;//拖动获取地面规则瓦片Rule Tile,-
- public Vector2Int lowerLeftCoo = new Vector2Int(-18, -7);//地图左下角位置
- public int width= 20;//地图宽度
- public int length= 100;//地图长度
-
- // Start is called before the first frame update
- void Start()
- {
-
- StartCoroutine(GroundStartPoi());
- }
-
- // Update is called once per frame
- IEnumerator GroundStartPoi()//生成地面起始点 用协程可以缓慢一步步生成地图,性能消耗少
- {
- tilemap.ClearAllTiles();
- Debug.Log("开始生成地面");
- for (int i = lowerLeftCoo.x; i < (this.length + lowerLeftCoo.x); i++)
- {
- for (int j = lowerLeftCoo.y; j < (this.width + lowerLeftCoo.y); j++)
- {
- yield return null;
- bool IsGround = j< (this.width +3)?(Random.value > 0.9): (Random.value > 0.95);//三元表达式,地面三行更容易生成地面起始点
- if (IsGround) StartCoroutine(GroundExtension(i,j));
-
- }
- }
- Debug.Log("结束生成地面");
- StartCoroutine(ClearChannel());//执行完GroundStartPoi(),GroundExtension()生成地面,开始清除产生能走的通道
-
- }
- IEnumerator GroundExtension(int i,int j)//从地面起始点开始延长
- {
- int groundLen = Random.Range(2, 10);
- for (int m = i; m <= i + groundLen; m++)
- {
- yield return null;
- tilemap.SetTile(new Vector3Int(m,j,0),groundTile);
- }
-
- }
- //清除,产生通道,思路就是从底层有方块的地方,开始判断上面。如果没有方块的话,就清除俩层/三层的通道
- IEnumerator ClearChannel(){
- Debug.Log("开始产生通道");
- for (int i = lowerLeftCoo.x; i < (this.length + lowerLeftCoo.x); i++)
- {
- for (int j = lowerLeftCoo.y; j < (this.width + lowerLeftCoo.y-1); j++)//最高层上面必然没有方块,不需要判断,-1
- {
- if (tilemap.GetTile(new Vector3Int(i, j, 0)) != null)//如果此处不为空方块
- {
- if (tilemap.GetTile(new Vector3Int(i, j + 1, 0)) == null)//如果此处上方为空方块
- {
- tilemap.SetTilesBlock(new BoundsInt(i-2, j + 1, 0,3,3,1),new TileBase[] { null,null, null, null, null, null,null, null, null });//将上方3x3格子置空
-
- }
-
-
- }
- yield return null;
-
- }
- }
-
- }
- }
4.Random Tile随机瓦片生成花,草,石头
和规则瓦片的创造方式一样,先创建tileMap,再创建ruleTile
注意需要修改环境瓦片地图的平铺轴和精灵图片的锚点位置,确保随机生成的精灵图是接触与地面而不是悬空的。(由于随机生成的环境精灵图大小不一样,但锚点都在中间,所以需要修改锚点)
提取常数,设置成可以改变的变量,再加上环境步骤脚本更新:
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Tilemaps;
- public class GroundTIleMap : MonoBehaviour
- {
- public Tilemap ground_tilemap;//拖动获取地面瓦片地图
- public Tilemap environ_tilemap;
- public TileBase groundTile;//拖动获取地面规则瓦片Rule Tile,-
- public TileBase environTile;//拖动获取环境规则瓦片
- public Vector2Int lowerLeftCoo = new Vector2Int(-18, -7);//地图起始左下角位置
- public int width= 20;//地图宽度
- public int length= 100;//地图长度
- public float groundStartPro = 0.10f;//生成地面起始点的概率
- public Vector2Int groundLenRan = new Vector2Int(3, 10);//起始地面点生成的长度范围
- public float environmentRich = 0.5f;//环境丰富度
-
- // Start is called before the first frame update
- void Start()
- {
-
- StartCoroutine(GroundStartPoi());
- }
-
- // Update is called once per frame
- IEnumerator GroundStartPoi()//生成地面起始点 用协程可以缓慢一步步生成地图,性能消耗少
- {
- ground_tilemap.ClearAllTiles();
- Debug.Log("开始生成地面");
- for (int i = lowerLeftCoo.x; i < (this.length + lowerLeftCoo.x); i++)
- {
- for (int j = lowerLeftCoo.y; j < (this.width + lowerLeftCoo.y); j++)
- {
- yield return null;
- bool IsGround = j< (this.width +3)?(Random.value <= groundStartPro) : (Random.value <= groundStartPro+0.05);//三元表达式,地面三行更容易生成地面起始点
- if (IsGround) StartCoroutine(GroundExtension(i,j));
-
- }
- }
- Debug.Log("结束生成地面");
- StartCoroutine(ClearChannel());//执行完GroundStartPoi(),GroundExtension()生成地面,开始清除产生能走的通道
-
- }
- IEnumerator GroundExtension(int i,int j)//从地面起始点开始延长
- {
- int groundLen = Random.Range(groundLenRan.x, groundLenRan.y);
- for (int m = i; m <= i + groundLen; m++)
- {
- yield return null;
- ground_tilemap.SetTile(new Vector3Int(m,j,0),groundTile);
- }
-
- }
- //清除,产生通道,思路就是从底层有方块的地方,开始判断上面。如果没有方块的话,就清除俩层/三层的通道
- IEnumerator ClearChannel(){
- Debug.Log("开始产生通道");
- for (int i = lowerLeftCoo.x; i < (this.length + lowerLeftCoo.x); i++)
- {
- for (int j = lowerLeftCoo.y; j < (this.width + lowerLeftCoo.y-1); j++)//最高层上面必然没有方块,不需要判断,-1
- {
- if (ground_tilemap.GetTile(new Vector3Int(i, j, 0)) != null)//如果此处不为空方块
- {
- if (ground_tilemap.GetTile(new Vector3Int(i, j + 1, 0)) == null)//如果此处上方为空方块
- {
- ground_tilemap.SetTilesBlock(new BoundsInt(i-2, j + 1, 0,3,3,1),new TileBase[] { null,null, null, null, null, null,null, null, null });//将上方3x3格子置空
-
- }
-
-
- }
- yield return null;
-
- }
- }
- Debug.Log("产生通道完成");
- StartCoroutine(GenerateEnviron());
- }
- IEnumerator GenerateEnviron()
- {
- Debug.Log("开始生成花草");
- yield return null;
- for (int i = lowerLeftCoo.x; i < (this.length + lowerLeftCoo.x); i++)
- {
- for (int j = lowerLeftCoo.y; j < (this.width + lowerLeftCoo.y ); j++)
- {
- if (ground_tilemap.GetTile(new Vector3Int(i, j, 0)) ==groundTile&& ground_tilemap.GetTile(new Vector3Int(i, j+1, 0)) == null)//如果此处为地面,上面为空方块
- {
-
- if (Random.value < environmentRich)//随机
- { environ_tilemap.SetTile(new Vector3Int(i, j + 1, 0), environTile); }
- }
- yield return null;
-
- }
- }
-
- }
- }
完成了!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。