版本: 2022.3
语言: 英语
其他有用类
可脚本化画笔

使用提供的示例创建可脚本化瓦片

可脚本化瓦片是可以分配行为 脚本一段代码,允许您创建自己的组件,触发游戏事件,随时间修改组件属性并按您的喜好响应用户输入。更多信息
词汇表
的瓦片,您可以在瓦片地图组件上使用可脚本化瓦片进行绘制。

此页上的代码示例演示了如何创建您自己的可脚本化瓦片以及如何在项目中使用它。 PipelineExampleTile 可脚本化瓦片是可以在瓦片地图上布局自动连接成线的瓦片的示例,这在设计旨在成为道路或管道的瓦片时非常有用。

为您的项目创建可脚本化瓦片
1. 使用脚本创建可脚本化瓦片及其行为
2. 使用可脚本化瓦片进行绘制

先决条件

在执行此任务之前,您必须安装 2D Tilemap Editor 包。此包是 2D功能集 的一部分,如果您在选择创建新项目时选择了2D模板,则将自动安装。您也可以通过 Unity的Package Manager 手动安装此包。

使用脚本创建可脚本化瓦片及其行为

要创建 PipelineExampleTile 可脚本化瓦片并在UnityEditor的 资产 菜单中作为可用选项

  1. 通过访问 Assets > 创建 > 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
}

注意:在保存文件后,Unity编辑器将自动重新编译。

使用可脚本化瓦片进行绘制

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

要使用 PipelineExampleTile 瓦片进行绘制

  1. 创建一个 PipelineExampleTile 瓦片资产(菜单: Assets > 创建 > PipelineExampleTile)。
  2. 选择创建的瓦片资产,并进入其 检查器一个Unity窗口,显示当前选定的GameObject、资产或项目设置的信息,允许您检查和编辑值。更多信息
    词汇表
    窗口。
  3. 根据周围瓷砖的数量,将 PipelineExampleTile 填充精灵。例如,针对单一开口的精灵对于 单数 而针对具有三个开口的精灵对于 三数均在一个开口中注意:使用您自己的精灵时,建议匹配以下示例中显示的位置和方向:
  4. 保存您的项目以保存对瓷砖所做的更改。
  5. 通过将瓷砖从 项目 窗口拖动到 “瓷砖调色板”编辑器窗口 中的瓷砖调色板来添加瓷砖到 “瓷砖调色板”
  6. 使用脚本文档的瓷砖并配合 画笔 工具 在您的 “瓷砖地图”允许您使用瓷砖和网格覆盖快速创建2D级别的GameObject。
    更多信息参考 专业术语
    上绘制。

其他资源

其他有用类
可脚本化画笔