游戏中使用Excel文件配置游戏数据,打包时需要将Excel文件转成txt以供游戏解析使用,尽管提供了一键转换的菜单,还是经常忘记,造成不必要的麻烦。
如果用程序监听数据表文件的改动,当文件被修改后自动更新数据表,这样开发工作流就更完善了。
监听文件改变的API:
var watcher = new FileSystemWatcher(ConstEditor.DataTableExcelPath, "*.xlsx");
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
watcher.EnableRaisingEvents = true;
fileChangedCb = new FileSystemEventHandler(OnDataTableChanged);
fileRenameCb = new RenamedEventHandler(OnDataTableChanged);
watcher.Changed += fileChangedCb;
watcher.Deleted += fileChangedCb;
watcher.Renamed += fileRenameCb;
这样会出现一个问题,经常会出现文件改变回调函数不会触发的情况。因为当编辑Excel文件时,Unity编辑器窗口处于非激活状态,在回调中更新表的逻辑就没有被执行。
可以用EditorApplication.update,当文件修改后记录修改状态,然后在update中刷新表数据:
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
public static partial class DataTableUpdater
{
static FileSystemWatcher watcher;
static FileSystemEventHandler fileChangedCb;
static RenamedEventHandler fileRenameCb;
static FileSystemEventArgs curChangeEventArgs;
static bool isInitialized = false;
[InitializeOnLoadMethod]
private static void Init()
{
if (isInitialized) return;
EditorApplication.update += OnUpdate;
curChangeEventArgs = null;
watcher = new FileSystemWatcher(ConstEditor.DataTableExcelPath, "*.xlsx");
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
watcher.EnableRaisingEvents = true;
fileChangedCb = new FileSystemEventHandler(OnDataTableChanged);
fileRenameCb = new RenamedEventHandler(OnDataTableChanged);
watcher.Changed += fileChangedCb;
watcher.Deleted += fileChangedCb;
watcher.Renamed += fileRenameCb;
isInitialized = true;
}
private static void OnUpdate()
{
if (curChangeEventArgs != null)
{
var fileName = Path.GetFileNameWithoutExtension(curChangeEventArgs.Name);
if (ArrayUtility.Contains(PreloadProcedure.dataTables, fileName))
{
MyGameTools.RefreshAllDataTable(new string[] { fileName });
Debug.LogFormat("Auto Refresh DataTable:{0}", curChangeEventArgs.FullPath);
}
else if (ArrayUtility.Contains(PreloadProcedure.configs, fileName))
{
MyGameTools.RefreshAllConfig(PreloadProcedure.configs);
Debug.LogFormat("Auto Refresh Config:{0}", curChangeEventArgs.FullPath);
}
curChangeEventArgs = null;
}
}
private static void OnDataTableChanged(object sender, FileSystemEventArgs e)
{
curChangeEventArgs = e;
}
}
#endif