出现问题的Unity版本为 2022.3.14,正常使用时的Unity版本为 2020.3.25。
代码为:
public class ScriptsInfoRecoder : UnityEditor.AssetModificationProcessor
{
private static void OnWillCreateAsset(string path)
{
path = path.Replace(".meta", "");
if (path.EndsWith(".cs"))
{
string str = File.ReadAllText(path);
str = str.Replace("#SCRIPTFULLNAME#", Path.GetFileName(path)).Replace(
"#CreateTime#", string.Concat(DateTime.Now.Year, "/", DateTime.Now.Month, "/",DateTime.Now.Day, " ", DateTime.Now.Hour, ":", DateTime.Now.Minute, ":", DateTime.Now.Second));
File.WriteAllText(path, str);
}
}
}
报错:
下方是报错的全部内容
FileNotFoundException: Could not find file "D:\Unity Project\UnlimitedMowing\Assets\Program\Scripts\Test.cs"
System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
(wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions)
System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
(wrapper remoting-invoke-with-check) System.IO.StreamReader..ctor(string,System.Text.Encoding,bool)
System.IO.File.InternalReadAllText (System.String path, System.Text.Encoding encoding) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
System.IO.File.ReadAllText (System.String path) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
Tool.Common.ScriptsInfoRecoder.OnWillCreateAsset (System.String path) (at Assets/Program/Scripts/Tool/Editor/ScriptsInfoRecoder.cs:21)
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
UnityEditor.AssetModificationProcessorInternal.OnWillCreateAsset (System.String path) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ProjectWindowUtil.CreateScriptAssetWithContent (System.String pathName, System.String templateContent) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ProjectWindowUtil.CreateScriptAssetFromTemplate (System.String pathName, System.String resourceFile) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ProjectWindowCallback.DoCreateScriptAsset.Action (System.Int32 instanceId, System.String pathName, System.String resourceFile) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ProjectWindowUtil.EndNameEditAction (UnityEditor.ProjectWindowCallback.EndNameEditAction action, System.Int32 instanceId, System.String pathName, System.String resourceFile, System.Boolean accepted) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.CreateAssetUtility.EndNewAssetCreation (System.String name) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea.RenameEnded () (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea.HandleRenameOverlay () (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea+LocalGroup.DrawItem (UnityEngine.Rect position, UnityEditor.FilteredHierarchy+FilterResult filterItem, UnityEditor.BuiltinResource builtinResource, System.Boolean isFolderBrowsing) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea+LocalGroup.DrawInternal (System.Int32 beginIndex, System.Int32 endIndex, System.Single yOffset) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea+Group.Draw (System.Single yOffset, UnityEngine.Vector2 scrollPos, System.Int32& rowsInUse) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea.HandleListArea () (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ObjectListArea.OnGUI (UnityEngine.Rect position, System.Int32 keyboardControlID) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.ProjectBrowser.OnGUI () (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.DockArea.DrawView (UnityEngine.Rect dockAreaRect) (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEditor.DockArea.OldOnGUI () (at <227afaeeb5894c00b1d9aa4278f87f8c>:0)
UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, UnityEngine.Matrix4x4 worldTransform, UnityEngine.Rect clippingRect, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.IMGUIContainer.HandleIMGUIEvent (UnityEngine.Event e, System.Boolean canAffectFocus) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUIRaw (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.IMGUIContainer.SendEventToIMGUI (UnityEngine.UIElements.EventBase evt, System.Boolean canAffectFocus, System.Boolean verifyBounds) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.KeyboardEventDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.EventDispatcher.Dispatch (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, UnityEngine.UIElements.DispatchMode dispatchMode) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.BaseVisualElementPanel.SendEvent (UnityEngine.UIElements.EventBase e, UnityEngine.UIElements.DispatchMode dispatchMode) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.UIElementsUtility.UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& eventHandled) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.UIEventRegistration.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.UIElements.UIEventRegistration+<>c.<.cctor>b__1_2 (System.Int32 i, System.IntPtr ptr) (at <900dc5ca37fe408984765dccf7e242de>:0)
UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr, System.Boolean& result) (at <ab3b53da78e948c59742f9e43eb67ec6>:0)
脚本中的第23行是 string str = File.ReadAllText(path) ,故问题就出现在此。
解决方案:
使用 UniTask,这个插件是我非常喜欢的一个插件,谁用谁知道。修改代码:
private static void OnWillCreateAsset(string path)
{
path = path.Replace(".meta", "");
if (path.EndsWith(".cs"))
{
ChangeFileContent(path);
}
}
static async void ChangeFileContent(string path)
{
await UniTask.Yield();
string str = File.ReadAllText(path);
str = str.Replace("#SCRIPTFULLNAME#", Path.GetFileName(path)).Replace(
"#CreateTime#", string.Concat(DateTime.Now.Year, "/", DateTime.Now.Month, "/",DateTime.Now.Day, " ", DateTime.Now.Hour, ":", DateTime.Now.Minute, ":", DateTime.Now.Second));
File.WriteAllText(path, str);
}
结论:
猜测是使用【OnWillCreateAsset】时该文件还没有被创建,而 File.ReadAllText 需要读取到文件故而报错。使用一帧延迟就是表示创建后再对该文件的查找。
请注意:editor下不能执行真正的协程。
如果有小伙伴有其他实现的方法,欢迎在下方评论