包含此页的版本:
不含此页的版本:
创建一个继承自GridBrushBase(或GridBrushBase喜欢GridBrush). 重写新 Brush 类所需的任何方法。以下是您将重写的常用方法:
Paint允许画笔将项目添加到目标网格上。Erase允许画笔从目标网格中删除项目。FloodFill允许画笔将项目填充到目标网格上。Rotate旋转画笔中设置的项目。Flip翻转画笔中设置的项目。使用ScriptableObject.CreateInstance<(Your Brush Class>(). 你可以在编辑器中将此新实例转换为资产,以便通过调用AssetDatabase.CreateAsset().
您还可以为画笔创建自定义编辑器。其工作方式与可编写脚本对象的自定义编辑器相同。以下是创建自定义编辑器时要覆盖的主要方法:
OnPaintInspectorGUI要拥有一个检查器一个Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息OnPaintSceneGUI在SceneView.validTargets以具有画笔可以与之交互的自定义目标列表。此目标列表在 调色板(Palette) 窗口中显示为下拉列表。创建后,可编写脚本笔刷将列在 调色板(Palette) 窗口的 笔刷(Brushes) 下拉菜单中。默认情况下,可编写脚本笔刷脚本的实例将实例化并存储在项目的 库(Library) 文件夹中。对笔刷属性的任何修改都存储在该实例中。如果你想要拥有具有不同属性的该笔刷的多个副本,你可以在项目中将笔刷实例化为资产。这些笔刷资产在 笔刷(Brush) 下拉菜单中单独列出。
您可以添加一个CustomGridBrush属性添加到你的 Scriptable Brush 类中。这允许你在 调色板(Palette) 窗口中配置画笔的行为。 这CustomGridBrush属性具有以下属性:
HideAssetInstances- 将此值设置为 true 以隐藏 调色板(Palette) 窗口中已创建的笔刷资产的所有副本。当你只想在 图块调色板(Tile Palette) 窗口的 笔刷(Brush) 下拉菜单中显示默认实例时,这很有用。HideDefaultInstances- 将此设置为 true 以隐藏 调色板(Palette) 窗口中笔刷的默认实例。当你只想将创建的资产显示在 平铺调色板(Tile Palette) 窗口的 笔刷(Brush) 下拉菜单中时,这非常有用。DefaultBrush- 将此值设置为 true 可将画笔的默认实例设置为项目中的默认画笔。这使此画笔成为项目启动时默认选定的画笔。 注意: 仅将一个可脚本笔刷设置为默认笔刷。设置多个默认笔刷可能会导致可编写脚本笔刷的行为不正确。DefaultName- 为此设置一个名称,让 笔刷(Brush) 下拉菜单使用设置的名称作为笔刷的名称,而不是笔刷类的名称。如果你希望你的可编写脚本笔刷类仅使用某些工具,你可以将BrushTools属性添加到您的类中,并包含兼容的列表TilemapEditorTools类型。 这可确保你的可脚本笔刷仅使用图块面板中的这些特定工具激活工具栏Unity 编辑器顶部的一排按钮和基本控件,允许您以各种方式(例如缩放、翻译)与编辑器进行交互。更多信息
请参阅术语表.
LineBrush提供了轻松地将图块线条绘制到图块贴图一种游戏对象,允许您使用图块和网格叠加层快速创建 2D 关卡。更多信息
请参阅术语表通过指定起点和终点。LineBrush 的 Paint 方法被重写,以允许用户在绘制模式下使用第一次鼠标单击指定线条的开头,并在绘制模式下使用第二次鼠标单击来绘制线条。这OnPaintSceneGUI方法被覆盖以生成要在第一次和第二次鼠标单击之间绘制的线的预览。下面是用于创建画笔的脚本。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace UnityEditor.Tilemaps
{
[CustomGridBrush(true, false, false, "Line Brush")]
public class LineBrush : GridBrush {
public bool lineStartActive = false;
public Vector3Int lineStart = Vector3Int.zero;
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
{
if (lineStartActive)
{
Vector2Int startPos = new Vector2Int(lineStart.x, lineStart.y);
Vector2Int endPos = new Vector2Int(position.x, position.y);
if (startPos == endPos)
base.Paint(grid, brushTarget, position);
else
{
foreach (var point in GetPointsOnLine(startPos, endPos))
{
Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z);
base.Paint(grid, brushTarget, paintPos);
}
}
lineStartActive = false;
}
else
{
lineStart = position;
lineStartActive = true;
}
}
[MenuItem("Assets/Create/Line Brush")]
public static void CreateBrush()
{
string path = EditorUtility.SaveFilePanelInProject("Save Line Brush", "New Line Brush", "Asset", "Save Line Brush", "Assets");
if (path == "")
return;
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<LineBrush>(), path);
}
// http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html
public static IEnumerable<Vector2Int> GetPointsOnLine(Vector2Int p1, Vector2Int p2)
{
int x0 = p1.x;
int y0 = p1.y;
int x1 = p2.x;
int y1 = p2.y;
bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
if (steep)
{
int t;
t = x0; // swap x0 and y0
x0 = y0;
y0 = t;
t = x1; // swap x1 and y1
x1 = y1;
y1 = t;
}
if (x0 > x1)
{
int t;
t = x0; // swap x0 and x1
x0 = x1;
x1 = t;
t = y0; // swap y0 and y1
y0 = y1;
y1 = t;
}
int dx = x1 - x0;
int dy = Math.Abs(y1 - y0);
int error = dx / 2;
int ystep = (y0 < y1) ? 1 : -1;
int y = y0;
for (int x = x0; x <= x1; x++)
{
yield return new Vector2Int((steep ? y : x), (steep ? x : y));
error = error - dy;
if (error < 0)
{
y += ystep;
error += dx;
}
}
yield break;
}
}
[CustomEditor(typeof(LineBrush))]
public class LineBrushEditor : GridBrushEditor
{
private LineBrush lineBrush { get { return target as LineBrush; } }
public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing)
{
base.OnPaintSceneGUI(grid, brushTarget, position, tool, executing);
if (lineBrush.lineStartActive)
{
Tilemap tilemap = brushTarget.GetComponent<Tilemap>();
if (tilemap != null)
tilemap.ClearAllEditorPreviewTiles();
// Draw preview tiles for tilemap
Vector2Int startPos = new Vector2Int(lineBrush.lineStart.x, lineBrush.lineStart.y);
Vector2Int endPos = new Vector2Int(position.x, position.y);
if (startPos == endPos)
PaintPreview(grid, brushTarget, position.min);
else
{
foreach (var point in LineBrush.GetPointsOnLine(startPos, endPos))
{
Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z);
PaintPreview(grid, brushTarget, paintPos);
}
}
if (Event.current.type == EventType.Repaint)
{
var min = lineBrush.lineStart;
var max = lineBrush.lineStart + position.size;
// Draws a box on the picked starting position
GL.PushMatrix();
GL.MultMatrix(GUI.matrix);
GL.Begin(GL.LINES);
Handles.color = Color.blue;
Handles.DrawLine(new Vector3(min.x, min.y, min.z), new Vector3(max.x, min.y, min.z));
Handles.DrawLine(new Vector3(max.x, min.y, min.z), new Vector3(max.x, max.y, min.z));
Handles.DrawLine(new Vector3(max.x, max.y, min.z), new Vector3(min.x, max.y, min.z));
Handles.DrawLine(new Vector3(min.x, max.y, min.z), new Vector3(min.x, min.y, min.z));
GL.End();
GL.PopMatrix();
}
}
}
}
}