Version: Unity 6.0 (6000.0)
语言 : 中文
可编程瓦片
图块资源参考

创建可编程瓦片

本页面的代码示例展示了创建可编程瓦片的方法,以及在项目中的使用方法。PipelineExampleTile 可编程瓦片为瓦片示例,用于在瓦片地图上使用线性分段,并在绘制时自动连接。其可用于设计用作道路或管道的瓦片。

为项目创建可编程瓦片:

  1. 使用脚本创建可编程瓦片及其行为
  2. 使用可编程瓦片进行绘制

先决条件

在继续执行任务之前,必须拥有 2D Tilemap Editor 包。此包为 2D 功能集的一部分,如果在创建新项目时选择 2D 模板,则该功能集会自动进行安装。还可以通过 Unity 的包管理器手动安装此包。

使用脚本创建可编程瓦片

创建 PipelineExampleTile 可编程瓦片并将其作为 Unity 编辑器的资源 (Asset) 菜单中的可用选项:

  1. 转到 资源 (Assets) > 创建 (Create) > MonoBehaviour 脚本 (MonoBehaviour Script),创建空白 MonoBehaviour 脚本。
  2. 将文件命名为 PipelineExampleTile.cs
  3. 在文本编辑器中打开文件。
  4. 将现有代码替换为以下内容,然后保存文件:
using System;

#if UNITY_EDITOR
using UnityEditor;
#endif


namespace UnityEngine.Tilemaps
{
   /// <summary>
   /// Pipeline Tiles are tiles which take into consideration its orthogonal neighboring tiles and displays a sprite depending on whether the neighboring tile is the same tile.
   /// </summary>
   [Serializable]
   public class PipelineExampleTile : TileBase
   {
       /// <summary>
       /// The Sprites used for defining the Pipeline.
       /// </summary>
       [SerializeField]
       public Sprite[] m_Sprites;


       /// <summary>
       /// This method is called when the tile is refreshed. The PipelineExampleTile will refresh all neighboring tiles to update their rendering data if they are the same tile.
       /// </summary>
       /// <param name="position">Position of the tile on the Tilemap.</param>
       /// <param name="tilemap">The Tilemap the tile is present on.</param>
       public override void RefreshTile(Vector3Int position, ITilemap tilemap)
       {
           for (int yd = -1; yd <= 1; yd++)
               for (int xd = -1; xd <= 1; xd++)
               {
                   Vector3Int pos = new Vector3Int(position.x + xd, position.y + yd, position.z);
                   if (TileValue(tilemap, pos))
                       tilemap.RefreshTile(pos);
               }
       }


       /// <summary>
       /// Retrieves any tile rendering data from the scripted tile.
       /// </summary>
       /// <param name="position">Position of the tile on the Tilemap.</param>
       /// <param name="tilemap">The Tilemap the tile is present on.</param>
       /// <param name="tileData">Data to render the tile.</param>
       public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
       {
           UpdateTile(position, tilemap, ref tileData);
       }


       /// <summary>
       /// Checks the orthogonal neighbouring positions of the tile and generates a mask based on whether the neighboring tiles are the same. The mask will determine the according Sprite and transform to be rendered at the given position. The Sprite and Transform is then filled into TileData for the Tilemap to use. The Flags lock the color and transform to the data provided by the tile. The ColliderType is set to the shape of the Sprite used.
       /// </summary>
       private void UpdateTile(Vector3Int position, ITilemap tilemap, ref TileData tileData)
       {
           tileData.transform = Matrix4x4.identity;
           tileData.color = Color.white;


           int mask = TileValue(tilemap, position + new Vector3Int(0, 1, 0)) ? 1 : 0;
           mask += TileValue(tilemap, position + new Vector3Int(1, 0, 0)) ? 2 : 0;
           mask += TileValue(tilemap, position + new Vector3Int(0, -1, 0)) ? 4 : 0;
           mask += TileValue(tilemap, position + new Vector3Int(-1, 0, 0)) ? 8 : 0;


           int index = GetIndex((byte)mask);
           if (index >= 0 && index < m_Sprites.Length && TileValue(tilemap, position))
           {
               tileData.sprite = m_Sprites[index];
               tileData.transform = GetTransform((byte)mask);
               tileData.flags = TileFlags.LockTransform | TileFlags.LockColor;
               tileData.colliderType = Tile.ColliderType.Sprite;
           }
       }


       /// <summary>
       /// Determines if the tile at the given position is the same tile as this.
       /// </summary>
       private bool TileValue(ITilemap tileMap, Vector3Int position)
       {
           TileBase tile = tileMap.GetTile(position);
           return (tile != null && tile == this);
       }


