您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

210 行
7.9 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Simulation;
using UnityEngine.Analytics;
using UnityEngine;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.Perception.Randomization.Randomizers;
using UnityEngine.Perception.Randomization.Scenarios;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Perception.Analytics
{
/// <summary>
/// Editor and Runtime analytics for the Perception package.
/// </summary>
/// <remarks>
/// To add an event:
/// 1. Create a constant with the name of the event (eg: <see cref="k_EventScenarioInformation"/>)
/// 2. Add the constant to <see cref="allEvents" />
/// 3. Create a function that will report data for the event and at the start of it call
/// <see cref="TryRegisterPerceptionAnalyticsEvent" /> with the event name defined in step 1.
/// Note: Remember to use the conditional "#if UNITY_EDITOR" if adding editor analytics.
/// </remarks>
public static class PerceptionAnalytics
{
const string k_VendorKey = "unity.perception";
const int k_MaxElementsInStruct = 100;
const int k_MaxEventsPerHour = 100;
#region Setup
[RuntimeInitializeOnLoadMethod]
static void OnInitializeOnLoad()
{
Manager.Instance.ShutdownNotification += OnSimulationShutdown;
}
static void OnSimulationShutdown()
{
var perceptionCamera = Object.FindObjectOfType<PerceptionCamera>();
ReportScenarioInformation(
perceptionCamera,
ScenarioBase.activeScenario
);
}
#endregion
/// <summary>
/// Stores whether each event has been registered successfully or not.
/// </summary>
static Dictionary<AnalyticsEvent, bool> s_EventRegistrationStatus = new Dictionary<AnalyticsEvent, bool>();
#region Event Definitions
static readonly AnalyticsEvent k_EventScenarioInformation = new AnalyticsEvent(
"perceptionScenarioInformation", AnalyticsEventType.RuntimeAndEditor, 1
);
static readonly AnalyticsEvent k_EventRunInUnitySimulation = new AnalyticsEvent(
"runinunitysimulation", AnalyticsEventType.Editor, 1
);
/// <summary>
/// All supported events. If an event does not exist in this list, an error will be thrown during
/// <see cref="TryRegisterPerceptionAnalyticsEvent" />.
/// </summary>
static IEnumerable<AnalyticsEvent> allEvents => new[]
{
k_EventScenarioInformation,
k_EventRunInUnitySimulation
};
#endregion
#region Helpers
/// <summary>
/// Tries to register an event and returns whether it was registered successfully. The result is also cached in
/// the <see cref="s_EventRegistrationStatus" /> dictionary.
/// </summary>
/// <param name="theEvent">The name of the event.</param>
/// <returns>Whether the event was successfully registered/</returns>
static bool TryRegisterPerceptionAnalyticsEvent(AnalyticsEvent theEvent)
{
// Make sure the event exists in the dictionary
if (!s_EventRegistrationStatus.ContainsKey(theEvent))
{
if (allEvents.Contains(theEvent))
s_EventRegistrationStatus[theEvent] = false;
else
throw new NotSupportedException($"Unrecognized event {theEvent} not included in {nameof(allEvents)}.");
}
// If registered previously, return true
if (s_EventRegistrationStatus[theEvent])
return true;
// Try registering the event and update the dictionary accordingly
s_EventRegistrationStatus[theEvent] = true;
#if UNITY_EDITOR
var status = EditorAnalytics.RegisterEventWithLimit(theEvent.name, k_MaxEventsPerHour, k_MaxElementsInStruct, k_VendorKey);
#else
var status = UnityEngine.Analytics.Analytics.RegisterEvent(theEvent.name, k_MaxEventsPerHour, k_MaxElementsInStruct, k_VendorKey);
#endif
s_EventRegistrationStatus[theEvent] &= status == AnalyticsResult.Ok;
return s_EventRegistrationStatus[theEvent];
}
/// <summary>
/// Based on the value of type for <see cref="theEvent" />, sends an Editor Analytics event,
/// a Runtime Analytics event, or both.
/// </summary>
/// <param name="theEvent">The analytics event.</param>
/// <param name="data">Payload of the event.</param>
static void SendPerceptionAnalyticsEvent(AnalyticsEvent theEvent, object data)
{
#if UNITY_EDITOR
if (theEvent.type == AnalyticsEventType.Editor || theEvent.type == AnalyticsEventType.RuntimeAndEditor)
{
EditorAnalytics.SendEventWithLimit(theEvent.name, data, theEvent.versionId);
}
#else
if (theEvent.type == AnalyticsEventType.Runtime || theEvent.type == AnalyticsEventType.RuntimeAndEditor)
{
UnityEngine.Analytics.Analytics.SendEvent(theEvent.name, data, theEvent.versionId, theEvent.prefix);
}
#endif
}
#endregion
#region Event: Scenario Information
/// <summary>
/// Which labelers will be identified and included in the analytics information.
/// </summary>
public static readonly string[] labelerAllowList = new[]
{
"BoundingBox3DLabeler", "BoundingBox2DLabeler", "InstanceSegmentationLabeler",
"KeypointLabeler", "ObjectCountLabeler", "SemanticSegmentationLabeler", "RenderedObjectInfoLabeler"
};
static void ReportScenarioInformation(
PerceptionCamera cam,
ScenarioBase scenario
)
{
if (!TryRegisterPerceptionAnalyticsEvent(k_EventScenarioInformation))
return;
var randomizers = scenario ? scenario.activeRandomizers : new List<Randomizer>();
var data = ScenarioCompletedData.FromCameraAndRandomizers(cam, randomizers);
SendPerceptionAnalyticsEvent(k_EventScenarioInformation, data);
}
#endregion
#region Event: Run In Unity Simulation
public static void ReportRunInUnitySimulationStarted(Guid runId, int totalIterations, int instanceCount, string existingBuildId)
{
if (!TryRegisterPerceptionAnalyticsEvent(k_EventRunInUnitySimulation))
return;
var data = new RunInUnitySimulationData
{
runId = runId.ToString(),
totalIterations = totalIterations,
instanceCount = instanceCount,
existingBuildId = existingBuildId,
runStatus = RunStatus.Started.ToString()
};
SendPerceptionAnalyticsEvent(k_EventRunInUnitySimulation, data);
}
public static void ReportRunInUnitySimulationFailed(Guid runId, string errorMessage)
{
if (!TryRegisterPerceptionAnalyticsEvent(k_EventRunInUnitySimulation))
return;
var data = new RunInUnitySimulationData
{
runId = runId.ToString(),
errorMessage = errorMessage,
runStatus = RunStatus.Failed.ToString()
};
SendPerceptionAnalyticsEvent(k_EventRunInUnitySimulation, data);
}
public static void ReportRunInUnitySimulationSucceeded(Guid runId, string runExecutionId)
{
if (!TryRegisterPerceptionAnalyticsEvent(k_EventRunInUnitySimulation))
return;
var data = new RunInUnitySimulationData
{
runId = runId.ToString(),
runExecutionId = runExecutionId,
runStatus = RunStatus.Succeeded.ToString()
};
SendPerceptionAnalyticsEvent(k_EventRunInUnitySimulation, data);
}
#endregion
}
}