包含此页的版本:
不含此页的版本:
本页上的代码示例演示了如何创建自己的可编写脚本磁贴,以及如何在项目中使用它。这PipelineExampleTile可编写脚本的图块是图块的一个示例,可用于将线性线段布局到图块地图上,这些线段在绘制时自动连接起来。这对于设计道路或管道的瓷砖非常有用。
要为项目创建可编写脚本的磁贴,请执行以下作:
在继续执行任务之前,您必须安装 2D 切片地图编辑器包。此包是 2D 功能集的一部分,如果您在创建新项目时选择其中一个 2D 模板,则会自动安装。您也可以通过 Unity 的包管理器手动安装此包。
要创建PipelineExampleTile可编写脚本的磁贴,并将其作为 UnityEditor 的 Asset 菜单中的可用选项:
PipelineExampleTile.cs.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 磁贴进行绘制,请执行以下作:
创建 PipelineExampleTile 磁贴资产(菜单:资产>创建> PipelineExampleTile)。
选择创建的磁贴资产,然后转到其检查器一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息
请参阅术语表窗。
填写PipelineExampleTile根据其边界的图块数量使用精灵。例如,sprite2D 图形对象。如果你习惯于在3D中工作,精灵本质上只是标准纹理,但有一些特殊的技术可以组合和管理精灵纹理,以提高开发过程中的效率和便利性。更多信息
请参阅术语表因为 One 有一个开口,而 Three 的精灵沿着精灵的边缘有三个开口。注意:使用自己的 Sprite 时,建议匹配以下示例中显示的位置和方向:
保存项目以保存对磁贴所做的更改。
将图块资源从 项目(Project) 窗口拖到 图块面板(Tile Palette) 编辑器窗口中的图块面板(Tile Palette) 上,将图块添加到图块面板。
使用“绘制”工具与可编写脚本的图块进行绘画tilemap一种游戏对象,允许您使用图块和网格叠加层快速创建 2D 关卡。更多信息
请参阅术语表.