       /// <summary>
       /// Determines the index of the Sprite to be used based on the neighbour mask.
       /// </summary>
       private int GetIndex(byte mask)
       {
           switch (mask)
           {
               case 0: return 0;
               case 3:
               case 6:
               case 9:
               case 12: return 1;
               case 1:
               case 2:
               case 4:
               case 5:
               case 10:
               case 8: return 2;
               case 7:
               case 11:
               case 13:
               case 14: return 3;
               case 15: return 4;
           }
           return -1;
       }


       /// <summary>
       /// Determines the Transform to be used based on the neighbour mask.
       /// </summary>
       private Matrix4x4 GetTransform(byte mask)
       {
           switch (mask)
           {
               case 9:
               case 10:
               case 7:
               case 2:
               case 8:
                   return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -90f), Vector3.one);
               case 3:
               case 14:
                   return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -180f), Vector3.one);
               case 6:
               case 13:
                   return Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -270f), Vector3.one);
           }
           return Matrix4x4.identity;
       }
   }
  
#if UNITY_EDITOR
   /// <summary>
   /// Custom Editor for a PipelineExampleTile. This is shown in the Inspector window when a PipelineExampleTile asset is selected.
   /// </summary>
   [CustomEditor(typeof(PipelineExampleTile))]
   public class PipelineExampleTileEditor : Editor
   {
       private PipelineExampleTile tile { get { return (target as PipelineExampleTile); } }


       public void OnEnable()
       {
           if (tile.m_Sprites == null || tile.m_Sprites.Length != 5)
               tile.m_Sprites = new Sprite[5];
       }


       /// <summary>
       /// Draws an Inspector for the PipelineExampleTile.
       /// </summary>
       public override void OnInspectorGUI()
       {
           EditorGUILayout.LabelField("Place sprites shown based on the number of tiles bordering it.");
           EditorGUILayout.Space();
          
           EditorGUI.BeginChangeCheck();
           tile.m_Sprites[0] = (Sprite) EditorGUILayout.ObjectField("None", tile.m_Sprites[0], typeof(Sprite), false, null);
           tile.m_Sprites[2] = (Sprite) EditorGUILayout.ObjectField("One", tile.m_Sprites[2], typeof(Sprite), false, null);
           tile.m_Sprites[1] = (Sprite) EditorGUILayout.ObjectField("Two", tile.m_Sprites[1], typeof(Sprite), false, null);
           tile.m_Sprites[3] = (Sprite) EditorGUILayout.ObjectField("Three", tile.m_Sprites[3], typeof(Sprite), false, null);
           tile.m_Sprites[4] = (Sprite) EditorGUILayout.ObjectField("Four", tile.m_Sprites[4], typeof(Sprite), false, null);
           if (EditorGUI.EndChangeCheck())
               EditorUtility.SetDirty(tile);
       }


       /// <summary>
       /// The following is a helper that adds a menu item to create a PipelineExampleTile Asset in the project.
       /// </summary>
       [MenuItem("Assets/Create/PipelineExampleTile")]
       public static void CreatePipelineExampleTile()
       {
           string path = EditorUtility.SaveFilePanelInProject("Save Pipeline Example Tile", "New Pipeline Example Tile", "Asset", "Save Pipeline Example Tile", "Assets");
           if (path == "")
               return;                           
           AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<PipelineExampleTile>(), path);
        }
   }
#endif
}

现在,可以使用 ScriptableObject.CreateInstance<YOUR_TILE_CLASS>() 在任何需要使用可编程瓦片的位置创建新类的实例。可通过调用 AssetDatabase.CreateAsset() 将此新实例转换为编辑器中的资源以便重复使用。

使用可编程瓦片进行绘制

PipelineExampleTile.cs脚本导入或保存到项目中后,您将能够创建 PipelineExampleTile 瓦片资源。

使用 PipelineExampleTile 瓦片进行绘制:

  1. 创建 PipelineExampleTile 瓦片资源(菜单:资源 (Assets) > 创建 (Create) > PipelineExampleTile)。

  2. 选择创建的瓦片资源,然后转到其检视视图 (Inspector) 窗口。

  3. 根据其边缘的瓦片数量,为 PipelineExampleTile 添加精灵。例如,One 的精灵有一个开口,而 Three 的精灵在其精灵的边缘有三个开口。注意:使用精灵时,建议与以下示例中显示的位置和方向匹配:

  4. 保存项目以保存对瓦片进行的更改。

  5. 将瓦片资源从项目 (Project) 窗口拖动到瓦片面板编辑器 (Tile Palette Editor) 窗口中的瓦片面板 (Tile Palette),即可将瓦片添加到瓦片面板

  6. 使用绘图 (Paint) 工具与可编程瓦片即可在瓦片地图上进行绘制。

其他资源

可编程瓦片
图块资源参考
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961