Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Documentation/analyze-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ This is an example MonoScript from a `UnityDataTool dump` of a Serialized File:
ID: -5763254701832525334 (ClassID: 115) MonoScript
m_Name (string) SpriteSkin
m_ExecutionOrder (int) 0
m_PropertiesHash (Hash128)
...
m_PropertiesHash (Hash128) 4ce2fab3c132c26713e5cd3f58f2e229
m_ClassName (string) SpriteSkin
m_Namespace (string) UnityEngine.U2D.Animation
m_AssemblyName (string) Unity.2D.Animation.Runtime
Expand Down
54 changes: 54 additions & 0 deletions TextDumper/TextDumperTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ void RecursiveDump(TypeTreeNode node, ref long offset, int level, int arrayIndex
// Skip child nodes as they were already processed here.
skipChildren = true;
}
else if (TryReadCompoundValue(node, ref offset, out var compoundValue))
{
m_StringBuilder.Append(' ');
m_StringBuilder.Append(compoundValue);

// Skip child nodes as they were already processed here.
skipChildren = true;
}

m_Writer.WriteLine(m_StringBuilder);
m_StringBuilder.Clear();
Expand Down Expand Up @@ -510,6 +518,52 @@ bool DumpManagedReferenceData(TypeTreeNode refTypeNode, TypeTreeNode referencedT
return true;
}

// Compound types that are more readable printed as a single value than as their serialized
// fields, similarly to strings. To support another type, add a case matching its type name and
// serialized layout, returning the formatted value and advancing offset past the data.
bool TryReadCompoundValue(TypeTreeNode node, ref long offset, out string value)
{
switch (node.Type)
{
// A GUID is serialized as 4 uint32 values.
case "GUID" when HasUniformLeafChildren(node, 4, 4):
value = GuidHelper.FormatUnityGuid(
m_Reader.ReadUInt32(offset),
m_Reader.ReadUInt32(offset + 4),
m_Reader.ReadUInt32(offset + 8),
m_Reader.ReadUInt32(offset + 12));
offset += 16;
return true;

// A Hash128 is serialized as 16 bytes.
case "Hash128" when HasUniformLeafChildren(node, 16, 1):
var bytes = new byte[16];
m_Reader.ReadArray(offset, 16, bytes);
value = GuidHelper.FormatUnityHash128(bytes);
offset += 16;
return true;
}

value = null;
return false;
}

// Confirms a compound type has the exact layout expected by TryReadCompoundValue, so that an
// unrelated type reusing the same name falls back to the generic field-by-field dump.
static bool HasUniformLeafChildren(TypeTreeNode node, int count, int size)
{
if (node.Children.Count != count)
return false;

foreach (var child in node.Children)
{
if (!child.IsLeaf || child.Size != size)
return false;
}

return true;
}

static long AlignTo4(long offset) => (offset + 3) & ~3L;

void AppendIndent(int level) => m_StringBuilder.Append(' ', level * 2);
Expand Down
32 changes: 32 additions & 0 deletions UnityDataTool.Tests/DumpTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class DumpTests
private string m_NoTypeTreeSerializedFilePath;
private string m_NoTypeTreeArchivePath;
private string m_SerializationDemoBundlePath;
private string m_ContentDirectoryBuildReportPath;

[OneTimeSetUp]
public void OneTimeSetup()
Expand All @@ -27,6 +28,7 @@ public void OneTimeSetup()
m_NoTypeTreeSerializedFilePath = Path.Combine(m_TestDataFolder, "PlayerNoTypeTree", "level0");
m_NoTypeTreeArchivePath = Path.Combine(m_TestDataFolder, "AssetBundleTypeTreeVariations", "AssetBundle-NoTypeTree", "small.bundle");
m_SerializationDemoBundlePath = Path.Combine(m_TestDataFolder, "LeadingEdgeBuilds", "AssetBundles", "serializationdemo");
m_ContentDirectoryBuildReportPath = Path.Combine(m_TestDataFolder, "LeadingEdgeBuilds", "BuildReport-ContentDirectory", "f64157fb08bb9f645971d39c1203bd03.buildreport");
}

