问题描述
在 Unity ScriptableObject 的使用过程中,遇到了在 Unity 编辑器内 ScriptableObject 实例没有与资源文件同步更新的情况。
我使用的 Unity 编辑器版本为 2020.2.5f1。
遇到该问题的具体场景:
- 在系统资源管理器中直接修改
.asset
文件。 - 通过版本管理工具(如 Git、SVN 等)更新或回退
.asset
文件。
经过以上任意一种操作后,再次回到 Unity 编辑器后会有对应资源的刷新过程,但是实际上 ScriptableObject 实例的数据并没有刷新成功,还是之前的数据。
即使在 Project 面板中 Reimport / Refresh 该资源也无济于事,也有尝试在代码中调用 AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate)
函数来重新导入该资源,结果依然没有任何变化。
问题原因
经过一顿 Google 后,在 Unity 官方论坛中找到了类似问题的帖子。
- [Solved] Issue with .asset files updating through Collab: https://forum.unity.com/threads/solved-issue-with-asset-files-updating-through-collab.457722/
看来这个问题早在 Unity 5.5 甚至更早的版本中就已经存在,Unity 官方技术人员称在 5.6 beta 版本中修复该问题,然而并没有修复成功~
从帖子中可以得知,该问题在 2020.3.13f1 (LTS) 中依然存在…
所以,目前可以确认这个就是 Unity 编辑器的 Bug 了。
解决方案
经过一次又一次的尝试后,最终还是找到了一个可行的解决方案。
简单来说就是:
- 将资源文件和其 .meta 文件移动到项目 Assets 目录之外的任意目录;
- 刷新 Unity 资源数据库;
- 然后再将文件移动回原来的位置。
具体代码:
public static async void ReimportAsset(Object asset)
{
EditorUtility.DisplayProgressBar("正在重新导入资源...", "请稍候...", 1);
{
// 资源文件路径
string assetPath = AssetDatabase.GetAssetPath(asset);
string filePath = Application.dataPath + assetPath.Substring(6);
string metaPath = filePath + ".meta";
FileInfo fileInfo = new FileInfo(filePath);
string dirPath = fileInfo.DirectoryName!.Replace("\\", "/");
// 临时目录路径(项目根目录)
string tempDirPath = Application.dataPath.Replace("/Assets", "");
string tempFilePath = filePath.Replace(dirPath, tempDirPath);
string tempMetaPath = tempFilePath + ".meta";
// 移动到临时目录,并刷新资源数据库
File.Move(filePath, tempFilePath);
File.Move(metaPath, tempMetaPath);
AssetDatabase.Refresh();
// 等待一会
await Task.Delay(100);
// 移动回项目内原位置,并刷新资源数据库
File.Move(tempFilePath, filePath);
File.Move(tempMetaPath, metaPath);
AssetDatabase.Refresh();
// 选中资源
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Object>(assetPath);
}
EditorUtility.ClearProgressBar();
}