fix:1、添加项目。2、基本箭头生成

This commit is contained in:
2026-06-12 18:10:00 +08:00
commit 2d5012e37e
6588 changed files with 665673 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
using System.Collections.Generic;
using UnityEngine;
namespace EditorTools
{
/// <summary>
/// 编辑器内单个箭头数据
/// </summary>
[System.Serializable]
public class EditorArrowData
{
public int arrowId;
public int startPoint;
public int endPoint;
public string colorHex = "#FFFFFF";
public List<string> pathDirs = new List<string>();
// 路径点位序列 (ID列表)
public List<int> pointIds = new List<int>();
}
/// <summary>
/// 关卡总配置(编辑器用)
/// </summary>
[System.Serializable]
public class EditorLevelData
{
public int levelId = 1001;
public string levelName = "可视化编辑关卡";
public int gridRows = 10;
public int gridCols = 10;
public int pointSpacing = 60;
public List<EditorArrowData> arrows = new List<EditorArrowData>();
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a26e6efd7d7cca34ab027117de8c8caf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+285
View File
@@ -0,0 +1,285 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace EditorTools
{
public class GridPathEditorWindow : EditorWindow
{
private EditorLevelData _levelData = new EditorLevelData();
// 绘制区域参数
private Vector2 _scrollPos;
private const float CellSize = 24f;
private const float DrawOffsetX = 20f;
private const float DrawOffsetY = 20f;
// 当前正在编辑的箭头
private int _curEditArrowIndex = -1;
private List<int> _tempPathPoints = new List<int>();
// 颜色预设
private readonly Color _gridLineColor = new Color(0.4f, 0.4f, 0.4f);
private readonly Color _startCellColor = new Color(0.2f, 0.8f, 0.2f);
private readonly Color _pathCellColor = new Color(0.2f, 0.5f, 1f);
private readonly Color _endCellColor = new Color(1f, 0.4f, 0.2f);
[MenuItem("工具/网格路径配置编辑器")]
public static void OpenWindow()
{
var win = GetWindow<GridPathEditorWindow>("网格路径编辑器");
win.minSize = new Vector2(600, 500);
win.Show();
}
private void OnGUI()
{
EditorGUILayout.BeginVertical("Box");
DrawLevelSetting();
EditorGUILayout.Space();
DrawArrowList();
EditorGUILayout.Space();
DrawGridCanvas();
EditorGUILayout.EndVertical();
}
#region 1.
private void DrawLevelSetting()
{
GUILayout.Label("【关卡基础设置】", EditorStyles.boldLabel);
_levelData.levelId = EditorGUILayout.IntField("关卡ID", _levelData.levelId);
_levelData.levelName = EditorGUILayout.TextField("关卡名称", _levelData.levelName);
EditorGUILayout.BeginHorizontal();
_levelData.gridRows = EditorGUILayout.IntField("网格行数", _levelData.gridRows);
_levelData.gridCols = EditorGUILayout.IntField("网格列数", _levelData.gridCols);
EditorGUILayout.EndHorizontal();
_levelData.pointSpacing = EditorGUILayout.IntField("点位间距(px)", _levelData.pointSpacing);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(" 新增箭头"))
{
AddNewArrow();
}
if (GUILayout.Button("💾 导出JSON"))
{
ExportJson();
}
if (GUILayout.Button("🗑️ 清空当前路径"))
{
_tempPathPoints.Clear();
_curEditArrowIndex = -1;
}
EditorGUILayout.EndHorizontal();
}
#endregion
#region 2.
private void DrawArrowList()
{
GUILayout.Label("【箭头列表(选中后绘制路径)】", EditorStyles.boldLabel);
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.Height(120));
for (int i = 0; i < _levelData.arrows.Count; i++)
{
var arrow = _levelData.arrows[i];
EditorGUILayout.BeginHorizontal("Box");
if (GUILayout.Toggle(_curEditArrowIndex == i, $"ID:{arrow.arrowId}", GUILayout.Width(60)))
{
SelectArrow(i);
}
arrow.colorHex = EditorGUILayout.TextField(arrow.colorHex, GUILayout.Width(80));
EditorGUILayout.LabelField($"起点:{arrow.startPoint} 终点:{arrow.endPoint}", GUILayout.Width(160));
if (GUILayout.Button("删除", GUILayout.Width(50)))
{
_levelData.arrows.RemoveAt(i);
if (_curEditArrowIndex >= _levelData.arrows.Count)
_curEditArrowIndex = -1;
break;
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void AddNewArrow()
{
int newId = _levelData.arrows.Count + 1;
_levelData.arrows.Add(new EditorArrowData
{
arrowId = newId,
colorHex = "#FFFFFF"
});
}
private void SelectArrow(int idx)
{
_curEditArrowIndex = idx;
_tempPathPoints.Clear();
var arr = _levelData.arrows[idx];
_tempPathPoints.AddRange(arr.pointIds);
}
#endregion
#region 3. +
private void DrawGridCanvas()
{
GUILayout.Label("【网格画布 - 点击格子绘制路径】", EditorStyles.boldLabel);
int rows = _levelData.gridRows;
int cols = _levelData.gridCols;
Rect totalRect = EditorGUILayout.GetControlRect(false, (rows + 1) * CellSize);
float startX = totalRect.x + DrawOffsetX;
float startY = totalRect.y + DrawOffsetY;
// 绘制网格 + 监听点击
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
int pointId = LevelJsonExporter.RowColToPointId(r, c, cols);
Rect cellRect = new Rect(
startX + c * CellSize,
startY + r * CellSize,
CellSize - 2,
CellSize - 2
);
// 格子背景色
Color cellColor = Color.white;
if (_tempPathPoints.Count > 0)
{
if (_tempPathPoints[0] == pointId)
cellColor = _startCellColor;
else if (_tempPathPoints[_tempPathPoints.Count - 1] == pointId)
cellColor = _endCellColor;
else if (_tempPathPoints.Contains(pointId))
cellColor = _pathCellColor;
}
// 绘制格子底色
EditorGUI.DrawRect(cellRect, cellColor);
// ===== 纯GUI绘制边框,全版本通用 =====
Color oldColor = GUI.color;
GUI.color = _gridLineColor;
// 上边框
DrawLineGUI(new Vector2(cellRect.xMin, cellRect.yMin), new Vector2(cellRect.xMax, cellRect.yMin));
// 右边框
DrawLineGUI(new Vector2(cellRect.xMax, cellRect.yMin), new Vector2(cellRect.xMax, cellRect.yMax));
// 下边框
DrawLineGUI(new Vector2(cellRect.xMax, cellRect.yMax), new Vector2(cellRect.xMin, cellRect.yMax));
// 左边框
DrawLineGUI(new Vector2(cellRect.xMin, cellRect.yMax), new Vector2(cellRect.xMin, cellRect.yMin));
GUI.color = oldColor;
// 点位ID文字
GUI.color = Color.black;
GUI.Label(cellRect, pointId.ToString(), EditorStyles.miniLabel);
GUI.color = Color.white;
// 鼠标点击
if (Event.current.type == EventType.MouseDown && cellRect.Contains(Event.current.mousePosition))
{
OnCellClick(pointId);
Event.current.Use();
}
}
}
}
// 纯GUI线条绘制(兼容所有Unity版本)
private void DrawLineGUI(Vector2 p1, Vector2 p2)
{
Handles.color = GUI.color;
Handles.DrawAAPolyLine(1, p1, p2);
}
private void OnCellClick(int clickPointId)
{
// 必须先选中一个箭头才能画路径
if (_curEditArrowIndex < 0 || _curEditArrowIndex >= _levelData.arrows.Count)
{
EditorUtility.DisplayDialog("提示", "请先在上方选中一个箭头", "确定");
return;
}
// 1. 空路径 = 设为起点
// 2. 已有点位 = 追加下一个路径点(只能相邻移动)
if (_tempPathPoints.Count == 0)
{
_tempPathPoints.Add(clickPointId);
}
else
{
int lastId = _tempPathPoints[_tempPathPoints.Count - 1];
if (IsAdjacent(lastId, clickPointId, _levelData.gridCols))
{
_tempPathPoints.Add(clickPointId);
}
else
{
EditorUtility.DisplayDialog("提示", "只能点击相邻格子!", "确定");
}
}
// 实时同步到当前箭头数据
SyncTempPathToArrow();
}
/// <summary>判断两个点位是否上下左右相邻</summary>
private bool IsAdjacent(int idA, int idB, int totalCol)
{
LevelJsonExporter.PointIdToRowCol(idA, totalCol, out int r1, out int c1);
LevelJsonExporter.PointIdToRowCol(idB, totalCol, out int r2, out int c2);
int dr = Mathf.Abs(r1 - r2);
int dc = Mathf.Abs(c1 - c2);
return (dr == 1 && dc == 0) || (dr == 0 && dc == 1);
}
/// <summary>临时路径 → 箭头正式数据(自动生成direction、start/end</summary>
private void SyncTempPathToArrow()
{
var arrow = _levelData.arrows[_curEditArrowIndex];
arrow.pointIds.Clear();
arrow.pathDirs.Clear();
arrow.pointIds.AddRange(_tempPathPoints);
if (_tempPathPoints.Count == 0) return;
arrow.startPoint = _tempPathPoints[0];
arrow.endPoint = _tempPathPoints[_tempPathPoints.Count - 1];
// 逐段生成方向列表
for (int i = 0; i < _tempPathPoints.Count - 1; i++)
{
string dir = LevelJsonExporter.GetDirection(_tempPathPoints[i], _tempPathPoints[i + 1], _levelData.gridCols);
if (!string.IsNullOrEmpty(dir))
arrow.pathDirs.Add(dir);
}
}
#endregion
#region 4. JSON
private void ExportJson()
{
if (_levelData.arrows.Count == 0)
{
EditorUtility.DisplayDialog("提示", "暂无箭头数据", "确定");
return;
}
string json = LevelJsonExporter.BuildLevelJson(_levelData);
LevelJsonExporter.SaveToStreamingAssets(json);
EditorUtility.DisplayDialog("导出完成", "JSON 已生成到 StreamingAssets/level_1001.json", "确定");
}
#endregion
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2c9307857b7d4263a329a46d2dda9a31
timeCreated: 1781254588
+106
View File
@@ -0,0 +1,106 @@
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace EditorTools
{
// 导出JSON 根实体
[System.Serializable]
public class ExportLevelRoot
{
public int levelId;
public string levelName;
public int gridRows;
public int gridCols;
public int pointSpacing;
public List<ExportArrowItem> arrows;
}
// 导出JSON 单条箭头实体
[System.Serializable]
public class ExportArrowItem
{
public int id;
public int startPoint;
public int endPoint;
public string color;
public List<string> path;
}
public static class LevelJsonExporter
{
/// <summary>
/// 行列转点位ID(和游戏代码完全一致)
/// </summary>
public static int RowColToPointId(int row, int col, int totalCol)
{
return row * totalCol + col;
}
/// <summary>
/// 点位ID转行列(和游戏代码完全一致)
/// </summary>
public static void PointIdToRowCol(int pointId, int totalCol, out int row, out int col)
{
row = pointId / totalCol;
col = pointId % totalCol;
}
/// <summary>
/// 根据前后两个点位,计算移动方向
/// </summary>
public static string GetDirection(int fromId, int toId, int totalCol)
{
PointIdToRowCol(fromId, totalCol, out int fRow, out int fCol);
PointIdToRowCol(toId, totalCol, out int tRow, out int tCol);
if (tRow < fRow) return "up";
if (tRow > fRow) return "down";
if (tCol < fCol) return "left";
if (tCol > fCol) return "right";
return "";
}
/// <summary>
/// 生成最终JSON字符串(纯实体类序列化,全版本兼容)
/// </summary>
public static string BuildLevelJson(EditorLevelData levelData)
{
ExportLevelRoot root = new ExportLevelRoot();
root.levelId = levelData.levelId;
root.levelName = levelData.levelName;
root.gridRows = levelData.gridRows;
root.gridCols = levelData.gridCols;
root.pointSpacing = levelData.pointSpacing;
root.arrows = new List<ExportArrowItem>();
foreach (var editorArr in levelData.arrows)
{
ExportArrowItem item = new ExportArrowItem();
item.id = editorArr.arrowId;
item.startPoint = editorArr.startPoint;
item.endPoint = editorArr.endPoint;
item.color = editorArr.colorHex;
item.path = new List<string>(editorArr.pathDirs);
root.arrows.Add(item);
}
return JsonUtility.ToJson(root, prettyPrint: true);
}
/// <summary>
/// 保存JSON到StreamingAssets
/// </summary>
public static bool SaveToStreamingAssets(string json, string fileName = "level_1001.json")
{
string folder = Application.streamingAssetsPath;
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
string fullPath = Path.Combine(folder, fileName);
File.WriteAllText(fullPath, json);
Debug.Log($"[导出成功] {fullPath}");
return true;
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3d01c5dd341d401bac259daf47388bee
timeCreated: 1781254572