Class MetadataCollect
Abstract class for creating a metadata collector type to populate the PackedMemorySnapshot.Metadata member. You can add multiple collectors, but it is recommended to add only one. A collector instance will auto-register during construction.
Namespace: Unity.MemoryProfiler
Assembly: Unity.MemoryProfiler.dll
Syntax
public abstract class MetadataCollect
Remarks
Creating a collector instance will override the default metadata collection functionality. If you want to keep the default metadata, go to the DefaultCollect method in the file com.unity.memoryprofiler\Runtime\MetadataInjector.cs and copy that code into your collector method.
Removing a collector can be achieved by calling dispose on the collector instance you want to unregister.
Examples
using Unity.MemoryProfiler;
using Unity.Profiling.Memory
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class SnapshotMetadataProvider : MonoBehaviour
{
public string levelName = "Default Level Name";
MyMetadataCollect m_MetadataCollector;
void Start()
{
m_MetadataCollector = new MyMetadataCollect(this);
}
void OnDestroy()
{
// Remember to dispose of the collector, so it won't leak.
m_MetadataCollector.Dispose();
}
}
public class MyMetadataCollect : MetadataCollect
{
SnapshotMetadataProvider m_MetadataProvider;
// Make sure to call the base constructor, which will handle the subscription to the MemoryProfiler.CreatingMetadata event.
public MyMetadataCollect(SnapshotMetadataProvider metadataProvider) : base()
{
m_MetadataProvider = metadataProvider;
}
public override void CollectMetadata(MemorySnapshotMetadata data)
{
// This is what the metadata default implementation of the package sets as the description:
data.Description += $"Project name: { Application.productName }\n"
+ $"This Memory Snapshot capture started at {System.DateTime.UtcNow} (UTC)\n"
+ $"Time.realtimeSinceStartup: {FormatSecondsToTime(Time.realtimeSinceStartupAsDouble)}\n";
#if UNITY_EDITOR
data.Description += $"EditorApplication.timeSinceStartup: {FormatSecondsToTime(EditorApplication.timeSinceStartup)}\n";
#endif
// Implementing one or more MetadataCollect types, will cause the default implementation to no longer execute.
// If you want to retain that default description, you can do so by mirroring the code in your implementation.
// The product name is however already part of the general memory snapshot metadata so you won't lose that detail if you don't.
// Note that if there are multiple MetadataCollect instances, each one will be called in the order in which they were created.
// To avoid overwriting what previous instance added to the Description, only append.
// Description is initialized as empty string so there is no need to check against null (unless one of your implementation sets it to null).
// Terminating with '\n' is a good convention to follow, in case there are other Metadata Providers that will add to this string.
data.Description += $"Captured in Level: {m_MetadataProvider.levelName}\n";
}
string FormatSecondsToTime(double timeInSeconds)
{
var seconds = (int)timeInSeconds;
var ms = (int)((timeInSeconds - seconds) * 1000);
var minutes = seconds / 60;
seconds %= 60;
var hours = minutes / 60;
minutes %= 60;
return $"{hours:00}:{minutes:00}:{seconds:00}.{ms:000}";
}
}
Constructors
MetadataCollect()
Default constructor of the MetadataCollect.
Declaration
protected MetadataCollect()
Remarks
When implementing your own version, remember to call the base constructor to ensure your instance is registered with Unity.Profiling.Memory.MemoryProfiler.CreatingMetadata.
Examples
You can inject a collector with InitializeOnLoadMethod or RuntimeInitializeOnLoadMethod to easily and globally add it to the project.
using Unity.MemoryProfiler;
using Unity.Profiling.Memory;
#if UNITY_EDITOR
using UnityEditor;
#else
using UnityEngine;
#endif
public class MySingletonMetadataCollect : MetadataCollect
{
static MySingletonMetadataCollect s_Instance;
#if UNITY_EDITOR
[InitializeOnLoadMethod]
static void EditorInitMetadata()
{
InitializeMetadataCollection();
}
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
static void EditorInitMetadata()
{
InitializeMetadataCollection();
}
#endif
static void InitializeMetadataCollection()
{
// Dispose any potential previous instance.
s_Instance?.Dispose();
s_Instance = new MySingletonMetadataCollect();
}
// Make sure to call the base constructor, which will handle the subscription to the MemoryProfiler.CreatingMetadata event.
public MySingletonMetadataCollect() : base()
{
}
public override void CollectMetadata(MemorySnapshotMetadata data)
{
// This is what the metadata default implementation of the package sets as the description.
data.Description += $"\nProject name: { Application.productName }\n"
+ $"This Memory Snapshot capture started at {System.DateTime.UtcNow} (UTC)\n"
+ $"Time.realtimeSinceStartup: {FormatSecondsToTime(Time.realtimeSinceStartupAsDouble)}\n";
#if UNITY_EDITOR
data.Description += $"EditorApplication.timeSinceStartup: {FormatSecondsToTime(EditorApplication.timeSinceStartup)}\n";
#endif
// Implementing one or more MetadataCollect types, will cause the default implementation to no longer execute.
// If you want to retain that default description, you can do so by mirroring the code in your implementation.
// The product name is however already part of the general memory snapshot metadata so you won't lose that detail if you don't.
// Note that if there are multiple MetadataCollect instances, each one will be called in the order in which they were created.
// To avoid overwriting what previous instance added to the Description, only append.
// Description is initialized as empty string so there is no need to check against null (unless one of your implementation sets it to null).
// Terminating with '\n' is a good convention to follow, in case there are other Metadata Providers that will add to this string.
data.Description += $"This is meta added by {nameof(MySingletonMetadataCollect)}\n";
}
string FormatSecondsToTime(double timeInSeconds)
{
var seconds = (int)timeInSeconds;
var ms = (int)((timeInSeconds - seconds) * 1000);
var minutes = seconds / 60;
seconds %= 60;
var hours = minutes / 60;
minutes %= 60;
return $"{hours:00}:{minutes:00}:{seconds:00}.{ms:000}";
}
}
See Also
Methods
CollectMetadata(MemorySnapshotMetadata)
The Memory Profiler will invoke this method during the capture process, to populate the metadata of the capture.
Declaration
public abstract void CollectMetadata(MemorySnapshotMetadata data)
Parameters
| Type | Name | Description |
|---|---|---|
| MemorySnapshotMetadata | data | The data payload that will get written to the snapshot file. It is initialized as an empty string but may have been populated by previous metadata collectors. |
Remarks
Note: If there are multiple MetadataCollect instances, each one will be called in the order in which they were created.
To avoid overwriting what previous instance added to data.Description, only append.
Description is initialized as empty string so there is no need to check against null (unless one of your implementation sets it to null).