fix: serialization GC not recursing into scriptable objects

This commit is contained in:
bd_ 2023-07-31 21:04:27 +09:00
parent 9138205ace
commit 0f2895c14e
3 changed files with 98 additions and 20 deletions

View File

@ -0,0 +1,57 @@
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using PlasticGui.WorkspaceWindow.QueryViews.Branches;
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
namespace modular_avatar_tests.serialization
{
class TestComponent : MonoBehaviour
{
public UnityEngine.Object ref1, ref2;
}
class TestScriptable : ScriptableObject
{
public UnityEngine.Object ref1, ref2;
}
public class SerializationSweepTest : TestBase
{
[Test]
public void testSerialization()
{
var root = CreateRoot("root");
var child = CreateChild(root, "child");
var testComponent = child.AddComponent<TestComponent>();
var testScriptable1 = ScriptableObject.CreateInstance<TestScriptable>();
var testScriptable2 = ScriptableObject.CreateInstance<TestScriptable>();
var testScriptable3 = ScriptableObject.CreateInstance<TestScriptable>();
var testScriptable4 = ScriptableObject.CreateInstance<TestScriptable>();
testComponent.ref1 = testScriptable1;
testComponent.ref2 = root;
testScriptable1.ref1 = testScriptable2;
testScriptable2.ref1 = testScriptable3;
testScriptable1.ref2 = testScriptable4;
testScriptable2.ref2 = testScriptable4;
testScriptable3.ref2 = testScriptable4;
BuildContext bc = new BuildContext(root.GetComponent<VRCAvatarDescriptor>());
bc.CommitReferencedAssets();
var path = AssetDatabase.GetAssetPath(testScriptable1);
Assert.IsFalse(string.IsNullOrEmpty(path));
Assert.AreEqual(path, AssetDatabase.GetAssetPath(testScriptable2));
Assert.AreEqual(path, AssetDatabase.GetAssetPath(testScriptable3));
Assert.AreEqual(path, AssetDatabase.GetAssetPath(testScriptable4));
Assert.IsTrue(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(testComponent)));
Assert.IsTrue(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(root)));
Assert.IsTrue(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(child)));
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a8035784f3364865a84cc938682be7a0
timeCreated: 1690804771

View File

@ -133,10 +133,18 @@ namespace nadena.dev.modular_avatar.core.editor
Walk(AvatarDescriptor.gameObject); Walk(AvatarDescriptor.gameObject);
foreach (var asset in referencedAssets referencedAssets.RemoveWhere(sceneAssets.Contains);
.Where(o => !sceneAssets.Contains(o)) referencedAssets.RemoveWhere(o => !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o)));
.Where(o => string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o))))
int index = 0;
foreach (var asset in referencedAssets)
{ {
if (asset.name == "")
{
asset.name = "Asset " + index++;
}
AssetDatabase.AddObjectToAsset(asset, AssetContainer); AssetDatabase.AddObjectToAsset(asset, AssetContainer);
} }
@ -157,28 +165,38 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
var so = new SerializedObject(component); Queue<UnityEngine.Object> visitQueue = new Queue<UnityEngine.Object>();
var sp = so.GetIterator(); visitQueue.Enqueue(component);
bool enterChildren = true;
while (sp.Next(enterChildren)) while (visitQueue.Count > 0)
{ {
enterChildren = true; var current = visitQueue.Dequeue();
if (sp.name == "m_GameObject") continue; if (referencedAssets.Contains(current)) continue;
if (sp.propertyType == SerializedPropertyType.String) referencedAssets.Add(current);
{
enterChildren = false;
continue;
}
if (sp.propertyType != SerializedPropertyType.ObjectReference) var so = new SerializedObject(current);
{ var sp = so.GetIterator();
continue; bool enterChildren = true;
}
if (sp.objectReferenceValue != null) while (sp.Next(enterChildren))
{ {
referencedAssets.Add(sp.objectReferenceValue); enterChildren = true;
if (sp.name == "m_GameObject") continue;
if (sp.propertyType == SerializedPropertyType.String)
{
enterChildren = false;
continue;
}
if (sp.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
if (sp.objectReferenceValue != null)
{
visitQueue.Enqueue(sp.objectReferenceValue);
}
} }
} }
} }