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).