633 lines
26 KiB
C#
633 lines
26 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Globalization;
|
|||
|
using Assets.UserReporting.Scripts.Plugin;
|
|||
|
using Unity.Cloud.UserReporting.Client;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.Analytics;
|
|||
|
using UnityEngine.Networking;
|
|||
|
using UnityEngine.Profiling;
|
|||
|
using UnityEngine.SceneManagement;
|
|||
|
|
|||
|
namespace Unity.Cloud.UserReporting.Plugin
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Represents the Unity user reporting platform.
|
|||
|
/// </summary>
|
|||
|
public class UnityUserReportingPlatform : IUserReportingPlatform, ILogListener
|
|||
|
{
|
|||
|
#region Nested Types
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents a log message.
|
|||
|
/// </summary>
|
|||
|
private struct LogMessage
|
|||
|
{
|
|||
|
#region Fields
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the log string.
|
|||
|
/// </summary>
|
|||
|
public string LogString;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the log type.
|
|||
|
/// </summary>
|
|||
|
public LogType LogType;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the stack trace.
|
|||
|
/// </summary>
|
|||
|
public string StackTrace;
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents a post operation.
|
|||
|
/// </summary>
|
|||
|
private class PostOperation
|
|||
|
{
|
|||
|
#region Properties
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the callback.
|
|||
|
/// </summary>
|
|||
|
public Action<bool, byte[]> Callback { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the progress callback.
|
|||
|
/// </summary>
|
|||
|
public Action<float, float> ProgressCallback { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the web request.
|
|||
|
/// </summary>
|
|||
|
public UnityWebRequest WebRequest { get; set; }
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents a profiler sampler.
|
|||
|
/// </summary>
|
|||
|
private struct ProfilerSampler
|
|||
|
{
|
|||
|
#region Fields
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the name.
|
|||
|
/// </summary>
|
|||
|
public string Name;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the recorder.
|
|||
|
/// </summary>
|
|||
|
public Recorder Recorder;
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Methods
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the value of the sampler.
|
|||
|
/// </summary>
|
|||
|
/// <returns>The value of the sampler.</returns>
|
|||
|
public double GetValue()
|
|||
|
{
|
|||
|
if (this.Recorder == null)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
return this.Recorder.elapsedNanoseconds / 1000000.0;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents a screenshot operation.
|
|||
|
/// </summary>
|
|||
|
private class ScreenshotOperation
|
|||
|
{
|
|||
|
#region Properties
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the callback.
|
|||
|
/// </summary>
|
|||
|
public Action<int, byte[]> Callback { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the frame number.
|
|||
|
/// </summary>
|
|||
|
public int FrameNumber { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the maximum height.
|
|||
|
/// </summary>
|
|||
|
public int MaximumHeight { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the maximum width.
|
|||
|
/// </summary>
|
|||
|
public int MaximumWidth { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the PNG data.
|
|||
|
/// </summary>
|
|||
|
public byte[] PngData { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the source.
|
|||
|
/// </summary>
|
|||
|
public object Source { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the stage.
|
|||
|
/// </summary>
|
|||
|
public ScreenshotStage Stage { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the texture.
|
|||
|
/// </summary>
|
|||
|
public Texture2D Texture { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the texture (resized).
|
|||
|
/// </summary>
|
|||
|
public Texture2D TextureResized { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the Unity frame.
|
|||
|
/// </summary>
|
|||
|
public int UnityFrame { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the wait frames.
|
|||
|
/// </summary>
|
|||
|
public int WaitFrames { get; set; }
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Represents a screenshot stage.
|
|||
|
/// </summary>
|
|||
|
private enum ScreenshotStage
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Render.
|
|||
|
/// </summary>
|
|||
|
Render = 0,
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Read pixels.
|
|||
|
/// </summary>
|
|||
|
ReadPixels = 1,
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets pixels.
|
|||
|
/// </summary>
|
|||
|
GetPixels = 2,
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Encode to PNG.
|
|||
|
/// </summary>
|
|||
|
EncodeToPNG = 3,
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Done.
|
|||
|
/// </summary>
|
|||
|
Done = 4
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Constructors
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a new instance of the <see cref="UnityUserReportingPlatform"/> class.
|
|||
|
/// </summary>
|
|||
|
public UnityUserReportingPlatform()
|
|||
|
{
|
|||
|
this.logMessages = new List<LogMessage>();
|
|||
|
this.postOperations = new List<PostOperation>();
|
|||
|
this.screenshotOperations = new List<ScreenshotOperation>();
|
|||
|
this.screenshotStopwatch = new Stopwatch();
|
|||
|
|
|||
|
// Recorders
|
|||
|
this.profilerSamplers = new List<ProfilerSampler>();
|
|||
|
Dictionary<string, string> samplerNames = this.GetSamplerNames();
|
|||
|
foreach (KeyValuePair<string, string> kvp in samplerNames)
|
|||
|
{
|
|||
|
Sampler sampler = Sampler.Get(kvp.Key);
|
|||
|
if (sampler.isValid)
|
|||
|
{
|
|||
|
Recorder recorder = sampler.GetRecorder();
|
|||
|
recorder.enabled = true;
|
|||
|
ProfilerSampler profilerSampler = new ProfilerSampler();
|
|||
|
profilerSampler.Name = kvp.Value;
|
|||
|
profilerSampler.Recorder = recorder;
|
|||
|
this.profilerSamplers.Add(profilerSampler);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Log Messages
|
|||
|
LogDispatcher.Register(this);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Fields
|
|||
|
|
|||
|
private List<LogMessage> logMessages;
|
|||
|
|
|||
|
private List<PostOperation> postOperations;
|
|||
|
|
|||
|
private List<ProfilerSampler> profilerSamplers;
|
|||
|
|
|||
|
private List<ScreenshotOperation> screenshotOperations;
|
|||
|
|
|||
|
private Stopwatch screenshotStopwatch;
|
|||
|
|
|||
|
private List<PostOperation> taskOperations;
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Methods
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public T DeserializeJson<T>(string json)
|
|||
|
{
|
|||
|
return SimpleJson.SimpleJson.DeserializeObject<T>(json);
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void OnEndOfFrame(UserReportingClient client)
|
|||
|
{
|
|||
|
// Screenshot Operations
|
|||
|
int screenshotOperationIndex = 0;
|
|||
|
while (screenshotOperationIndex < this.screenshotOperations.Count)
|
|||
|
{
|
|||
|
ScreenshotOperation screenshotOperation = this.screenshotOperations[screenshotOperationIndex];
|
|||
|
if (screenshotOperation.Stage == ScreenshotStage.Render && screenshotOperation.WaitFrames < 1)
|
|||
|
{
|
|||
|
Camera cameraSource = screenshotOperation.Source as Camera;
|
|||
|
if (cameraSource != null)
|
|||
|
{
|
|||
|
this.screenshotStopwatch.Reset();
|
|||
|
this.screenshotStopwatch.Start();
|
|||
|
RenderTexture renderTexture = new RenderTexture(screenshotOperation.MaximumWidth, screenshotOperation.MaximumHeight, 24);
|
|||
|
RenderTexture originalTargetTexture = cameraSource.targetTexture;
|
|||
|
cameraSource.targetTexture = renderTexture;
|
|||
|
cameraSource.Render();
|
|||
|
cameraSource.targetTexture = originalTargetTexture;
|
|||
|
this.screenshotStopwatch.Stop();
|
|||
|
client.SampleClientMetric("Screenshot.Render", this.screenshotStopwatch.ElapsedMilliseconds);
|
|||
|
screenshotOperation.Source = renderTexture;
|
|||
|
screenshotOperation.Stage = ScreenshotStage.ReadPixels;
|
|||
|
screenshotOperation.WaitFrames = 15;
|
|||
|
screenshotOperationIndex++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
screenshotOperation.Stage = ScreenshotStage.ReadPixels;
|
|||
|
}
|
|||
|
}
|
|||
|
if (screenshotOperation.Stage == ScreenshotStage.ReadPixels && screenshotOperation.WaitFrames < 1)
|
|||
|
{
|
|||
|
this.screenshotStopwatch.Reset();
|
|||
|
this.screenshotStopwatch.Start();
|
|||
|
RenderTexture renderTextureSource = screenshotOperation.Source as RenderTexture;
|
|||
|
if (renderTextureSource != null)
|
|||
|
{
|
|||
|
RenderTexture originalActiveTexture = RenderTexture.active;
|
|||
|
RenderTexture.active = renderTextureSource;
|
|||
|
screenshotOperation.Texture = new Texture2D(renderTextureSource.width, renderTextureSource.height, TextureFormat.ARGB32, true);
|
|||
|
screenshotOperation.Texture.ReadPixels(new Rect(0, 0, renderTextureSource.width, renderTextureSource.height), 0, 0);
|
|||
|
screenshotOperation.Texture.Apply();
|
|||
|
RenderTexture.active = originalActiveTexture;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
screenshotOperation.Texture = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, true);
|
|||
|
screenshotOperation.Texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
|
|||
|
screenshotOperation.Texture.Apply();
|
|||
|
}
|
|||
|
this.screenshotStopwatch.Stop();
|
|||
|
client.SampleClientMetric("Screenshot.ReadPixels", this.screenshotStopwatch.ElapsedMilliseconds);
|
|||
|
screenshotOperation.Stage = ScreenshotStage.GetPixels;
|
|||
|
screenshotOperation.WaitFrames = 15;
|
|||
|
screenshotOperationIndex++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (screenshotOperation.Stage == ScreenshotStage.GetPixels && screenshotOperation.WaitFrames < 1)
|
|||
|
{
|
|||
|
this.screenshotStopwatch.Reset();
|
|||
|
this.screenshotStopwatch.Start();
|
|||
|
int maximumWidth = screenshotOperation.MaximumWidth > 32 ? screenshotOperation.MaximumWidth : 32;
|
|||
|
int maximumHeight = screenshotOperation.MaximumHeight > 32 ? screenshotOperation.MaximumHeight : 32;
|
|||
|
int width = screenshotOperation.Texture.width;
|
|||
|
int height = screenshotOperation.Texture.height;
|
|||
|
int mipLevel = 0;
|
|||
|
while (width > maximumWidth || height > maximumHeight)
|
|||
|
{
|
|||
|
width /= 2;
|
|||
|
height /= 2;
|
|||
|
mipLevel++;
|
|||
|
}
|
|||
|
screenshotOperation.TextureResized = new Texture2D(width, height);
|
|||
|
screenshotOperation.TextureResized.SetPixels(screenshotOperation.Texture.GetPixels(mipLevel));
|
|||
|
screenshotOperation.TextureResized.Apply();
|
|||
|
this.screenshotStopwatch.Stop();
|
|||
|
client.SampleClientMetric("Screenshot.GetPixels", this.screenshotStopwatch.ElapsedMilliseconds);
|
|||
|
screenshotOperation.Stage = ScreenshotStage.EncodeToPNG;
|
|||
|
screenshotOperation.WaitFrames = 15;
|
|||
|
screenshotOperationIndex++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (screenshotOperation.Stage == ScreenshotStage.EncodeToPNG && screenshotOperation.WaitFrames < 1)
|
|||
|
{
|
|||
|
this.screenshotStopwatch.Reset();
|
|||
|
this.screenshotStopwatch.Start();
|
|||
|
screenshotOperation.PngData = screenshotOperation.TextureResized.EncodeToPNG();
|
|||
|
this.screenshotStopwatch.Stop();
|
|||
|
client.SampleClientMetric("Screenshot.EncodeToPNG", this.screenshotStopwatch.ElapsedMilliseconds);
|
|||
|
screenshotOperation.Stage = ScreenshotStage.Done;
|
|||
|
screenshotOperationIndex++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (screenshotOperation.Stage == ScreenshotStage.Done && screenshotOperation.WaitFrames < 1)
|
|||
|
{
|
|||
|
screenshotOperation.Callback(screenshotOperation.FrameNumber, screenshotOperation.PngData);
|
|||
|
UnityEngine.Object.Destroy(screenshotOperation.Texture);
|
|||
|
UnityEngine.Object.Destroy(screenshotOperation.TextureResized);
|
|||
|
this.screenshotOperations.Remove(screenshotOperation);
|
|||
|
}
|
|||
|
screenshotOperation.WaitFrames--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void Post(string endpoint, string contentType, byte[] content, Action<float, float> progressCallback, Action<bool, byte[]> callback)
|
|||
|
{
|
|||
|
UnityWebRequest webRequest = new UnityWebRequest(endpoint, "POST");
|
|||
|
webRequest.uploadHandler = new UploadHandlerRaw(content);
|
|||
|
webRequest.downloadHandler = new DownloadHandlerBuffer();
|
|||
|
webRequest.SetRequestHeader("Content-Type", contentType);
|
|||
|
webRequest.SendWebRequest();
|
|||
|
UnityUserReportingPlatform.PostOperation postOperation = new UnityUserReportingPlatform.PostOperation();
|
|||
|
postOperation.WebRequest = webRequest;
|
|||
|
postOperation.Callback = callback;
|
|||
|
postOperation.ProgressCallback = progressCallback;
|
|||
|
this.postOperations.Add(postOperation);
|
|||
|
}
|
|||
|
|
|||
|
public void ReceiveLogMessage(string logString, string stackTrace, LogType logType)
|
|||
|
{
|
|||
|
lock (this.logMessages)
|
|||
|
{
|
|||
|
LogMessage logMessage = new LogMessage();
|
|||
|
logMessage.LogString = logString;
|
|||
|
logMessage.StackTrace = stackTrace;
|
|||
|
logMessage.LogType = logType;
|
|||
|
this.logMessages.Add(logMessage);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void RunTask(Func<object> task, Action<object> callback)
|
|||
|
{
|
|||
|
callback(task());
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void SendAnalyticsEvent(string eventName, Dictionary<string, object> eventData)
|
|||
|
{
|
|||
|
Analytics.CustomEvent(eventName, eventData);
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public string SerializeJson(object instance)
|
|||
|
{
|
|||
|
return SimpleJson.SimpleJson.SerializeObject(instance);
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void TakeScreenshot(int frameNumber, int maximumWidth, int maximumHeight, object source, Action<int, byte[]> callback)
|
|||
|
{
|
|||
|
ScreenshotOperation screenshotOperation = new ScreenshotOperation();
|
|||
|
screenshotOperation.FrameNumber = frameNumber;
|
|||
|
screenshotOperation.MaximumWidth = maximumWidth;
|
|||
|
screenshotOperation.MaximumHeight = maximumHeight;
|
|||
|
screenshotOperation.Source = source;
|
|||
|
screenshotOperation.Callback = callback;
|
|||
|
screenshotOperation.UnityFrame = Time.frameCount;
|
|||
|
this.screenshotOperations.Add(screenshotOperation);
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public void Update(UserReportingClient client)
|
|||
|
{
|
|||
|
// Log Messages
|
|||
|
lock (this.logMessages)
|
|||
|
{
|
|||
|
foreach (LogMessage logMessage in this.logMessages)
|
|||
|
{
|
|||
|
UserReportEventLevel eventLevel = UserReportEventLevel.Info;
|
|||
|
if (logMessage.LogType == LogType.Warning)
|
|||
|
{
|
|||
|
eventLevel = UserReportEventLevel.Warning;
|
|||
|
}
|
|||
|
else if (logMessage.LogType == LogType.Error)
|
|||
|
{
|
|||
|
eventLevel = UserReportEventLevel.Error;
|
|||
|
}
|
|||
|
else if (logMessage.LogType == LogType.Exception)
|
|||
|
{
|
|||
|
eventLevel = UserReportEventLevel.Error;
|
|||
|
}
|
|||
|
else if (logMessage.LogType == LogType.Assert)
|
|||
|
{
|
|||
|
eventLevel = UserReportEventLevel.Error;
|
|||
|
}
|
|||
|
if (client.IsConnectedToLogger)
|
|||
|
{
|
|||
|
client.LogEvent(eventLevel, logMessage.LogString, logMessage.StackTrace);
|
|||
|
}
|
|||
|
}
|
|||
|
this.logMessages.Clear();
|
|||
|
}
|
|||
|
|
|||
|
// Metrics
|
|||
|
if (client.Configuration.MetricsGatheringMode == MetricsGatheringMode.Automatic)
|
|||
|
{
|
|||
|
// Sample Automatic Metrics
|
|||
|
this.SampleAutomaticMetrics(client);
|
|||
|
|
|||
|
// Profiler Samplers
|
|||
|
foreach (ProfilerSampler profilerSampler in this.profilerSamplers)
|
|||
|
{
|
|||
|
client.SampleMetric(profilerSampler.Name, profilerSampler.GetValue());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Post Operations
|
|||
|
int postOperationIndex = 0;
|
|||
|
while (postOperationIndex < this.postOperations.Count)
|
|||
|
{
|
|||
|
UnityUserReportingPlatform.PostOperation postOperation = this.postOperations[postOperationIndex];
|
|||
|
if (postOperation.WebRequest.isDone)
|
|||
|
{
|
|||
|
bool isError = postOperation.WebRequest.error != null && postOperation.WebRequest.responseCode != 200;
|
|||
|
if (isError)
|
|||
|
{
|
|||
|
string errorMessage = string.Format("UnityUserReportingPlatform.Post: {0} {1}", postOperation.WebRequest.responseCode, postOperation.WebRequest.error);
|
|||
|
UnityEngine.Debug.Log(errorMessage);
|
|||
|
client.LogEvent(UserReportEventLevel.Error, errorMessage);
|
|||
|
}
|
|||
|
postOperation.ProgressCallback(1, 1);
|
|||
|
postOperation.Callback(!isError, postOperation.WebRequest.downloadHandler.data);
|
|||
|
this.postOperations.Remove(postOperation);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
postOperation.ProgressCallback(postOperation.WebRequest.uploadProgress, postOperation.WebRequest.downloadProgress);
|
|||
|
postOperationIndex++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Virtual Methods
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public virtual IDictionary<string, string> GetDeviceMetadata()
|
|||
|
{
|
|||
|
Dictionary<string, string> deviceMetadata = new Dictionary<string, string>();
|
|||
|
|
|||
|
// Unity
|
|||
|
deviceMetadata.Add("BuildGUID", Application.buildGUID);
|
|||
|
deviceMetadata.Add("DeviceModel", SystemInfo.deviceModel);
|
|||
|
deviceMetadata.Add("DeviceType", SystemInfo.deviceType.ToString());
|
|||
|
deviceMetadata.Add("DeviceUniqueIdentifier", SystemInfo.deviceUniqueIdentifier);
|
|||
|
deviceMetadata.Add("DPI", Screen.dpi.ToString(CultureInfo.InvariantCulture));
|
|||
|
deviceMetadata.Add("GraphicsDeviceName", SystemInfo.graphicsDeviceName);
|
|||
|
deviceMetadata.Add("GraphicsDeviceType", SystemInfo.graphicsDeviceType.ToString());
|
|||
|
deviceMetadata.Add("GraphicsDeviceVendor", SystemInfo.graphicsDeviceVendor);
|
|||
|
deviceMetadata.Add("GraphicsDeviceVersion", SystemInfo.graphicsDeviceVersion);
|
|||
|
deviceMetadata.Add("GraphicsMemorySize", SystemInfo.graphicsMemorySize.ToString());
|
|||
|
deviceMetadata.Add("InstallerName", Application.installerName);
|
|||
|
deviceMetadata.Add("InstallMode", Application.installMode.ToString());
|
|||
|
deviceMetadata.Add("IsEditor", Application.isEditor.ToString());
|
|||
|
deviceMetadata.Add("IsFullScreen", Screen.fullScreen.ToString());
|
|||
|
deviceMetadata.Add("OperatingSystem", SystemInfo.operatingSystem);
|
|||
|
deviceMetadata.Add("OperatingSystemFamily", SystemInfo.operatingSystemFamily.ToString());
|
|||
|
deviceMetadata.Add("Orientation", Screen.orientation.ToString());
|
|||
|
deviceMetadata.Add("Platform", Application.platform.ToString());
|
|||
|
try
|
|||
|
{
|
|||
|
deviceMetadata.Add("QualityLevel", QualitySettings.names[QualitySettings.GetQualityLevel()]);
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
// Empty
|
|||
|
}
|
|||
|
deviceMetadata.Add("ResolutionWidth", Screen.currentResolution.width.ToString());
|
|||
|
deviceMetadata.Add("ResolutionHeight", Screen.currentResolution.height.ToString());
|
|||
|
deviceMetadata.Add("ResolutionRefreshRate", Screen.currentResolution.refreshRate.ToString());
|
|||
|
deviceMetadata.Add("SystemLanguage", Application.systemLanguage.ToString());
|
|||
|
deviceMetadata.Add("SystemMemorySize", SystemInfo.systemMemorySize.ToString());
|
|||
|
deviceMetadata.Add("TargetFrameRate", Application.targetFrameRate.ToString());
|
|||
|
deviceMetadata.Add("UnityVersion", Application.unityVersion);
|
|||
|
deviceMetadata.Add("Version", Application.version);
|
|||
|
|
|||
|
// Other
|
|||
|
deviceMetadata.Add("Source", "Unity");
|
|||
|
|
|||
|
// Type
|
|||
|
Type type = this.GetType();
|
|||
|
deviceMetadata.Add("IUserReportingPlatform", type.Name);
|
|||
|
|
|||
|
// Return
|
|||
|
return deviceMetadata;
|
|||
|
}
|
|||
|
|
|||
|
public virtual Dictionary<string, string> GetSamplerNames()
|
|||
|
{
|
|||
|
Dictionary<string, string> samplerNames = new Dictionary<string, string>();
|
|||
|
samplerNames.Add("AudioManager.FixedUpdate", "AudioManager.FixedUpdateInMilliseconds");
|
|||
|
samplerNames.Add("AudioManager.Update", "AudioManager.UpdateInMilliseconds");
|
|||
|
samplerNames.Add("LateBehaviourUpdate", "Behaviors.LateUpdateInMilliseconds");
|
|||
|
samplerNames.Add("BehaviourUpdate", "Behaviors.UpdateInMilliseconds");
|
|||
|
samplerNames.Add("Camera.Render", "Camera.RenderInMilliseconds");
|
|||
|
samplerNames.Add("Overhead", "Engine.OverheadInMilliseconds");
|
|||
|
samplerNames.Add("WaitForRenderJobs", "Engine.WaitForRenderJobsInMilliseconds");
|
|||
|
samplerNames.Add("WaitForTargetFPS", "Engine.WaitForTargetFPSInMilliseconds");
|
|||
|
samplerNames.Add("GUI.Repaint", "GUI.RepaintInMilliseconds");
|
|||
|
samplerNames.Add("Network.Update", "Network.UpdateInMilliseconds");
|
|||
|
samplerNames.Add("ParticleSystem.EndUpdateAll", "ParticleSystem.EndUpdateAllInMilliseconds");
|
|||
|
samplerNames.Add("ParticleSystem.Update", "ParticleSystem.UpdateInMilliseconds");
|
|||
|
samplerNames.Add("Physics.FetchResults", "Physics.FetchResultsInMilliseconds");
|
|||
|
samplerNames.Add("Physics.Processing", "Physics.ProcessingInMilliseconds");
|
|||
|
samplerNames.Add("Physics.ProcessReports", "Physics.ProcessReportsInMilliseconds");
|
|||
|
samplerNames.Add("Physics.Simulate", "Physics.SimulateInMilliseconds");
|
|||
|
samplerNames.Add("Physics.UpdateBodies", "Physics.UpdateBodiesInMilliseconds");
|
|||
|
samplerNames.Add("Physics.Interpolation", "Physics.InterpolationInMilliseconds");
|
|||
|
samplerNames.Add("Physics2D.DynamicUpdate", "Physics2D.DynamicUpdateInMilliseconds");
|
|||
|
samplerNames.Add("Physics2D.FixedUpdate", "Physics2D.FixedUpdateInMilliseconds");
|
|||
|
return samplerNames;
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc cref="IUserReportingPlatform"/>
|
|||
|
public virtual void ModifyUserReport(UserReport userReport)
|
|||
|
{
|
|||
|
// Active Scene
|
|||
|
Scene activeScene = SceneManager.GetActiveScene();
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("ActiveSceneName", activeScene.name));
|
|||
|
|
|||
|
// Main Camera
|
|||
|
Camera mainCamera = Camera.main;
|
|||
|
if (mainCamera != null)
|
|||
|
{
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("MainCameraName", mainCamera.name));
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("MainCameraPosition", mainCamera.transform.position.ToString()));
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("MainCameraForward", mainCamera.transform.forward.ToString()));
|
|||
|
|
|||
|
// Looking At
|
|||
|
RaycastHit hit;
|
|||
|
if (Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit))
|
|||
|
{
|
|||
|
GameObject lookingAt = hit.transform.gameObject;
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("LookingAt", hit.point.ToString()));
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("LookingAtGameObject", lookingAt.name));
|
|||
|
userReport.DeviceMetadata.Add(new UserReportNamedValue("LookingAtGameObjectPosition", lookingAt.transform.position.ToString()));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Samples automatic metrics.
|
|||
|
/// </summary>
|
|||
|
/// <param name="client">The client.</param>
|
|||
|
public virtual void SampleAutomaticMetrics(UserReportingClient client)
|
|||
|
{
|
|||
|
// Graphics
|
|||
|
client.SampleMetric("Graphics.FramesPerSecond", 1.0f / Time.deltaTime);
|
|||
|
|
|||
|
// Memory
|
|||
|
client.SampleMetric("Memory.MonoUsedSizeInBytes", Profiler.GetMonoUsedSizeLong());
|
|||
|
client.SampleMetric("Memory.TotalAllocatedMemoryInBytes", Profiler.GetTotalAllocatedMemoryLong());
|
|||
|
client.SampleMetric("Memory.TotalReservedMemoryInBytes", Profiler.GetTotalReservedMemoryLong());
|
|||
|
client.SampleMetric("Memory.TotalUnusedReservedMemoryInBytes", Profiler.GetTotalUnusedReservedMemoryLong());
|
|||
|
|
|||
|
// Battery
|
|||
|
client.SampleMetric("Battery.BatteryLevelInPercent", SystemInfo.batteryLevel);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|