Skip to content

Commit

Permalink
fix: preview system fails to recover from the loss of the primary pro…
Browse files Browse the repository at this point in the history
…xy object
  • Loading branch information
bdunderscore committed Oct 20, 2024
1 parent 91a2738 commit 4a9c14c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 9 deletions.
38 changes: 30 additions & 8 deletions Editor/PreviewSystem/Rendering/ProxyObjectCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ private class ProxyHandleImpl : IProxyHandle
private readonly Renderer _key;
private readonly Func<Renderer> _createFunc;
private readonly RendererState _state;
private bool _disposed;

public ProxyHandleImpl(ProxyObjectCache cache, Renderer key, Func<Renderer> createFunc, RendererState state)
{
Expand Down Expand Up @@ -70,6 +71,14 @@ public void ReturnSetupProxy(Renderer proxy)

public void Dispose()
{
if (_disposed)
{
Debug.LogWarning("Proxy handle was disposed twice!");
throw new ObjectDisposedException(nameof(ProxyHandleImpl));
}

_disposed = true;

if (--_state.ActivePrimaryCount == 0)
{
_cache.MaybeDisposeProxy(_key);
Expand Down Expand Up @@ -118,30 +127,43 @@ private void OnPlayModeStateChanged(PlayModeStateChange obj)
public IProxyHandle GetHandle(Renderer original, Func<Renderer> create)
{
IsRegistered = true;

Func<Renderer> createShimmed = () =>
{
var newProxy = create();
newProxy.gameObject.AddComponent<ProxyTagComponent>();
_proxyObjectInstanceIds.Add(newProxy.gameObject.GetInstanceID());

return newProxy;
};

if (!_renderers.TryGetValue(original, out var state))
{
state = new RendererState();
state.PrimaryProxy = create();
state.PrimaryProxy = createShimmed();
_renderers.Add(original, state);
}

state.ActivePrimaryCount++;

return new ProxyHandleImpl(this, original, () =>
if (state.PrimaryProxy == null)
{
var newProxy = create();
_proxyObjectInstanceIds.Add(newProxy.gameObject.GetInstanceID());
// Recover from loss of the primary proxy
state.PrimaryProxy = createShimmed();
}

return newProxy;
}, state);
state.ActivePrimaryCount++;

return new ProxyHandleImpl(this, original, createShimmed, state);
}

private static void DestroyProxy(Renderer proxy)
{
if (proxy == null) return;

var gameObject = proxy.gameObject;
if (gameObject.TryGetComponent<ProxyTagComponent>(out var tag))
{
tag.Armed = false;
}
_proxyObjectInstanceIds.Remove(gameObject.GetInstanceID());
Object.DestroyImmediate(gameObject);
}
Expand Down
10 changes: 9 additions & 1 deletion Editor/PreviewSystem/Rendering/ProxyObjectController.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#region

using System;
using System.Diagnostics;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.SceneManagement;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;

#endregion
Expand Down Expand Up @@ -33,6 +35,8 @@ internal class ProxyObjectController : IDisposable
private bool _visibilityOffOriginal;
private bool _pickingOffOriginal, _pickingOffReplacement;
private long _lastVisibilityCheck = long.MinValue;

private readonly Stopwatch _lastWarning = new();

private static CustomSampler _onPreFrameSampler = CustomSampler.Create("ProxyObjectController.OnPreFrame");

Expand Down Expand Up @@ -137,7 +141,11 @@ internal bool OnPreFrame()
{
if (Renderer == null)
{
Debug.LogWarning("Proxy object was destroyed improperly! Resetting pipeline...");
if (!_lastWarning.IsRunning || _lastWarning.ElapsedMilliseconds > 1000)
{
Debug.LogWarning("Proxy object was destroyed improperly! Resetting pipeline...");
_lastWarning.Restart();
}
}
return false;
}
Expand Down
6 changes: 6 additions & 0 deletions Editor/PreviewSystem/Rendering/ProxyPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ await Task.WhenAll(_stages.SelectMany(s => s.NodeTasks))
{
proxy.FinishSetup();

if (proxy.Renderer == null)
{
Invalidate();
continue;
}

OriginalToProxyRenderer = OriginalToProxyRenderer.Add(r, proxy.Renderer);
OriginalToProxyObject = OriginalToProxyObject.Add(r.gameObject, proxy.Renderer.gameObject);
ProxyToOriginalObject = ProxyToOriginalObject.Add(proxy.Renderer.gameObject, r.gameObject);
Expand Down
20 changes: 20 additions & 0 deletions Runtime/ProxyTagComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using UnityEngine;

namespace nadena.dev.ndmf.preview
{
[AddComponentMenu("/")]
internal class ProxyTagComponent : MonoBehaviour
{
internal bool Armed = true;

private void OnDestroy()
{
#if NDMF_DEBUG
if (Armed)
{
Debug.LogWarning("Proxy object was destroyed improperly here!");
}
#endif
}
}
}
3 changes: 3 additions & 0 deletions Runtime/ProxyTagComponent.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4a9c14c

Please sign in to comment.