[Test]
Expand Down Expand Up @@ -309,4 +311,34 @@ public async Task Dump_Stdout_AssetBundle_SerializationDemo_ContainsExpectedFiel
Assert.That(output, Does.Contain("Array<int>[512]"));
Assert.That(output, Does.Contain("293, 294, 295, 296,"));
}

// GUID and Hash128 fields are printed as a single hex string instead of their serialized fields.
// The expected values can be verified independently: buildSessionGUID matches the build report
// file name, and the Scene1 sourceAssetGUID matches Assets/Scenes/Scene1.unity.meta in the
// LeadingEdge project.
[Test]
public async Task Dump_Stdout_BuildReport_PrintsGuidAndHash128AsHexStrings()
{
using var sw = new StringWriter();
var currentOut = Console.Out;
try
{
Console.SetOut(sw);
Assert.AreEqual(0, await Program.Main(new string[] { "dump", m_ContentDirectoryBuildReportPath, "--stdout" }));
}
finally
{
Console.SetOut(currentOut);
}

var output = sw.ToString();

Assert.That(output, Does.Contain("buildSessionGUID (GUID) f64157fb08bb9f645971d39c1203bd03"));
Assert.That(output, Does.Contain("sourceAssetGUID (GUID) 162c015549f8733449ac70ae78ad3aa5"));
Assert.That(output, Does.Contain("buildManifestHash (Hash128) baff06b928d147276f2245dd3b19216a"));

// The individual fields of these compound types are no longer dumped.
Assert.That(output, Does.Not.Contain("data[0] (unsigned int)"));
Assert.That(output, Does.Not.Contain("bytes[0] (UInt8)"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27148,23 +27148,7 @@ ID: -4365321507395843767 (ClassID: 33) MeshFilter
ID: -4339217461983190205 (ClassID: 115) MonoScript
m_Name (string) SerializeReferencePolymorphismExample
m_ExecutionOrder (int) 0
m_PropertiesHash (Hash128)
bytes[0] (UInt8) 5
bytes[1] (UInt8) 61
bytes[2] (UInt8) 135
bytes[3] (UInt8) 226
bytes[4] (UInt8) 11
bytes[5] (UInt8) 136
bytes[6] (UInt8) 110
bytes[7] (UInt8) 198
bytes[8] (UInt8) 240
bytes[9] (UInt8) 145
bytes[10] (UInt8) 18
bytes[11] (UInt8) 73
bytes[12] (UInt8) 18
bytes[13] (UInt8) 65
bytes[14] (UInt8) 27
bytes[15] (UInt8) 13
m_PropertiesHash (Hash128) 053d87e20b886ec6f091124912411b0d
m_ClassName (string) SerializeReferencePolymorphismExample
m_Namespace (string)
m_AssemblyName (string) Assembly-CSharp.dll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27148,23 +27148,7 @@ ID: -4365321507395843767 (ClassID: 33) MeshFilter
ID: -4339217461983190205 (ClassID: 115) MonoScript
m_Name (string) SerializeReferencePolymorphismExample
m_ExecutionOrder (int) 0
m_PropertiesHash (Hash128)
bytes[0] (UInt8) 5
bytes[1] (UInt8) 61
bytes[2] (UInt8) 135
bytes[3] (UInt8) 226
bytes[4] (UInt8) 11
bytes[5] (UInt8) 136
bytes[6] (UInt8) 110
bytes[7] (UInt8) 198
bytes[8] (UInt8) 240
bytes[9] (UInt8) 145
bytes[10] (UInt8) 18
bytes[11] (UInt8) 73
bytes[12] (UInt8) 18
bytes[13] (UInt8) 65
bytes[14] (UInt8) 27
bytes[15] (UInt8) 13
m_PropertiesHash (Hash128) 053d87e20b886ec6f091124912411b0d
m_ClassName (string) SerializeReferencePolymorphismExample
m_Namespace (string)
m_AssemblyName (string) Assembly-CSharp.dll
Expand Down
Loading
Loading