上方菜单
cs
[MenuItem("工具栏选项名")]
static void XXX(){
}
弹窗
下面演示了在弹窗上点击一个按钮,出现文件浏览器,且只显示xlsx文件,很有用。
cs
public class PopWindow : EditorWindow
{
[MenuItem("我的工具/弹窗")]
static void OpenWindow(){
GetWindow<PopWindow>(false,"我的弹窗",true);
}
void OnGUI(){
EditorGUILayout.LabelField("Excel路径", ExcelPath);
if (GUILayout.Button("选择Excel文件"))
{
ExcelPath = EditorUtility.OpenFilePanel("选择Excel文件",
Application.dataPath + "/..", "xlsx");
}
}
static string ExcelPath;
}
自定义检查器
cs
[CustomEditor(typeof(XXX))]
public class MyXXXEditor : Editor
{
XXX _component;
void OnEnable(){
_component=target as XXX;
}
void OnDisable(){
_component=null;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
}
}
Hierarchy窗口增加选项
cs
[MenuItem("GameObject/选项")]
static void XXX(){
}
Project窗口增加选项
cs
[MenuItem("Assets/选项")]
static void XXX(){
}
在Add Component菜单增加选项
cs
[AddComponentMenu("选项/选项2")]
public class XXX:MonoBehaviour{
}
在组件右键菜单增加选项
cs
[MenuItem("CONTEXT/脚本名/选项")]
static void XXX(){
}
Excel导表工具(弹窗式)
生成C#数据类,把Excel配表二进制序列化存储
cs
using Excel;
using Mercenaria;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.IO.Pipes;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEditor;
using UnityEngine;
using static UnityEngine.EventSystems.EventTrigger;
using static UnityEngine.Rendering.DebugUI;
public class MyExcelTool : EditorWindow
{
[MenuItem("我的工具/Excel导表工具")]
static void OpenWindow(){
GetWindow<MyExcelTool>(false, "Excel导表工具", true);
}
void OnGUI() {
EditorGUILayout.LabelField("Excel路径", ExcelPath);
if (GUILayout.Button("选择Excel文件"))
{
ExcelPath = EditorUtility.OpenFilePanel("选择Excel文件",
Application.dataPath + "/..", "xlsx");
}
NAMESPACE = EditorGUILayout.TextField("命名空间", NAMESPACE);
FieldNameRow = EditorGUILayout.IntField("变量名所在行", FieldNameRow);
TypeRow = EditorGUILayout.IntField("类型所在行", TypeRow);
KeyMarkRow = EditorGUILayout.IntField("key标记所在行", KeyMarkRow);
ContentStartRow = EditorGUILayout.IntField("内容开始行", ContentStartRow);
DataClassName = EditorGUILayout.TextField("数据类名", DataClassName);
OutputCsPath = EditorGUILayout.TextField("数据类生成路径", OutputCsPath);
if (GUILayout.Button("生成C#数据类"))
{
GenerateDataClass();
}
OutputBinPath = EditorGUILayout.TextField("二进制导出路径", OutputBinPath);
if (GUILayout.Button("Excel表导出为自定义二进制"))
{
ExcelToBin();
}
if (GUILayout.Button("生成对话配置文件"))
{
ExportTalk();
}
if (GUILayout.Button("读取并打印对话配置文件"))
{
PrintTalk();
}
}
static int FieldNameRow = 0;//第几行是字段名
static int TypeRow = 1;//第几行是类型名
static int KeyMarkRow = 2;//第几行标记key
static int ContentStartRow = 4;//从第几行数据开始
static string ExcelPath;
static string OutputBinPath = Application.streamingAssetsPath + "/Config";
static string OutputCsPath = $"{Application.dataPath}/Scripts/Data1.cs";
static string NAMESPACE = "Mercenaria";
static string DataClassName;
static void ExcelToBin()
{
using (FileStream excelStream = File.Open(ExcelPath,
FileMode.Open, FileAccess.Read),
outputStream = new FileStream
(OutputBinPath, FileMode.OpenOrCreate, FileAccess.Write))
{
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(excelStream);
DataSet dataSet = reader.AsDataSet();
DataTable table = dataSet.Tables[0];
int dataRowNum = table.Rows.Count - ContentStartRow;
outputStream.Write(BitConverter.GetBytes(dataRowNum), 0, 4);
DataRow fieldRow = table.Rows[FieldNameRow];
DataRow typeRow = table.Rows[TypeRow];
DataRow row;
for (int i = ContentStartRow; i < table.Rows.Count; i++)
{
row = table.Rows[i];
for (int j = 0; j < table.Columns.Count; j++)
{
string val = row[j].ToString();
Debug.Log(val);
switch (typeRow[j].ToString())
{
case "int":
outputStream.Write(
BitConverter.GetBytes(int.Parse(val)), 0, 4);
break;
case "float":
outputStream.Write(
BitConverter.GetBytes(float.Parse(val)), 0, 4);
break;
case "bool":
outputStream.Write(BitConverter.GetBytes(bool.Parse(val)), 0, 1);
break;
case "string":
StringToStream(outputStream, val);
break;
}
}
}
outputStream.Close();
excelStream.Close();
AssetDatabase.Refresh();
}
}
static void GenerateDataClass()
{
using (FileStream excelStream = File.Open(ExcelPath,
FileMode.Open, FileAccess.Read))
{
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(excelStream);
DataSet dataSet = reader.AsDataSet();
DataTable table = dataSet.Tables[0];
DataRow fieldRow = table.Rows[FieldNameRow];
DataRow typeRow = table.Rows[TypeRow];
string className = DataClassName == null || DataClassName == "" ? table.TableName : DataClassName;
StringBuilder builder = new StringBuilder($"namespace {NAMESPACE}{{\n\tpublic class {className}{{\n");
for (int i = 0; i < table.Columns.Count; i++)
{
builder.Append($"\t\tpublic {typeRow[i]} {fieldRow[i]};\n");
}
builder.Append("\t}\n}");
File.WriteAllText(OutputCsPath, builder.ToString());
excelStream.Close();
}
AssetDatabase.Refresh();
}
static void StringToStream(Stream stream, string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
stream.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
stream.Write(bytes, 0, bytes.Length);
}
[MenuItem("我的工具/读取配置")]
static void ReadConfig()
{
Dictionary<int, GunConfigEx> dic = MyConfigManager.Instance.LoadConfig<GunConfigEx>(
MyConfigManager.OutputPath);
foreach (KeyValuePair<int, GunConfigEx> pair in dic)
{
Debug.Log(pair.Value.name);
Debug.Log(pair.Value.desc);
}
}
static void ExportTalk()
{
using (FileStream excelStream = File.Open(ExcelPath,
FileMode.Open, FileAccess.Read),
outputStream = new FileStream
(OutputBinPath, FileMode.OpenOrCreate, FileAccess.Write))
{
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(excelStream);
DataSet dataSet = reader.AsDataSet();
Debug.Log($"读取Excel{reader},它有{dataSet.Tables.Count}个sheet");
TalkConfig talkConfig = new TalkConfig();
for (int i = 0; i < dataSet.Tables.Count; i++)
{//一个sheet是一段对话
DataTable table = dataSet.Tables[i];
if (!talkConfig.talkDic.ContainsKey(table.TableName))
{
List<SentenceEntry>sentences= new List<SentenceEntry>();
DataRow row;
Debug.Log(table.Rows.Count);
for (int j = ContentStartRow; j < table.Rows.Count; j++)
{
row = table.Rows[j];
SentenceEntry entry = new SentenceEntry();
//这样赋值写,通过报错能看出哪个字段失败了。直接初始化不行
entry.id = int.Parse(row[0].ToString());
entry.NPCWords = row[1].ToString();
entry.Reply = row[2].ToString();
entry.AudioClip = row[3].ToString();
entry.AnimClip = row[4].ToString();
entry.LookAtPlayer = bool.Parse(row[5].ToString());
entry.JumpTo = int.Parse(row[6].ToString());
entry.EventName = row[7].ToString();
sentences.Add(entry);
}
talkConfig.talkDic.Add(table.TableName, sentences);
Debug.Log($"对话{table.TableName}导出{table.Rows.Count- ContentStartRow}句话");
}
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(outputStream, talkConfig);
outputStream.Close();
excelStream.Close();
AssetDatabase.Refresh();
Debug.Log("对话配置导出完毕");
}
}
static void PrintTalk()
{
TalkConfig talkConfig = new TalkConfig();
using (FileStream fileStream = new FileStream(OutputBinPath,
FileMode.Open, FileAccess.Read))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
talkConfig = binaryFormatter.Deserialize(fileStream) as TalkConfig;
fileStream.Close();
}
Debug.Log(talkConfig.talkDic.Count);
foreach (KeyValuePair<string, List<SentenceEntry>> pair in talkConfig.talkDic)
{
Debug.Log(pair.Key);
for (int i = 0; i < pair.Value.Count; i++)
{
Debug.Log(pair.Value[i].NPCWords);
}
}
}
}