Closed anatawa12 closed 3 weeks ago
こちらの環境では再現できてません(ProxyPipelineなどの中にMeshを参照するテストコードを追加などしてみてもだめっぽい)
Mac特有の事情の可能性もあるので、とりあえず発生時点でのスタックトレースなどをお願いします。
スタックトレース的には変化がありません
少し今試した感じ、エディタをいじってるだけでは発生確率が低いですが、シーンウィンドウの視点移動をしていたりすると(PlayerLoopをトリガさせていると?)よく発生するように思えます
Instantiate IsPlayerLoop: True
UnityEngine.Debug:Log (object)
Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>:MoveNext () (at ./Packages/AvatarOptimizer/Editor/EditModePreview/AAORenderFilterBase.cs:64)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.IRenderFilterNode>:Start<Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>> (Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>&)
Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1<Anatawa12.AvatarOptimizer.RemoveMeshInBox>:Instantiate (nadena.dev.ndmf.preview.RenderGroup,System.Collections.Generic.IEnumerable`1<System.ValueTuple`2<UnityEngine.Renderer, UnityEngine.Renderer>>,nadena.dev.ndmf.preview.ComputeContext)
nadena.dev.ndmf.preview.NodeController/<Create>d__23:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/NodeController.cs:121)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.NodeController/<Create>d__23> (nadena.dev.ndmf.preview.NodeController/<Create>d__23&)
nadena.dev.ndmf.preview.NodeController:Create (nadena.dev.ndmf.preview.IRenderFilter,nadena.dev.ndmf.preview.RenderGroup,nadena.dev.ndmf.ObjectRegistry,System.Collections.Generic.List`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>>,string)
nadena.dev.ndmf.preview.NodeController/<Refresh>d__24:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/NodeController.cs:190)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.NodeController/<Refresh>d__24> (nadena.dev.ndmf.preview.NodeController/<Refresh>d__24&)
nadena.dev.ndmf.preview.NodeController:Refresh (System.Collections.Generic.List`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>>,nadena.dev.ndmf.preview.RenderAspects,string)
nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/ProxyPipeline.cs:234)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d> (nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d&)
nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2:<Build>b__5 (System.Threading.Tasks.Task`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>[]>)
UnityEngine.UnitySynchronizationContext:ExecuteTasks () (at /Users/bokken/build/output/unity/unity/Runtime/Export/Scripting/UnitySynchronizationContext.cs:107)
Instantiate IsPlayerLoop: False
UnityEngine.Debug:Log (object)
Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>:MoveNext () (at ./Packages/AvatarOptimizer/Editor/EditModePreview/AAORenderFilterBase.cs:64)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.IRenderFilterNode>:Start<Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>> (Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1/<Instantiate>d__5<Anatawa12.AvatarOptimizer.RemoveMeshInBox>&)
Anatawa12.AvatarOptimizer.EditModePreview.AAORenderFilterBase`1<Anatawa12.AvatarOptimizer.RemoveMeshInBox>:Instantiate (nadena.dev.ndmf.preview.RenderGroup,System.Collections.Generic.IEnumerable`1<System.ValueTuple`2<UnityEngine.Renderer, UnityEngine.Renderer>>,nadena.dev.ndmf.preview.ComputeContext)
nadena.dev.ndmf.preview.NodeController/<Create>d__23:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/NodeController.cs:121)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.NodeController/<Create>d__23> (nadena.dev.ndmf.preview.NodeController/<Create>d__23&)
nadena.dev.ndmf.preview.NodeController:Create (nadena.dev.ndmf.preview.IRenderFilter,nadena.dev.ndmf.preview.RenderGroup,nadena.dev.ndmf.ObjectRegistry,System.Collections.Generic.List`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>>,string)
nadena.dev.ndmf.preview.NodeController/<Refresh>d__24:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/NodeController.cs:190)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.NodeController/<Refresh>d__24> (nadena.dev.ndmf.preview.NodeController/<Refresh>d__24&)
nadena.dev.ndmf.preview.NodeController:Refresh (System.Collections.Generic.List`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>>,nadena.dev.ndmf.preview.RenderAspects,string)
nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d:MoveNext () (at ./Packages/ndmf/Editor/PreviewSystem/Rendering/ProxyPipeline.cs:234)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<nadena.dev.ndmf.preview.NodeController>:Start<nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d> (nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2/<<Build>b__5>d&)
nadena.dev.ndmf.preview.ProxyPipeline/<>c__DisplayClass22_2:<Build>b__5 (System.Threading.Tasks.Task`1<System.ValueTuple`3<UnityEngine.Renderer, nadena.dev.ndmf.preview.ProxyObjectController, nadena.dev.ndmf.ObjectRegistry>[]>)
UnityEngine.UnitySynchronizationContext:ExecuteTasks () (at /Users/bokken/build/output/unity/unity/Runtime/Export/Scripting/UnitySynchronizationContext.cs:107)
今試したところ、windowsでも再現しました。
context.Observe
でextractを指定していないIRenderFilter
がある必要がありそうです
Windowsで確認するために使ったコードです。GUIDとfileIDをRead Write mesh offなメッシュにしてください。(この例ではあのんちゃんになってます)
static class IsInPlayerLoop
{
private static Mesh? _mesh;
private static System.Reflection.PropertyInfo? _propertyInfo;
public static bool IsPlayerLoop() {
if (_mesh == null)
{
// GUID and fileID of a read write mesh off mesh here
var guid = "b90ae694f8009d949934a1419170452e";
var fileID = 13727694889372365607;
UnityEditor.GlobalObjectId.TryParse($"GlobalObjectId_V1-1-{guid}-{fileID}-0", out var globalObjectId);
_mesh = (Mesh)UnityEditor.GlobalObjectId.GlobalObjectIdentifierToObjectSlow(globalObjectId);
}
if (_propertyInfo == null)
{
_propertyInfo = typeof(Mesh).GetProperty("canAccess", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!;
}
var canAccess = (bool)_propertyInfo.GetValue(_mesh)!;
return !canAccess;
}
}
context.Observeでextractを指定していないIRenderFilterがある必要がありそうです
こちらはなくても、シーン上の動作を下にしたIRenderFilterの更新がある場合に発生することがありそうです(on macos with RemoveMesh in Boxのpreviewで確認)
再現できました。どうやらUnityのデフォルトSynchronizationContextがPlayerLoop扱いになるため、TaskThrottleが起動するとPlayerLoopに移ってしまうようです。NDMF専用のSynchronizationContextで対応します。
e70e43bbf3086e4e3305ab9a313a0ed969a341e1 で確認しました。
IRenderFilter.Instantiate
などがランダムでPlayerLoopの内外で呼び出されてしまいます。PlayerLoopの中で呼び出されるとRead/Write offなメッシュのアクセスがエラーになってしまうので、これが発生するか否かがランダムだとデバッグ時に微妙に困ります。
PlayerLoopのなかかどうかは
_Z18IsInsidePlayerLoopv
を呼び出せば確認できますがDllImportでは呼び出せないため様々なハックが必要となってしまいます。(正攻法は不明)一応EditorApplication.updateなどは外であることが確定しています。
unity 2022.3.22f1 arm64でのみ動く確認用コードはありますが他環境だと確実に壊れますため汎用性がないです。 https://gist.github.com/anatawa12/f730f08940ef965cadcf25388c0afb1c