Unity使用Isometric Z As Y Tilemap创建2.5D地图(三)如何用代码创建Tilemap

  • 创建Tilemap Palette
    • 1.一些需要了解的事情
      • 1.1 UnityEditor代码存放位置
      • 1.2 使用MenuItem添加UnityEditor菜单
    • 2.使用代码创建Palette
    • 3.使用代码在场景中创建Tilemap
    • 4.使用代码在场景Tilemap各层上画地图

   上一篇文档介绍了Unity在使用Isometric Z As Y Tilemap时如何正确处理图片遮挡顺序(《Unity使用Isometric Z As Y Tilemap创建2.5D地图(二)如何按照正确遮挡顺序渲染图片》)。本篇文章将讲解如何使用C#代码方式创建Tilemap、Palette,进行地图绘制。

创建Tilemap Palette

1.一些需要了解的事情

   通常场景地图都是提前在Unity编辑器中提前创建好的,也有根据需要在游戏运行时动态创建的,本例子是在UnityEditor中创建地图内容。

1.1 UnityEditor代码存放位置

   Unity为了避免不必要的包含,Unity3D的运行时类和编辑器类是存储在不同的Assemblies中(UnityEngine和UnityEditor),我们将要编写的编辑器代码通常是需要放在相应工程下的 Assets\Scripts\Editor 目录中。

