Unity提供全套的Tile工具来编辑2D地图。使用Tile编辑地图,可以极大地减少内存的占用。美术人员只需要小格式地图,并且保证可以相互拼接接口,策划人员最终将这些小格子元素编辑在一起。灵活的拼接可以生成很多不同的2D地图。使用Tile之前请确保安装Tilemap Editor包
创建Tile 创建tile之前,需要确认Tile的大小,一般是32和64。
首先要将需要使用的tile按照大小设置Pixel Per Unit,然后按照Multiple Sprite Mode切分,还要把Filter Mode改为Point,把Compression设为None
在Hierarchy视图中创建TileMap游戏对象。选择Create——2D Object——TileMap命令。
此时场景中将出现一个Grid对象并且它下面套着TileMap对象。Grid就是Tile的画布,它可以设置画布每个单元的大小。由于前面Pixels Per Unit已经设置成32,所以这里默认填1就好了。Cell GAP可以设置每个单元之间的间距,一般都设置成0就好。最后的Cell Swizzle用于设置Grid布局的朝向,而XYZ表示斜角为45°的2D游戏?
Grid对象下面就是TIlemap了。它可以设置动画帧率(tilemap的动画需要配合tilemap extra package,这在Unity2020中是一个preview版本的package)、锚点和朝向等信息。Tilemap Renderer组件和Sprite Renderer很像,可以设置排序和遮罩等。
Tile Palette 接着,需要将可编辑的Sprite汇总在Tile Palette面板中,在Hierarchy窗口点击Grid,在Scene窗口直接点击“Open Tile Palette”。在Tile Palette窗口中,点击
Create New Palette可以创建多个调色板。根据不同风格需要创建多个调色板。
最后将需要编辑的sprite资源直接拖入相应的Palette就可以自动生成Tile了。
同一Grid中可能会有多个Tilemap,例如背景层和前景层,在Active Tilemap下拉框中选择当前grid下的对应tilemap,方便互相切换编辑
Palette也是可以编辑的,点击edit进入调色板编辑模式,修改后按Ctrl S保存退出Palette编辑
编辑Tile Tile Palette工具栏中,工具从左到右一次如下
点选工具(S):可以选择某一个Tile。
移动工具(M):当使用点选工具选择一个Tile时,可以使用此工具移动Tile的位置。
画笔工具(B):选择一个TIle,在Scene视图中刷
区域工具(U):按住左键框选刷多个区域
吸图工具(I):吸取Scene中某个或某一些Tile的图,然后编辑
橡皮工具(D):删除Scene中不需要的Tile。
批量填充工具(G):大规模填充Tile。
多Tile编辑与排序 在普通的2D游戏场景中,至少需要2个Tile层,前景层和背景层。比如一棵树,上半部分是树叶(前景层),下半部分是树干(背景层),这样人物在树附近上下移动的时候,走到树下应该自己要挡住树干,走到树上面应该被树叶挡住自己。
在Tile Palette面板中切换当前需要编辑的Tilemap时,可以在Scene视图选择Focus On Tilemap,这样就可以突出显示正在编辑的Tilemap了。
拓展Tile Palette Unity提供了Tile Palette的拓展编辑功能,可以重写画笔的任意行为。
新添加的Tile 画笔要继承GridBrush,如果画笔需要复用,还支持可以添加配置参数的画笔。
首先在Editor文件夹下,新建CustomBrush
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 using UnityEngine;using UnityEditor;using System;using UnityEditor.Tilemaps;[CustomGridBrush(false,true,false,"Custom Brush" ) ] public class CustomBrush : GridBrush { public new string name; public override void Paint (GridLayout gridLayout, GameObject brushTarget, Vector3Int position ) { if (EditorUtility.DisplayDialog("重要提示" ,string .Format("确认笔刷:{0} {1}" ,gridLayout.name,position),"ok" ) ){ base .Paint(gridLayout, brushTarget, position); } } [MenuItem("Assets/Create/2D/Tile Palette/CustomBrush" ) ] public static void CreateCustomBrush () { string path = EditorUtility.SaveFilePanelInProject("Save CustomBrush" , "New CustomBrush" , "Asset" , "Save CustomBrush" , "Assets" ); if (path == "" ) return ; AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<CustomBrush>(), path); } } [CustomEditor(typeof(CustomBrush)) ] public class CustomBrushEditor : GridBrushEditor { protected override void OnEnable () { base .OnEnable(); Debug.Log((target as CustomBrush).name); } public override void OnPaintSceneGUI (GridLayout gridLayout, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing ) { base .OnPaintSceneGUI(gridLayout, brushTarget, position, tool, executing); Handles.color = Color.red; GUIStyle style = new GUIStyle(); style.normal.textColor = Color.red; style.fontSize = 20 ; Handles.Label(gridLayout.CellToWorld(new Vector3Int(position.x, position.y, 0 )), position.center.ToString(), style); } }
然后我们在“Assets/Create/2D/Tile Palette/CustomBrush”中点击,就会弹出保存自定义笔刷位置的窗口,我们选定好位置保存
然后在Project文件夹中点击,就会打出我们自定义的参数
选中自定义笔刷然后在场景中会显示位置,点击绘制会弹出确定信息
Handles
类是UnityEditor提供的渲染辅助类,Handles.Label()
表示在Scene窗口中渲染出一个文本信息
拓展Tile TIle实际上就是一个序列化的asset资源文件,默认的Tile里面记录着它引用的sprite、颜色和碰撞类型等。
如果不满足默认的需求,我们还可以继承它并且重写Tile基类的一些重要回调方法。
首先在Editor文件夹下,新建CustomTile
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 using UnityEngine;using UnityEngine.Tilemaps;#if UNITY_EDITOR using UnityEditor;#endif public class CustomTile : Tile { public override void RefreshTile (Vector3Int position, ITilemap tilemap ) { base .RefreshTile(position, tilemap); } public override void GetTileData (Vector3Int position, ITilemap tilemap, ref TileData tileData ) { base .GetTileData(position, tilemap, ref tileData); } public override bool GetTileAnimationData (Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData ) { return base .GetTileAnimationData(position, tilemap, ref tileAnimationData); } public override bool StartUp (Vector3Int position, ITilemap tilemap, GameObject go ) { return base .StartUp(position, tilemap, go); } #if UNITY_EDITOR [MenuItem("Assets/Create/2D/Tile Palette/CustomTile" ) ] public static void CreateRoadTile () { string path = EditorUtility.SaveFilePanelInProject("Save Custom Tile" , "New CustomTile" , "Asset" , "Save Custom Tile" , "Assets" ); if (path == "" ) return ; AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<CustomTile>(), path); } #endif }
更新TIle 更新Tile就是调用tilemap.GetTile()
和tilemap.SetTile()
方法。和2D精灵一样,TIle的坐标原点也是屏幕的正中心点。
我们控制人物在屏幕中移动来“吃豆豆”,代码如下所示(注意人物要使用上一节的移动代码)
新建TIlemapRefresh
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using UnityEngine;using UnityEngine.Tilemaps;public class TIleMapRefresh : MonoBehaviour { public SpriteRenderer spriteRenderer; public Tilemap tilemap; private void Update () { Vector3Int cellpos = tilemap.WorldToCell(spriteRenderer.transform.position); if (tilemap.GetTile(cellpos) != null ) { tilemap.SetTile(cellpos, null ); } } }