1.2 使用MenuItem添加UnityEditor菜单

   MenuItem属性允许你添加菜单项到主菜单和检视面板上下文菜单,该属性可以把任意静态函数变为一个可通过菜单调用的命令,仅静态函数能使用MenuItem属性。

   [MenuItem("Tools/Create Palettee")]static void CreatePalettee(){//to do someting}

   在 Assets\Scripts\Editor 目录中新建一个C#类,通过上面代码可以在Unity编辑器的 Tools 菜单中增加一个 Create Palettee的菜单,点击菜单后会执行CreatePalettee()方法。

2.使用代码创建Palette

  首先在 Assets 目录下创建需要存放Palette的目录,例子中是放在Assets/Palette目录下。

  if (!AssetDatabase.IsValidFolder("Assets/Palette")){AssetDatabase.CreateFolder("Assets", "Palette");}if (dir.Exists){/*遍历Resources/images下子目录,可以用不同目录存放不同层的图片比如ground目录下放ground层图片、build目录放build图片等等*/foreach (DirectoryInfo subDir in dir.GetDirectories()){string subPath = "Assets/Palette/" + subDir.Name;if (!AssetDatabase.IsValidFolder(subPath)){AssetDatabase.CreateFolder("Assets/Palette", "" + subDir.Name);}//创建Palette,相关参数含义请参考前面文章GameObject palette = CreateNewPalette("Assets/Palette", subDir.Name, GridLayout.CellLayout.IsometricZAsY,GridPalette.CellSizing.Manual, new Vector3(72f, 36f, 1f), GridLayout.CellSwizzle.XYZ);//准备向Palette中写入地图块对象Tilemap layer1 = palette.GetComponentInChildren<Tilemap>(true);//获取目录下所有图片Sprite[] sprites = Resources.LoadAll<Sprite>("images/" + subDir.Name);int x = 0;int y = 0;for (int i = 0; i < sprites.Length; i++){/*下面这行代码不是必要的,下面会解释。*/Vector2 offset = TextureManager.GetSpriteOffset(sprites[i].name);//在Palette里创建TileTile tile = Tile.CreateInstance<Tile>();switch(subDir.Name){case "ground":tile.colliderType = Tile.ColliderType.None;break;case "build":tile.colliderType = Tile.ColliderType.Grid;break;case "airbuild":tile.colliderType = Tile.ColliderType.None;break;}tile.color = Color.white;tile.sprite = sprites[i];tile.flags = TileFlags.LockColor;tile.name = sprites[i].name;/*下面5行代码不是必要的,用处是设置Palette中Tile默认的transform。此处用来将我读取的图片资源偏移写入Palette的Tile中。*/Matrix4x4 matrix = tile.transform;matrix.m03 = sprites[i].rect.width/2 - offset.x;//xmatrix.m13 = offset.y - sprites[i].rect.height;//ymatrix.m23 = (offset.y - sprites[i].rect.height) * 2;//ztile.transform = matrix;//生成Tile assetstring tilePath = AssetDatabase.GenerateUniqueAssetPath(subPath + "/" + tile.name + ".asset");AssetDatabase.CreateAsset(tile, tilePath);//将Tile写入Pallettelayer1.SetTile(new Vector3Int(x, y, 0), tile);//此处将40个图片放在一行,可根据需要调整y = y + 1;if(y >= 40){x = x + 1;y = 0;}}}AssetDatabase.SaveAssets();}

   上面代码中,Vector2 offset = TextureManager.GetSpriteOffset(sprites[i].name);以及 Matrix4x4相关5行代码不是必要的,但我认为很多时候是很有用的。
   由于我所用资源的图片大小不规则,所以导入资源时需要将图片显示偏移位置加入到Palette的图片中,这样绘制Tilemap地图时才能显示在正确的位置。大家可以根据自己图片需要去掉或调整相关代码。
   Matrix4x4用于矩阵转换,可以用来完成缩放、旋转等作用。这里我们只用到其中3个属性,m03对应坐标X值,m13对应坐标Y值,m23对应坐标Z值。

   代码中Tile.colliderType相关设置,是用来设置Tile的碰撞类型:

属性名 作用描述
Tile.ColliderType.None 无碰撞
Tile.ColliderType.Grid 用网格的outline作为碰撞检测形状
Tile.ColliderType.Sprite 用Sprite outline作为碰撞检测形状

CreateNewPalette方法定义如下:

private static GameObject CreateNewPalette(string folderPath, string name, GridLayout.CellLayout layout, GridPalette.CellSizing cellSizing, Vector3 cellSize, GridLayout.CellSwizzle swizzle)
{GameObject temporaryGO = new GameObject(name);Grid grid = temporaryGO.AddComponent<Grid>();grid.cellSize = cellSize;grid.cellGap = cellSize;grid.cellLayout = layout;grid.cellSwizzle = swizzle;CreateNewLayer(temporaryGO, "Layer1", layout);string path = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + name + ".prefab");UnityEngine.Object prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(temporaryGO, path, InteractionMode.AutomatedAction);GridPalette palette = CreateGridPalette(cellSizing);AssetDatabase.AddObjectToAsset(palette, prefab);PrefabUtility.ApplyPrefabInstance(temporaryGO, InteractionMode.AutomatedAction);AssetDatabase.Refresh();GameObject.DestroyImmediate(temporaryGO);return AssetDatabase.LoadAssetAtPath<GameObject>(path);}

CreateNewLayer方法定义如下:

private static GameObject CreateNewLayer(GameObject paletteGO, string name, GridLayout.CellLayout layout)
{GameObject newLayerGO = new GameObject(name);var tilemap = newLayerGO.AddComponent<Tilemap>();//Sprite Anchor需要根据实际情况调整tilemap.tileAnchor = new Vector3(0, 0, 0);var renderer = newLayerGO.AddComponent<TilemapRenderer>();newLayerGO.transform.parent = paletteGO.transform;newLayerGO.layer = paletteGO.layer;//默认设置switch (layout){case GridLayout.CellLayout.Hexagon:{tilemap.tileAnchor = Vector3.zero;break;}case GridLayout.CellLayout.Isometric:case GridLayout.CellLayout.IsometricZAsY:{renderer.sortOrder = TilemapRenderer.SortOrder.TopRight;break;}}return newLayerGO;
}

GridPalette 方法定义如下:

private static GridPalette CreateGridPalette(GridPalette.CellSizing cellSizing)
{var palette = GridPalette.CreateInstance<GridPalette>();palette.name = "Palette Settings";palette.cellSizing = cellSizing;return palette;
}

3.使用代码在场景中创建Tilemap

首先在场景中创建Tilemap对象,主要代码如下:

  //在场景中创建Tilemap Grid,这里命名为TilemapRoot,可根据需要调整。GameObject tilemap = new GameObject("TilemapRoot");Grid grid = tilemap.AddComponent<Grid>();grid.cellSize = new Vector3(72, 36, 1);grid.cellLayout = GridLayout.CellLayout.IsometricZAsY;grid.cellSwizzle = GridLayout.CellSwizzle.XYZ;

在Tilemap对象下根据需要创建多层Tilemap Layer。我这里创建了地面层、建筑层、空中层、碰撞层,可根据实际情况调整。主要代码如下:

  //创建ground tilemapTilemap groundLayer = CreateTilemapLayer("ground", tilemap, Vector3.zero,"Ground",0);Tilemap buildLayer = CreateTilemapLayer("build", tilemap, Vector3.zero, "Build", 1);Tilemap airbuildLayer = CreateTilemapLayer("airbuild", tilemap, Vector3.zero, "Build", 1);Tilemap colliderLayer = CreateTilemapLayer("collider", tilemap, Vector3.zero, "Ground", 0);//为碰撞层添加TilemapCollider2D组件,否则碰撞无法触发。TilemapCollider2D collider = colliderLayer.gameObject.AddComponent<TilemapCollider2D>();collider.usedByComposite = true;//此为碰撞形状偏移,可以使用默认没有偏移,或者根据需要设置。collider.offset = new Vector2(-2, 26);

CreateTilemapLayer类定义如下:

private static Tilemap CreateTilemapLayer(string name,GameObject parent, Vector3 anchor,string sortingLayerName,int sortOrderInLayer)
{GameObject layer = new GameObject(name);Tilemap layerTilemap = layer.AddComponent<Tilemap>();layerTilemap.tileAnchor = anchor;TilemapRenderer tilemapRenderer = layer.AddComponent<TilemapRenderer>();tilemapRenderer.sortOrder = TilemapRenderer.SortOrder.TopRight;tilemapRenderer.mode = TilemapRenderer.Mode.Individual;tilemapRenderer.sortingLayerName = sortingLayerName;tilemapRenderer.sortingOrder = sortOrderInLayer;layer.transform.parent = parent.transform;return layerTilemap;
}

4.使用代码在场景Tilemap各层上画地图

使用上一章定义的Tilemap Layer上画地图了,主要涉及代码如下:

  //可以直接通过加载之前创建的Palette Tile资源画图。举例如下:Tile tile = AssetDatabase.LoadAssetAtPath<Tile>("Assets/Palette/ground/0.asset");if (tile!=null){tile = GameObject.Instantiate(tile);//准备要画图的网格位置Vector3Int position = new Vector3Int(x,y,1);//下面4行代码不是必要的,可以根据需要动态调整场景中图片显示的x、y、z值。Matrix4x4 pos = tile.transform;pos.m13 = pos.m13 + offsetHeight[i-1, j, k];pos.m23 = pos.m23 + (offsetHeight[i - 1, j, k] - 1) * 2;tile.transform = pos;//在对应Tilemap Layer图层中画图tilemapLayer.SetTile(position, tile);}

   上面Matrix4x4 pos相关代码不是必要的,但根据我的图片资源情况是很有用的,可以根据实际需要调整对应网格图片显示的X、Y、Z值。根据前面的文章可以知道,这对于正确显示地图图片和调整图片遮挡关系是很有必要的。


   好了,有了以上主要代码,大家就可以根据自己需要通过代码自动创建Tilemap Palette调色板和地图的。代码中有不对的地方请务必指正。

Unity使用Isometric Z As Y Tilemap创建2.5D地图(三)如何用代码创建Tilemap相关推荐

  1. Unity使用Isometric Z As Y Tilemap创建2.5D地图(一)如何创建Tilemap

    Unity2019使用Isometric Z as Y Tilemap创建2.5D地图 (一)创建Tilemap 1.Tilemap的类型 2.新建Isometric Z As Y Tilemap 2 ...

  2. Unity使用Isometric Z As Y Tilemap创建2.5D地图(二)如何按照正确遮挡顺序渲染图片

    Unity使用Isometric Z As Y Tilemap创建2.5D地图(二)如何按照正确遮挡顺序渲染图片 如何按照正确遮挡顺序渲染图片 1.创建多层Tilemap 2.使用Sorting La ...

  3. vscode如何创建一个go项目_如何用手机创建一个网站

    如何用手机创建网站?其实正确的说法是如何创建一个手机网站才对,因为很难用手机去制作网站,很不方便.一般是用电脑模拟手机去建网站. 我们知道现在很多人上网都是通过手机上网,所以我们自己建网站时,也要学会 ...

  4. Unity创建2.5D地图 【1】

    打开unity 1.创建Hierarchy→2D Object→TileMap 2.创建完成后,TileMap位于Grid下,选择Grid,切换Cell Layout的值,有以下类型可选. 第一个看上 ...

  5. unity如何用代码创建自已的logo

    首先创建一个场景用于进入游戏的logo.如图: Canvas 画布下有两个ui.image个是黑色的背景.logo 我自已设置的是一个text UI ,这里我先将它的color的透明度调为0现在是看不 ...

  6. 如何在Vue项目中引入ArcGIS JavaScript API​ 创建三维可视化地图(含vue项目创建教程)

    新手上路之在Vue项目中引入ArcGIS API​ 视频教程 B站搜索 X北辰北,感谢up主无私的教学~ B站地址:https://www.bilibili.com/video/BV18E411K7B ...

  7. ae 创建图像等高线 蒙版_如何用AE创建简单的UI动效

    工具 After Effects CS6 or CC Photoshop CS6 or CC 设计流程 After Effects 在一个合成中创建转场效果 另外一个合成中创建展示效果 导出 Phot ...

  8. Unity Tilemap动态生成2d地图

    Unity Tilemap动态生成2d地图 (参考链接) rule tile 动态生成地图:https://blog.csdn.net/mkr67n/article/details/108340749 ...

  9. unity mega_[MEGA DEAL] Unity A至Z游戏开发套件(96%折扣)

    unity mega 涵盖游戏开发的所有方面(83小时!),从Unity中的编码到在Blender中设计3D资产 嘿,怪胎, 本周,在我们的JCG Deals商店中 ,我们提供了另一个超值优惠 . 我 ...

最新文章

  1. 利用Python基础代码语句,实现2G时代文字小游戏,世界如此简单
  2. qt on android qml,Qt on Android: Qt Quick 之 Hello World 图文详解
  3. 轴等比缩放_CAD教程:自由缩放命令的操作流程
  4. 工业利用计算机实现生产自动化属于,自动化考试试题(含答案)
  5. 保存点云数据_PCL入门系列三——PCL进行数据读写
  6. LeetCode 2020 力扣杯全国春季编程大赛(1644/4093,前40.2%)
  7. page对保护的作用
  8. DataList控件DataKeyField以及DataKeys区别
  9. BZOJ4423: [AMPPZ2013]Bytehattan
  10. 整理一些MongoDB常用数据库命令
  11. 【HDU6286】2018(容斥)
  12. java调用tuxedo中间件_初探TUXEDO中间件
  13. 双厨狂喜!海盗船机械键盘联名石之海,一起欧拉欧拉!
  14. 屏幕坐标转换成threejs的坐标
  15. 贪心算法 看这一篇就够了
  16. 世界上最神奇的网站收录--不是最无聊就是最有意思
  17. mysql特性绕过安全狗_【经验总结】SQL注入Bypass安全狗360主机卫士
  18. 《程序员拒绝一个合理需求的15个方法!》
  19. 什么是智能制造成能力成熟度模型?
  20. 20230326作业

热门文章

  1. Day21 jQuery 基础二
  2. 1转自 饮水思源 bbs.sjtu.edu.cn·[FROM: 202.120.25.97]
  3. 组装台式计算机的流程,如何组装电脑?组装电脑的操作流程!
  4. 关于计算机专业演讲稿,计算机专业组长竞聘演讲稿
  5. Makefile详解——从入门到精通
  6. 贵金属实时行情看盘软件排行榜(top 10)
  7. 美国OFAC发布针对个人的“网络安全相关处罚”规则
  8. 自制Arduino Leonardo笔记
  9. uni-app 微信小程序 腾讯地图选点插件
  10. esp32,基于阿里云平台,配置实现Node.js SDK接入示例出现description: ‘Failed to authenticate: 4‘ BUG